1+ from behave import step , given , when , then , use_step_matcher
2+
3+ from utils import IfcFile
4+
5+ use_step_matcher ("parse" )
6+ @step (u"There must be exactly {number} {ifc_class} element" )
7+ @step (u"There must be exactly {number} {ifc_class} elements" )
8+ def step_impl (context , number , ifc_class ):
9+ num = len (IfcFile .get ().by_type (ifc_class ))
10+ assert num == int (number ), "Could not find {} elements of {}. Found {} element(s)." .format (number , ifc_class , num )
11+
12+ @given (u'a set of specific related elements' )
13+ def step_impl (context ):
14+ model = getattr (context , "model" , None )
15+ if not model :
16+ context .model = TableModel ()
17+ for row in context .table :
18+ context .model .add_row (row ["RelatedObjects" ], row ["RelatingGroup" ])
19+
20+ @given (u'a set of specific related elements taken from the file "{path_file}"' )
21+ def step_impl (context , path_file ):
22+ import csv
23+ model = getattr (context , "model" , None )
24+ if not model :
25+ context .model = TableModel ()
26+ with open (path_file , encoding = "utf-8" ) as csvfile :
27+ reader = csv .DictReader (csvfile )
28+ for row in reader :
29+ context .model .add_row (row ["RelatedObjects" ], row ["RelatingGroup" ])
30+
31+ @then (u'there must be exactly a number of {ifc_class} equals to the number of distinct row value' )
32+ def step_impl (context , ifc_class ):
33+ try :
34+ context .execute_steps (u"""
35+ then There must be exactly {number} {ifc_class} elements
36+ """ .format (ifc_class = ifc_class , number = context .model .get_count_distinct_values ()))
37+ except AssertionError as error :
38+ str_error = str (error )
39+ assert False , str_error [:str_error .find ("Traceback" )]
40+ assert True
41+
42+ @then (u'there is a relationship {ifc_class} with {left_attribute} and {right_attribute} between the two elements of each row' )
43+ def step_impl (context , ifc_class , left_attribute , right_attribute ):
44+ rows = context .model .rows
45+ elements = IfcFile .by_type (ifc_class )
46+ errors = []
47+ for key , value in rows .items ():
48+ found = False
49+ for element in elements :
50+ if any (x .Name == key for x in getattr (element , left_attribute ))\
51+ and getattr (element , right_attribute ).Name == value :
52+ found = True
53+ if not found :
54+ errors .append (f'The row ({ key } , { value } ) does not have the relationship.' )
55+ assert not errors , "Errors occured:\n {}" .format ("\n " .join (errors ))
56+
57+ use_step_matcher ("re" )
58+ @step ("all IfcGroup must be linked to a type in the list (?P<linked_ifc_classes>.*)" )
59+ def step_impl (context , linked_ifc_classes ):
60+ groups = IfcFile .by_type ("IfcGroup" )
61+ errors = []
62+ for group in groups :
63+ if not hasattr (group , "IsGroupedBy" ):
64+ errors .append (f'The element "{ group .Name } " has no "IsGroupedBy" attribute.' )
65+ else :
66+ for grouped_by in getattr (group , "IsGroupedBy" ):
67+ if not hasattr (grouped_by , "RelatedObjects" ):
68+ errors .append (f'The element "{ grouped_by .Name } " has no "RelatedObjects" attribute.' )
69+ else :
70+ for related_object in getattr (grouped_by , "RelatedObjects" ):
71+ found = False
72+ for linked_ifc_class in linked_ifc_classes .split ("," ):
73+ if (related_object .is_a (linked_ifc_class )):
74+ found = True
75+ if not found :
76+ errors .append (f'The element "{ related_object .Name } " does not have the right associated type.' )
77+ assert not errors , "Errors occured:\n {}" .format ("\n " .join (errors ))
78+
79+ @then (u'there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row key' )
80+ def step_impl (context , ifc_types , attribute_name ):
81+ check_if_element_exists_by_types_with_attribute_name (ifc_types , attribute_name , context .model .rows .keys ())
82+
83+ @then (u'there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row value' )
84+ def step_impl (context , ifc_types , attribute_name ):
85+ values = set (context .model .rows .values ())
86+ check_if_element_exists_by_types_with_attribute_name (ifc_types , attribute_name , values )
87+
88+ def check_if_element_exists_by_types_with_attribute_name (ifc_types , attribute_name , attribute_values ):
89+ errors = []
90+ # retrieve all elements of that type
91+ elements = IfcFile .by_types (ifc_types )
92+ # loop
93+ for attribute_value in attribute_values :
94+ found = False
95+ for element in elements :
96+ if hasattr (element , attribute_name ) and getattr (element , attribute_name ) == attribute_value :
97+ found = True
98+ if not found :
99+ errors .append (f'An element with { attribute_name } attribute "{ attribute_value } " was not found.' )
100+ assert not errors , "Errors occured:\n {}" .format ("\n " .join (errors ))
101+
102+ class TableModel (object ):
103+ """This class represents a table of data."""
104+ def __init__ (self ):
105+ self .rows = dict ()
106+
107+ def add_row (self , related , relating ):
108+ self .rows [related ] = relating
109+
110+ def get_count (self ):
111+ return len (self .rows )
112+
113+ def get_count_distinct_values (self ):
114+ return len (set (self .rows .values ()))
0 commit comments