diff --git a/src/blenderbim/pytest.ini b/src/blenderbim/pytest.ini index 61129246d0..0fc7461a14 100644 --- a/src/blenderbim/pytest.ini +++ b/src/blenderbim/pytest.ini @@ -4,6 +4,7 @@ markers = context geometry owner + project pset_template spatial style diff --git a/src/blenderbim/test/bim/bootstrap.py b/src/blenderbim/test/bim/bootstrap.py index f531cef13c..adc8f0492f 100644 --- a/src/blenderbim/test/bim/bootstrap.py +++ b/src/blenderbim/test/bim/bootstrap.py @@ -180,7 +180,7 @@ def the_object_name_does_not_exist(name): def the_object_name_is_an_ifc_class(name, ifc_class): ifc = an_ifc_file_exists() element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id) - assert element.is_a(ifc_class), f'Object "{name}" is a {element.is_a()}' + assert element.is_a(ifc_class), f'Object "{name}" is an {element.is_a()}' def the_object_name_is_not_an_ifc_element(name): diff --git a/src/blenderbim/test/bim/feature/owner.feature b/src/blenderbim/test/bim/feature/owner.feature index 8c204ce1f5..383edabd5f 100644 --- a/src/blenderbim/test/bim/feature/owner.feature +++ b/src/blenderbim/test/bim/feature/owner.feature @@ -1,6 +1,5 @@ @owner Feature: Owner - Covers ownership history, people, organisations, roles, and addresses. Scenario: Add person Given an empty IFC project diff --git a/src/blenderbim/test/bim/feature/project.feature b/src/blenderbim/test/bim/feature/project.feature new file mode 100644 index 0000000000..9d462fe1e1 --- /dev/null +++ b/src/blenderbim/test/bim/feature/project.feature @@ -0,0 +1,277 @@ +@project +Feature: Project + +Scenario: Create project + Given an empty Blender session + When I press "bim.create_project" + Then an IFC file exists + And the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/My Storey" is an "IfcBuildingStorey" + And the object "IfcProject/My Project" is in the collection "IfcProject/My Project" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" + +Scenario: Load project + Given an empty Blender session + When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc')" + Then an IFC file exists + And the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" + And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" + And the object "IfcSlab/Slab" is an "IfcSlab" + And the object "IfcWall/Wall" is an "IfcWall" + And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" + And the object "IfcBeam/Beam" is an "IfcBeam" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" + And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" + And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" + And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" + And "scene.BIMProjectProperties.is_loading" is "False" + +Scenario: Load project - advanced mode + Given an empty Blender session + When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + Then an IFC file exists + And "scene.BIMProjectProperties.is_loading" is "True" + And the object "IfcProject/My Project" does not exist + +Scenario: Load project elements - load all project elements + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "NONE" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" + And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" + And the object "IfcSlab/Slab" is an "IfcSlab" + And the object "IfcWall/Wall" is an "IfcWall" + And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" + And the object "IfcBeam/Beam" is an "IfcBeam" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" + And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" + And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" + And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" + And "scene.BIMProjectProperties.is_loading" is "False" + +Scenario: Load project elements - load objects filtered by decomposition + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "DECOMPOSITION" + Then "scene.BIMProjectProperties.filter_categories['IfcSite/My Site'].total_elements" is "0" + Then "scene.BIMProjectProperties.filter_categories['IfcBuilding/My Building'].total_elements" is "0" + Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Ground Floor'].total_elements" is "1" + Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].total_elements" is "2" + When I set "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].is_selected" to "True" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" + And the object "IfcWall/Wall" is an "IfcWall" + And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" + And the object "IfcBeam/Beam" is an "IfcBeam" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" + And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" + And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" + And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" + And the object "IfcBuildingStorey/Ground Floor" does not exist + And the object "IfcSlab/Slab" does not exist + +Scenario: Load project elements - load objects filtered by IFC class + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "IFC_CLASS" + Then "scene.BIMProjectProperties.filter_categories['IfcWall'].total_elements" is "1" + And "scene.BIMProjectProperties.filter_categories['IfcSlab'].total_elements" is "1" + And "scene.BIMProjectProperties.filter_categories['IfcElementAssembly'].total_elements" is "1" + And "scene.BIMProjectProperties.filter_categories['IfcBeam'].total_elements" is "1" + When I set "scene.BIMProjectProperties.filter_categories['IfcSlab'].is_selected" to "True" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" + And the object "IfcSlab/Slab" is an "IfcSlab" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcBuildingStorey/Level 1" does not exist + And the object "IfcWall/Wall" does not exist + +Scenario: Load project elements - load objects filtered by whitelist + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "WHITELIST" + And I set "scene.BIMProjectProperties.filter_query" to ".IfcSlab" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" + And the object "IfcSlab/Slab" is an "IfcSlab" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" + And the object "IfcBuildingStorey/Level 1" does not exist + And the object "IfcWall/Wall" does not exist + +Scenario: Load project elements - load objects filtered by blacklist + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "BLACKLIST" + And I set "scene.BIMProjectProperties.filter_query" to ".IfcSlab" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" + And the object "IfcWall/Wall" is an "IfcWall" + And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" + And the object "IfcBeam/Beam" is an "IfcBeam" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" + And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" + And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" + And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" + And the object "IfcBuildingStorey/Ground Floor" does not exist + And the object "IfcSlab/Slab" does not exist + +Scenario: Load project elements - load no objects due to filter + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "IFC_CLASS" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" does not exist + And the object "IfcBuilding/My Building" does not exist + And the object "IfcBuildingStorey/Ground Floor" does not exist + And the object "IfcBuildingStorey/Level 1" does not exist + And the object "IfcSlab/Slab" does not exist + And the object "IfcWall/Wall" does not exist + +Scenario: Load project elements - load with the decomposition collection mode + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/decomposition.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "NONE" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/My Storey" is an "IfcBuildingStorey" + And the object "IfcSpace/Space" is an "IfcSpace" + And the object "IfcElementAssembly/Assembly" is an "IfcElementAssembly" + And the object "IfcBeam/Beam" is an "IfcBeam" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" + And the object "IfcSpace/Space" is in the collection "IfcSpace/Space" + And the object "IfcElementAssembly/Assembly" is in the collection "IfcElementAssembly/Assembly" + And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Assembly" + And the collection "IfcSite/My Site" is in the collection "IfcProject/My Project" + And the collection "IfcBuilding/My Building" is in the collection "IfcSite/My Site" + And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcBuilding/My Building" + And the collection "IfcSpace/Space" is in the collection "IfcBuildingStorey/My Storey" + And the collection "IfcElementAssembly/Assembly" is in the collection "IfcSpace/Space" + And "scene.BIMProjectProperties.is_loading" is "False" + +Scenario: Load project elements - load with the spatial decomposition collection mode + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/decomposition.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.collection_mode" to "SPATIAL_DECOMPOSITION" + And I set "scene.BIMProjectProperties.filter_mode" to "NONE" + And I press "bim.load_project_elements" + Then the object "IfcProject/My Project" is an "IfcProject" + And the object "IfcSite/My Site" is an "IfcSite" + And the object "IfcBuilding/My Building" is an "IfcBuilding" + And the object "IfcBuildingStorey/My Storey" is an "IfcBuildingStorey" + And the object "IfcSpace/Space" is an "IfcSpace" + And the object "IfcElementAssembly/Assembly" is an "IfcElementAssembly" + And the object "IfcBeam/Beam" is an "IfcBeam" + And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" + And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" + And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" + And the object "IfcSpace/Space" is in the collection "IfcSpace/Space" + And the object "IfcElementAssembly/Assembly" is in the collection "IfcSpace/Space" + And the object "IfcBeam/Beam" is in the collection "IfcSpace/Space" + And the collection "IfcSite/My Site" is in the collection "IfcProject/My Project" + And the collection "IfcBuilding/My Building" is in the collection "IfcSite/My Site" + And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcBuilding/My Building" + And the collection "IfcSpace/Space" is in the collection "IfcBuildingStorey/My Storey" + And "scene.BIMProjectProperties.is_loading" is "False" + + +Scenario: Load project elements - manual offset of object placements + Given an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/manual-geolocation.ifc', is_advanced=True)" + When I set "scene.BIMProjectProperties.should_offset_model" to "True" + And I set "scene.BIMProjectProperties.model_offset_coordinates" to "-268388.5, -5774506.0, -21.899999618530273" + And I press "bim.load_project_elements" + Then the object "IfcPlate/1780 x 270 PRECAST WALL" is at "0,0,0" + +Scenario: Unload project + Given an empty Blender session + When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" + And I press "bim.unload_project" + Then an IFC file does not exist + And "scene.BIMProjectProperties.is_loading" is "False" + +Scenario: Link IFC + Given an empty IFC project + When I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" + Then "scene.BIMProjectProperties.links['{cwd}/test/files/basic.blend'].is_loaded" is "True" + And the object "IfcWall/Wall" exists + And the object "IfcSlab/Slab" exists + And the object "IfcElementAssembly/Empty" exists + And the object "IfcBeam/Beam" exists + And the object "IfcBuildingStorey/Ground Floor" exists + And the object "IfcBuildingStorey/Level 1" exists + +Scenario: Unload link + Given an empty Blender session + And I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" + When I press "bim.unload_link(filepath='{cwd}/test/files/basic.blend')" + Then "scene.BIMProjectProperties.links['{cwd}/test/files/basic.blend'].is_loaded" is "False" + And "scene.collection.children.get('IfcProject/My Project')" is "None" + +Scenario: Load link + Given an empty Blender session + And I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" + And I press "bim.unload_link(filepath='{cwd}/test/files/basic.blend')" + When I press "bim.load_link(filepath='{cwd}/test/files/basic.blend')" + Then "scene.BIMProjectProperties.links['{cwd}/test/files/basic.blend'].is_loaded" is "True" + And "scene.collection.children['IfcProject/My Project'].users" is "2" + +Scenario: Unlink IFC + Given an empty Blender session + And I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" + And I press "bim.unload_link(filepath='{cwd}/test/files/basic.blend')" + When I press "bim.unlink_ifc(filepath='{cwd}/test/files/basic.blend')" + Then "scene.BIMProjectProperties.links.get('{cwd}/test/files/basic.blend')" is "None" + And "scene.collection.children.get('IfcProject/My Project')" is "None" diff --git a/src/blenderbim/test/bim/module/project/__init__.py b/src/blenderbim/test/bim/module/project/__init__.py deleted file mode 100644 index fb33323db9..0000000000 --- a/src/blenderbim/test/bim/module/project/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# BlenderBIM Add-on - OpenBIM Blender Add-on -# Copyright (C) 2021 Dion Moult -# -# This file is part of BlenderBIM Add-on. -# -# BlenderBIM Add-on is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# BlenderBIM Add-on is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with BlenderBIM Add-on. If not, see . diff --git a/src/blenderbim/test/bim/module/project/test_operator.py b/src/blenderbim/test/bim/module/project/test_operator.py deleted file mode 100644 index 34bb377b08..0000000000 --- a/src/blenderbim/test/bim/module/project/test_operator.py +++ /dev/null @@ -1,344 +0,0 @@ -# BlenderBIM Add-on - OpenBIM Blender Add-on -# Copyright (C) 2021 Dion Moult -# -# This file is part of BlenderBIM Add-on. -# -# BlenderBIM Add-on is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# BlenderBIM Add-on is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with BlenderBIM Add-on. If not, see . - -import test.bim.bootstrap - - -class TestCreateProject(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_creating_a_project(self): - return """ - When I press "bim.create_project" - Then an IFC file exists - And the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/My Storey" is an "IfcBuildingStorey" - And the object "IfcProject/My Project" is in the collection "IfcProject/My Project" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" - """ - - -class TestLoadProject(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_loading_a_project(self): - return """ - When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc')" - Then an IFC file exists - And the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" - And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" - And the object "IfcSlab/Slab" is an "IfcSlab" - And the object "IfcWall/Wall" is an "IfcWall" - And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" - And the object "IfcBeam/Beam" is an "IfcBeam" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" - And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" - And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" - And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" - And "scene.BIMProjectProperties.is_loading" is "False" - """ - - @test.bim.bootstrap.scenario - def test_loading_a_project_in_advanced_mode(self): - return """ - When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - Then an IFC file exists - And "scene.BIMProjectProperties.is_loading" is "True" - And the object "IfcProject/My Project" does not exist - """ - - -class TestLoadProjectElements(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_loading_all_project_elements(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "NONE" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" - And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" - And the object "IfcSlab/Slab" is an "IfcSlab" - And the object "IfcWall/Wall" is an "IfcWall" - And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" - And the object "IfcBeam/Beam" is an "IfcBeam" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" - And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" - And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" - And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" - And "scene.BIMProjectProperties.is_loading" is "False" - """ - - @test.bim.bootstrap.scenario - def test_loading_objects_filtered_by_decomposition(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "DECOMPOSITION" - Then "scene.BIMProjectProperties.filter_categories['IfcSite/My Site'].total_elements" is "0" - Then "scene.BIMProjectProperties.filter_categories['IfcBuilding/My Building'].total_elements" is "0" - Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Ground Floor'].total_elements" is "1" - Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].total_elements" is "2" - When I set "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].is_selected" to "True" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" - And the object "IfcWall/Wall" is an "IfcWall" - And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" - And the object "IfcBeam/Beam" is an "IfcBeam" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" - And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" - And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" - And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" - And the object "IfcBuildingStorey/Ground Floor" does not exist - And the object "IfcSlab/Slab" does not exist - """ - - @test.bim.bootstrap.scenario - def test_loading_objects_filtered_by_ifc_class(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "IFC_CLASS" - Then "scene.BIMProjectProperties.filter_categories['IfcWall'].total_elements" is "1" - And "scene.BIMProjectProperties.filter_categories['IfcSlab'].total_elements" is "1" - And "scene.BIMProjectProperties.filter_categories['IfcElementAssembly'].total_elements" is "1" - And "scene.BIMProjectProperties.filter_categories['IfcBeam'].total_elements" is "1" - When I set "scene.BIMProjectProperties.filter_categories['IfcSlab'].is_selected" to "True" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" - And the object "IfcSlab/Slab" is an "IfcSlab" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcBuildingStorey/Level 1" does not exist - And the object "IfcWall/Wall" does not exist - """ - - @test.bim.bootstrap.scenario - def test_loading_objects_filtered_by_whitelist(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "WHITELIST" - And I set "scene.BIMProjectProperties.filter_query" to ".IfcSlab" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey" - And the object "IfcSlab/Slab" is an "IfcSlab" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor" - And the object "IfcBuildingStorey/Level 1" does not exist - And the object "IfcWall/Wall" does not exist - """ - - @test.bim.bootstrap.scenario - def test_loading_objects_filtered_by_blacklist(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "BLACKLIST" - And I set "scene.BIMProjectProperties.filter_query" to ".IfcSlab" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey" - And the object "IfcWall/Wall" is an "IfcWall" - And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly" - And the object "IfcBeam/Beam" is an "IfcBeam" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1" - And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1" - And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty" - And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty" - And the object "IfcBuildingStorey/Ground Floor" does not exist - And the object "IfcSlab/Slab" does not exist - """ - - @test.bim.bootstrap.scenario - def test_loading_no_objects_due_to_filter(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "IFC_CLASS" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" does not exist - And the object "IfcBuilding/My Building" does not exist - And the object "IfcBuildingStorey/Ground Floor" does not exist - And the object "IfcBuildingStorey/Level 1" does not exist - And the object "IfcSlab/Slab" does not exist - And the object "IfcWall/Wall" does not exist - """ - - @test.bim.bootstrap.scenario - def test_loading_with_the_decomposition_collection_mode(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/decomposition.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "NONE" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/My Storey" is an "IfcBuildingStorey" - And the object "IfcSpace/Space" is an "IfcSpace" - And the object "IfcElementAssembly/Assembly" is an "IfcElementAssembly" - And the object "IfcBeam/Beam" is an "IfcBeam" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" - And the object "IfcSpace/Space" is in the collection "IfcSpace/Space" - And the object "IfcElementAssembly/Assembly" is in the collection "IfcElementAssembly/Assembly" - And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Assembly" - And the collection "IfcSite/My Site" is in the collection "IfcProject/My Project" - And the collection "IfcBuilding/My Building" is in the collection "IfcSite/My Site" - And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcBuilding/My Building" - And the collection "IfcSpace/Space" is in the collection "IfcBuildingStorey/My Storey" - And the collection "IfcElementAssembly/Assembly" is in the collection "IfcSpace/Space" - And "scene.BIMProjectProperties.is_loading" is "False" - """ - - @test.bim.bootstrap.scenario - def test_loading_with_the_spatial_decomposition_collection_mode(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/decomposition.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.collection_mode" to "SPATIAL_DECOMPOSITION" - And I set "scene.BIMProjectProperties.filter_mode" to "NONE" - And I press "bim.load_project_elements" - Then the object "IfcProject/My Project" is an "IfcProject" - And the object "IfcSite/My Site" is an "IfcSite" - And the object "IfcBuilding/My Building" is an "IfcBuilding" - And the object "IfcBuildingStorey/My Storey" is an "IfcBuildingStorey" - And the object "IfcSpace/Space" is an "IfcSpace" - And the object "IfcElementAssembly/Assembly" is an "IfcElementAssembly" - And the object "IfcBeam/Beam" is an "IfcBeam" - And the object "IfcSite/My Site" is in the collection "IfcSite/My Site" - And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building" - And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" - And the object "IfcSpace/Space" is in the collection "IfcSpace/Space" - And the object "IfcElementAssembly/Assembly" is in the collection "IfcSpace/Space" - And the object "IfcBeam/Beam" is in the collection "IfcSpace/Space" - And the collection "IfcSite/My Site" is in the collection "IfcProject/My Project" - And the collection "IfcBuilding/My Building" is in the collection "IfcSite/My Site" - And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcBuilding/My Building" - And the collection "IfcSpace/Space" is in the collection "IfcBuildingStorey/My Storey" - And "scene.BIMProjectProperties.is_loading" is "False" - """ - - @test.bim.bootstrap.scenario - def test_manual_offset_of_object_placements(self): - return """ - Given I press "bim.load_project(filepath='{cwd}/test/files/manual-geolocation.ifc', is_advanced=True)" - When I set "scene.BIMProjectProperties.should_offset_model" to "True" - And I set "scene.BIMProjectProperties.model_offset_coordinates" to "-268388.5, -5774506.0, -21.899999618530273" - And I press "bim.load_project_elements" - Then the object "IfcPlate/1780 x 270 PRECAST WALL" is at "0,0,0" - """ - - -class TestUnloadProject(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_unloading_a_project(self): - return """ - When I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc', is_advanced=True)" - And I press "bim.unload_project" - Then an IFC file does not exist - And "scene.BIMProjectProperties.is_loading" is "False" - """ - - -class TestLinkIFC(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_linking_an_ifc(self): - return """ - Given I press "bim.create_project" - When I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" - Then "scene.BIMProjectProperties.links['{cwd}/test/files/basic.blend'].is_loaded" is "True" - And the object "IfcWall/Wall" exists - And the object "IfcSlab/Slab" exists - And the object "IfcElementAssembly/Empty" exists - And the object "IfcBeam/Beam" exists - And the object "IfcBuildingStorey/Ground Floor" exists - And the object "IfcBuildingStorey/Level 1" exists - """ - - -class TestUnloadLink(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_unloading_a_link(self): - return """ - When I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" - And I press "bim.unload_link(filepath='{cwd}/test/files/basic.blend')" - Then "scene.BIMProjectProperties.links['{cwd}/test/files/basic.blend'].is_loaded" is "False" - And "scene.collection.children.get('IfcProject/My Project')" is "None" - """ - - -class TestLoadLink(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_loading_a_link(self): - return """ - When I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" - And I press "bim.unload_link(filepath='{cwd}/test/files/basic.blend')" - And I press "bim.load_link(filepath='{cwd}/test/files/basic.blend')" - Then "scene.BIMProjectProperties.links['{cwd}/test/files/basic.blend'].is_loaded" is "True" - And "scene.collection.children['IfcProject/My Project'].users" is "2" - """ - - -class TestUnlinkIFC(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_unlinking_an_ifc(self): - return """ - When I press "bim.link_ifc(filepath='{cwd}/test/files/basic.blend')" - And I press "bim.unload_link(filepath='{cwd}/test/files/basic.blend')" - And I press "bim.unlink_ifc(filepath='{cwd}/test/files/basic.blend')" - Then "scene.BIMProjectProperties.links.get('{cwd}/test/files/basic.blend')" is "None" - And "scene.collection.children.get('IfcProject/My Project')" is "None" - """ diff --git a/src/blenderbim/test/bim/test_feature.py b/src/blenderbim/test/bim/test_feature.py index 8a599e82ed..a813176e07 100644 --- a/src/blenderbim/test/bim/test_feature.py +++ b/src/blenderbim/test/bim/test_feature.py @@ -22,6 +22,7 @@ import ifcopenshell import blenderbim.tool as tool from blenderbim.bim.ifc import IfcStore from pytest_bdd import scenarios, given, when, then, parsers +from mathutils import Vector scenarios("feature") @@ -34,6 +35,16 @@ def replace_variables(value): return value +@given("an empty Blender session") +def an_empty_ifc_project(): + IfcStore.purge() + bpy.ops.wm.read_homefile(app_template="") + if len(bpy.data.objects) > 0: + while bpy.data.objects: + bpy.data.objects.remove(bpy.data.objects[0]) + bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True) + + @given("an empty IFC project") def an_empty_ifc_project(): IfcStore.purge() @@ -133,7 +144,7 @@ def nothing_happens(): pass -@then('the object "{name}" exists') +@then(parsers.parse('the object "{name}" exists')) def the_object_name_exists(name) -> bpy.types.Object: obj = bpy.data.objects.get(name) if not obj: @@ -141,6 +152,13 @@ def the_object_name_exists(name) -> bpy.types.Object: return obj +@then("an IFC file does not exist") +def an_ifc_file_does_not_exist(): + ifc = IfcStore.get_file() + if ifc: + assert False, "An IFC is available" + + @then("an IFC file exists") def an_ifc_file_exists(): ifc = IfcStore.get_file() @@ -215,7 +233,7 @@ def the_object_name_is_not_a_void(name): def the_object_name_is_an_ifc_class(name, ifc_class): ifc = an_ifc_file_exists() element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id) - assert element.is_a(ifc_class), f'Object "{name}" is a {element.is_a()}' + assert element.is_a(ifc_class), f'Object "{name}" is an {element.is_a()}' @then(parsers.parse('the object "{name}" is not an IFC element')) @@ -256,6 +274,7 @@ def the_object_name_is_not_a_filling(name): @then(parsers.parse('"{prop}" is "{value}"')) def prop_is_value(prop, value): + prop = replace_variables(prop) value = replace_variables(value) is_value = False try: @@ -284,3 +303,16 @@ def the_object_name_is_in_the_collection_collection(name, collection): @then(parsers.parse('the collection "{name1}" is in the collection "{name2}"')) def the_collection_name1_is_in_the_collection_name2(name1, name2): assert bpy.data.collections.get(name2).children.get(name1) + + +@then(parsers.parse('the object "{name}" does not exist')) +def the_object_name_does_not_exist(name): + assert bpy.data.objects.get(name) is None, "Object exists" + + +@then(parsers.parse('the object "{name}" is at "{location}"')) +def the_object_name_is_at_location(name, location): + obj_location = the_object_name_exists(name).location + assert ( + obj_location - Vector([float(co) for co in location.split(",")]) + ).length < 0.1, f"Object is at {obj_location}"