From 85d76c084b5b73914bf387fd7ed185a559cfaa24 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 7 Dec 2021 12:59:50 +0100 Subject: [PATCH] bimstester: features, move element class attributes tests from examples to implemented steps --- .../bimtester/features/steps/all.py | 3 + .../steps/attributes_eleclasses/de.py | 31 ++ .../steps/attributes_eleclasses/en.py | 270 ++++++++++++++++++ .../examples/steps/attributes_eleclasses.py | 46 --- .../steps/attributes_eleclasses_de.py | 26 -- .../steps/attributes_eleclasses_methods.py | 140 --------- 6 files changed, 304 insertions(+), 212 deletions(-) create mode 100644 src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/de.py create mode 100644 src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/en.py delete mode 100644 src/ifcbimtester/examples/steps/attributes_eleclasses_de.py delete mode 100644 src/ifcbimtester/examples/steps/attributes_eleclasses_methods.py diff --git a/src/ifcbimtester/bimtester/features/steps/all.py b/src/ifcbimtester/bimtester/features/steps/all.py index d3b03a3159..d83f59fc09 100644 --- a/src/ifcbimtester/bimtester/features/steps/all.py +++ b/src/ifcbimtester/bimtester/features/steps/all.py @@ -4,6 +4,9 @@ from bimtester.features.steps.aggregation import en use_step_matcher("parse") from bimtester.features.steps.application import en +use_step_matcher("parse") +from bimtester.features.steps.attributes_eleclasses import en, de + use_step_matcher("parse") from bimtester.features.steps.attributes_psets import en, de diff --git a/src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/de.py b/src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/de.py new file mode 100644 index 0000000000..ddf3d91071 --- /dev/null +++ b/src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/de.py @@ -0,0 +1,31 @@ +from behave import step + + +@step('Es sind keine "{ifc_class}" Bauteile vorhanden') +def step_impl(context, ifc_class): + context.execute_steps(f'* There are no "{ifc_class}" elements') + + +@step('Aus folgendem Grund gibt es keine "{ifc_class}" Bauteile: {reason}') +def step_impl(context, ifc_class, reason): + context.execute_steps(f'* There are no "{ifc_class}" elements because "{reason}"') + + +@step('Alle "{ifc_class}" Bauteilklassenattribute haben einen Wert') +def step_impl(context, ifc_class): + context.execute_steps(f'* All "{ifc_class}" elements class attributes have a value') + + +@step('Bei allen "{ifc_class}" Bauteilen ist der Name angegeben') +def step_impl(context, ifc_class): + context.execute_steps(f'* All "{ifc_class}" elements have a name given') + + +@step('Bei allen "{ifc_class}" Bauteilen ist die Beschreibung angegeben') +def step_impl(context, ifc_class): + context.execute_steps(f'* All "{ifc_class}" elements have a description given') + + +@step('Es sind ausschliesslich "{ifc_classes}" Bauteile vorhanden') +def step_impl(context, ifc_classes): + context.execute_steps(f'* There are exclusively "{ifc_class}" elements only') diff --git a/src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/en.py b/src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/en.py new file mode 100644 index 0000000000..9f7244daa8 --- /dev/null +++ b/src/ifcbimtester/bimtester/features/steps/attributes_eleclasses/en.py @@ -0,0 +1,270 @@ +import ifcopenshell.util.element as eleutils + +from behave import step + +from bimtester import util +from bimtester.ifc import IfcStore +from bimtester.lang import _ + + +@step('There are no "{ifc_class}" elements') +def step_impl(context, ifc_class): + no_eleclass( + context, + ifc_class + ) + + +@step('There are no "{ifc_class}" elements because "{reason}"') +def step_impl(context, ifc_class, reason): + no_eleclass( + context, + ifc_class + ) + + +@step('All "{ifc_class}" elements class attributes have a value') +def step_impl(context, ifc_class): + eleclass_have_class_attributes_with_a_value( + context, + ifc_class + ) + + +@step('All "{ifc_class}" elements have a name given') +def step_impl(context, ifc_class): + eleclass_has_name_with_a_value( + context, + ifc_class + ) + + +@step('All "{ifc_class}" elements have a description given') +def step_impl(context, ifc_class): + eleclass_has_description_with_a_value( + context, + ifc_class + ) + + +@step('There are exclusively "{ifc_class}" elements only') +def step_impl(context, ifc_classes): + only_eleclasses( + context, + ifc_classes + ) + + +@step('All "{ifc_class}" elements have a name matching the pattern "{pattern}"') +def step_impl(context, ifc_class, pattern): + import re + + elements = IfcStore.file.by_type(ifc_class) + for element in elements: + if not re.search(pattern, element.Name): + assert False + + +@step('There is an "{ifc_class}" element with a "{attribute_name}" attribute with a value of "{attribute_value}"') +def step_impl(context, ifc_class, attribute_name, attribute_value): + elements = IfcStore.file.by_type(ifc_class) + for element in elements: + if hasattr(element, attribute_name) and getattr(element, attribute_name) == attribute_value: + return + assert False + + +# ************************************************************************************************ +# helper +def only_eleclasses( + context, ifc_classes +): + + context.falseelems = [] + context.falseguids = [] + + # get the list of ifc_classes + target_ifc_classes = ifc_classes.replace(" ","").split(",") + # ToDo test if they exist in ifc standard, should be possible with ifcos + + all_elements = IfcStore.file.by_type("IfcBuildingElement") + context.elemcount = len(all_elements) + + false_elements = [] + for elem in all_elements: + if elem.is_a() not in target_ifc_classes: + context.falseelems.append(str(elem)) + context.falseguids.append(elem.GlobalId) + + out_falseelems = "\n" + for e in context.falseelems: + out_falseelems += e + "\n" + context.falsecount = len(context.falseelems) + # print(context.falsecount) + # print(context.elemcount) + + if context.falsecount == 0: + return # Test OK, thus we can not use the assert_elements method ... really ? + elif context.falsecount == context.elemcount: + assert False, ( + _("All {elemcount} false elements in the file are {ifc_classes}.") + .format( + elemcount=context.elemcount, + ifc_classes=ifc_classes + ) + ) + elif context.falsecount > 0 and context.falsecount < context.elemcount: + assert False, ( + _("{falsecount} of {elemcount} false_elements are {ifc_classes} false_elements: {falseelems}") + .format( + falsecount=context.falsecount, + elemcount=context.elemcount, + ifc_classes=ifc_classes, + falseelems=out_falseelems, + ) + ) + else: + assert False, _("Error in falsecount, something went wrong.") + + +def no_eleclass( + context, ifc_class +): + + context.falseelems = [] + context.falseguids = [] + + elements = IfcStore.file.by_type(ifc_class) + context.elemcount = len(IfcStore.file.by_type("IfcBuildingElement")) + for elem in elements: + context.falseelems.append(str(elem)) + context.falseguids.append(elem.GlobalId) + + out_falseelems = "\n" + for e in context.falseelems: + out_falseelems += e + "\n" + context.falsecount = len(context.falseelems) + # print(context.falsecount) + # print(context.elemcount) + + if context.falsecount == 0: + return # Test OK, thus we can not use the assert_elements method ... really ? + elif context.falsecount == context.elemcount: + assert False, ( + _("All {elemcount} elements in the file are {ifc_class}.") + .format( + elemcount=context.elemcount, + ifc_class=ifc_class + ) + ) + elif context.falsecount > 0 and context.falsecount < context.elemcount: + assert False, ( + _("{falsecount} of {elemcount} elements are {ifc_class} elements: {falseelems}") + .format( + falsecount=context.falsecount, + elemcount=context.elemcount, + ifc_class=ifc_class, + falseelems=out_falseelems, + ) + ) + else: + assert False, _("Error in falsecount, something went wrong.") + + +def eleclass_have_class_attributes_with_a_value( + context, ifc_class +): + + from ifcopenshell.ifcopenshell_wrapper import schema_by_name + # schema = schema_by_name("IFC2X3") + schema = schema_by_name(IfcStore.file.schema) + class_attributes = [] + for cl_attrib in schema.declaration_by_name(ifc_class).all_attributes(): + class_attributes.append(cl_attrib.name()) + # print(class_attributes) + + context.falseelems = [] + context.falseguids = [] + context.falseprops = {} + + elements = IfcStore.file.by_type(ifc_class) + for elem in elements: + failed_attribs = [] + elem_failed = False + for cl_attrib in class_attributes: + attrib_value = getattr(elem, cl_attrib) + if not attrib_value: + elem_failed = True + failed_attribs.append(cl_attrib) + # print(attrib_value) + if elem_failed is True: + context.falseelems.append(str(elem)) + context.falseguids.append(elem.GlobalId) + context.falseprops[elem.id()] = failed_attribs + + context.elemcount = len(elements) + context.falsecount = len(context.falseelems) + util.assert_elements( + ifc_class, + context.elemcount, + context.falsecount, + context.falseelems, + message_all_falseelems=_("For all {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value."), + message_some_falseelems=_("For the following {falsecount} out of {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value: {falseelems}"), + message_no_elems=_("There are no {ifc_class} elements in the IFC file."), + parameter=failed_attribs + ) + + +def eleclass_has_name_with_a_value(context, ifc_class): + + context.falseelems = [] + context.falseguids = [] + + elements = IfcStore.file.by_type(ifc_class) + for elem in elements: + # print(elem.Name) + if not elem.Name: + context.falseelems.append(str(elem)) + context.falseguids.append(elem.GlobalId) + + context.elemcount = len(elements) + context.falsecount = len(context.falseelems) + util.assert_elements( + ifc_class, + context.elemcount, + context.falsecount, + context.falseelems, + message_all_falseelems=_("The name of all {elemcount} {elemcount} elements is not set."), + message_some_falseelems=_("The name of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"), + message_no_elems=_("There are no {ifc_class} elements in the IFC file."), + ) + + +def eleclass_has_description_with_a_value( + context, ifc_class +): + + context.falseelems = [] + context.falseguids = [] + + elements = IfcStore.file.by_type(ifc_class) + for elem in elements: + # print(elem.Description) + if not elem.Description: + context.falseelems.append(str(elem)) + context.falseguids.append(elem.GlobalId) + + context.elemcount = len(elements) + context.falsecount = len(context.falseelems) + util.assert_elements( + ifc_class, + context.elemcount, + context.falsecount, + context.falseelems, + message_all_falseelems=_("The description of all {elemcount} {elemcount} elements is not set."), + message_some_falseelems=_("The description of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"), + message_no_elems=_("There are no {ifc_class} elements in the IFC file."), + ) + + diff --git a/src/ifcbimtester/examples/steps/attributes_eleclasses.py b/src/ifcbimtester/examples/steps/attributes_eleclasses.py index d587773166..249f55efb6 100644 --- a/src/ifcbimtester/examples/steps/attributes_eleclasses.py +++ b/src/ifcbimtester/examples/steps/attributes_eleclasses.py @@ -1,54 +1,8 @@ from behave import step -import attributes_eleclasses_methods as aem -from utils import assert_elements from utils import IfcFile -@step("There are no {ifc_class} elements") -def step_impl(context, ifc_class): - aem.no_eleclass(context, ifc_class) - - -@step("There are no {ifc_class} elements because {reason}") -def step_impl(context, ifc_class, reason): - aem.no_eleclass(context, ifc_class) - - -@step("All {ifc_class} elements class attributes have a value") -def step_impl(context, ifc_class): - aem.eleclass_have_class_attributes_with_a_value(context, ifc_class) - - -@step("All {ifc_class} elements have a name given") -def step_impl(context, ifc_class): - aem.eleclass_has_name_with_a_value(context, ifc_class) - - -@step("All {ifc_class} elements have a description given") -def step_impl(context, ifc_class): - aem.eleclass_has_description_with_a_value(context, ifc_class) - - -@step('all {ifc_class} elements have a name matching the pattern "{pattern}"') -def step_impl(context, ifc_class, pattern): - import re - - elements = IfcFile.get().by_type(ifc_class) - for element in elements: - if not re.search(pattern, element.Name): - assert False - - -@step('there is an {ifc_class} element with a {attribute_name} attribute with a value of "{attribute_value}"') -def step_impl(context, ifc_class, attribute_name, attribute_value): - elements = IfcFile.get().by_type(ifc_class) - for element in elements: - if hasattr(element, attribute_name) and getattr(element, attribute_name) == attribute_value: - return - assert False - - use_step_matcher("re") diff --git a/src/ifcbimtester/examples/steps/attributes_eleclasses_de.py b/src/ifcbimtester/examples/steps/attributes_eleclasses_de.py deleted file mode 100644 index 9cf25d075a..0000000000 --- a/src/ifcbimtester/examples/steps/attributes_eleclasses_de.py +++ /dev/null @@ -1,26 +0,0 @@ -from behave import step - - -@step("Es sind keine {ifc_class} Bauteile vorhanden") -def step_impl(context, ifc_class): - context.execute_steps(f"* There are no {ifc_class} elements") - - -@step("Aus folgendem Grund gibt es keine {ifc_class} Bauteile: {reason}") -def step_impl(context, ifc_class, reason): - context.execute_steps(f"* There are no {ifc_class} elements because {reason}") - - -@step("Alle {ifc_class} Bauteilklassenattribute haben einen Wert") -def step_impl(context, ifc_class): - context.execute_steps(f"* All {ifc_class} elements class attributes have a value") - - -@step("Bei allen {ifc_class} Bauteile ist der Name angegeben") -def step_impl(context, ifc_class): - context.execute_steps(f"* All {ifc_class} elements have a name given") - - -@step("Bei allen {ifc_class} Bauteile ist die Beschreibung angegeben") -def step_impl(context, ifc_class): - context.execute_steps(f"* All {ifc_class} elements have a description given") diff --git a/src/ifcbimtester/examples/steps/attributes_eleclasses_methods.py b/src/ifcbimtester/examples/steps/attributes_eleclasses_methods.py deleted file mode 100644 index 018d01f0a8..0000000000 --- a/src/ifcbimtester/examples/steps/attributes_eleclasses_methods.py +++ /dev/null @@ -1,140 +0,0 @@ -import gettext # noqa - -from utils import assert_elements -from utils import IfcFile - - -def no_eleclass( - context, ifc_class -): - - context.falseelems = [] - context.falseguids = [] - - elements = IfcFile.get().by_type(ifc_class) - for elem in elements: - context.falseelems.append(str(elem)) - context.falseguids.append(elem.GlobalId) - - context.elemcount = len(elements) - context.falsecount = len(context.falseelems) - - if context.elemcount == 0 and context.falsecount == 0: - return # Test OK, thus we can not use the assert_elements method - elif context.falsecount == context.elemcount: - assert False, ( - _("All {elemcount} elements in the file are {ifc_class}.") - .format( - elemcount=context.elemcount, - ifc_class=ifc_class - ) - ) - elif context.falsecount > 0 and fcontext.alsecount < context.elemcount: - assert False, ( - _("{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}") - .format( - falsecount=context.falsecount, - elemcount=context.elemcount, - ifc_class=ifc_class, - falseelems=context.falseelems, - ) - ) - else: - assert False, _("Error in falsecount, something went wrong.") - - -def eleclass_have_class_attributes_with_a_value( - context, ifc_class -): - - from ifcopenshell.ifcopenshell_wrapper import schema_by_name - # schema = schema_by_name("IFC2X3") - schema = schema_by_name(IfcFile.get().schema) - class_attributes = [] - for cl_attrib in schema.declaration_by_name(ifc_class).all_attributes(): - class_attributes.append(cl_attrib.name()) - # print(class_attributes) - - context.falseelems = [] - context.falseguids = [] - context.falseprops = {} - - elements = IfcFile.get().by_type(ifc_class) - for elem in elements: - failed_attribs = [] - elem_failed = False - for cl_attrib in class_attributes: - attrib_value = getattr(elem, cl_attrib) - if not attrib_value: - elem_failed = True - failed_attribs.append(cl_attrib) - # print(attrib_value) - if elem_failed is True: - context.falseelems.append(str(elem)) - context.falseguids.append(elem.GlobalId) - context.falseprops[elem.id()] = failed_attribs - - context.elemcount = len(elements) - context.falsecount = len(context.falseelems) - assert_elements( - ifc_class, - context.elemcount, - context.falsecount, - context.falseelems, - message_all_falseelems=_("For all {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value."), - message_some_falseelems=_("For the following {falsecount} out of {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value: {falseelems}"), - message_no_elems=_("There are no {ifc_class} elements in the IFC file."), - parameter=failed_attribs - ) - - -def eleclass_has_name_with_a_value(context, ifc_class): - - context.falseelems = [] - context.falseguids = [] - - elements = IfcFile.get().by_type(ifc_class) - for elem in elements: - # print(elem.Name) - if not elem.Name: - context.falseelems.append(str(elem)) - context.falseguids.append(elem.GlobalId) - - context.elemcount = len(elements) - context.falsecount = len(context.falseelems) - assert_elements( - ifc_class, - context.elemcount, - context.falsecount, - context.falseelems, - message_all_falseelems=_("The name of all {elemcount} {elemcount} elements is not set."), - message_some_falseelems=_("The name of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"), - message_no_elems=_("There are no {ifc_class} elements in the IFC file."), - ) - - -def eleclass_has_description_with_a_value( - context, ifc_class -): - - context.falseelems = [] - context.falseguids = [] - - elements = IfcFile.get().by_type(ifc_class) - for elem in elements: - # print(elem.Description) - if not elem.Description: - context.falseelems.append(str(elem)) - context.falseguids.append(elem.GlobalId) - - context.elemcount = len(elements) - context.falsecount = len(context.falseelems) - assert_elements( - ifc_class, - context.elemcount, - context.falsecount, - context.falseelems, - message_all_falseelems=_("The description of all {elemcount} {elemcount} elements is not set."), - message_some_falseelems=_("The description of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"), - message_no_elems=_("There are no {ifc_class} elements in the IFC file."), - )