From 24eac8ccdd174d3f5ade62795b088709266d5fbc Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 29 Sep 2021 16:17:41 +1000 Subject: [PATCH] Just realised pytest-bdd existed. Migrating over. See #1711. --- src/blenderbim/setup_pytest.py | 8 +- src/blenderbim/test/bim/feature/owner.feature | 167 +++++++++++ .../test/bim/module/owner/__init__.py | 17 -- .../test/bim/module/owner/test_operator.py | 279 ------------------ src/blenderbim/test/bim/test_feature.py | 83 ++++++ 5 files changed, 253 insertions(+), 301 deletions(-) create mode 100644 src/blenderbim/test/bim/feature/owner.feature delete mode 100644 src/blenderbim/test/bim/module/owner/__init__.py delete mode 100644 src/blenderbim/test/bim/module/owner/test_operator.py create mode 100644 src/blenderbim/test/bim/test_feature.py diff --git a/src/blenderbim/setup_pytest.py b/src/blenderbim/setup_pytest.py index 0dba1f5264..8a722bc015 100644 --- a/src/blenderbim/setup_pytest.py +++ b/src/blenderbim/setup_pytest.py @@ -20,10 +20,8 @@ import subprocess import sys py_exec = str(sys.executable) -# Ensure pip is installed subprocess.call([py_exec, "-m", "ensurepip", "--user"]) -# Update pip subprocess.call([py_exec, "-m", "pip", "install", "--upgrade", "pip"]) -# Install packages -subprocess.call([py_exec, "-m", "pip", "install", f"--target={py_exec[:-14]}" + "lib", "pytest"]) -subprocess.call([py_exec, "-m", "pip", "install", f"--target={py_exec[:-14]}" + "lib", "pytest-blender"]) +subprocess.call([py_exec, "-m", "pip", "install", "pytest"]) +subprocess.call([py_exec, "-m", "pip", "install", "pytest-blender"]) +subprocess.call([py_exec, "-m", "pip", "install", "pytest-bdd"]) diff --git a/src/blenderbim/test/bim/feature/owner.feature b/src/blenderbim/test/bim/feature/owner.feature new file mode 100644 index 0000000000..c5183bb730 --- /dev/null +++ b/src/blenderbim/test/bim/feature/owner.feature @@ -0,0 +1,167 @@ +Feature: Owner + Covers ownership history, people, organisations, roles, and addresses. + +Scenario: Add person + Given an empty IFC project + When I press "bim.add_person" + Then nothing happens + +Scenario: Remove person + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.remove_person(person={person})" + Then nothing happens + +Scenario: Add person attribute + Given an empty IFC project + When I press "bim.add_person" + And I press "bim.add_person_attribute(name='MiddleNames')" + And I press "bim.add_person_attribute(name='PrefixTitles')" + And I press "bim.add_person_attribute(name='SuffixTitles')" + Then nothing happens + +Scenario: Remove person attribute + Given an empty IFC project + When I press "bim.add_person" + And I press "bim.add_person_attribute(name='MiddleNames')" + And I press "bim.remove_person_attribute(name='MiddleNames', id=0)" + And I press "bim.add_person_attribute(name='PrefixTitles')" + And I press "bim.remove_person_attribute(name='PrefixTitles', id=0)" + And I press "bim.add_person_attribute(name='SuffixTitles')" + And I press "bim.remove_person_attribute(name='SuffixTitles', id=0)" + Then nothing happens + +Scenario: Enable editing person + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.enable_editing_person(person={person})" + Then "scene.BIMOwnerProperties.active_person_id" is "{person}" + +Scenario: Disable editing person + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.enable_editing_person(person={person})" + And I press "bim.disable_editing_person" + Then "scene.BIMOwnerProperties.active_person_id" is "0" + +Scenario: Edit person + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.enable_editing_person(person={person})" + And I press "bim.edit_person" + Then "scene.BIMOwnerProperties.active_person_id" is "0" + +Scenario: Add role + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_role(parent={person})" + Then nothing happens + +Scenario: Remove role + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_role(parent={person})" + And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" + And I press "bim.remove_role(role={role})" + Then nothing happens + +Scenario: Enable editing role + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_role(parent={person})" + And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" + And I press "bim.enable_editing_role(role={role})" + Then nothing happens + +Scenario: Disable editing role + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_role(parent={person})" + And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" + And I press "bim.enable_editing_role(role={role})" + And I press "bim.disable_editing_role()" + Then nothing happens + +Scenario: Edit role + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_role(parent={person})" + And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" + And I press "bim.enable_editing_role(role={role})" + And I press "bim.edit_role()" + Then nothing happens + +Scenario: Add address + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + Then nothing happens + +Scenario: Add address attribute + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" + And I press "bim.enable_editing_address(address={address})" + And I press "bim.add_address_attribute(name='AddressLines')" + Then nothing happens + +Scenario: Remove address attribute + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" + And I press "bim.enable_editing_address(address={address})" + And I press "bim.add_address_attribute(name='AddressLines')" + And I press "bim.remove_address_attribute(name='AddressLines', id=0)" + Then nothing happens + +Scenario: Remove address + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" + And I press "bim.remove_address(address={address})" + Then nothing happens + +Scenario: Enable editing address + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" + And I press "bim.enable_editing_address(address={address})" + Then nothing happens + +Scenario: Disable editing address + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" + And I press "bim.enable_editing_address(address={address})" + And I press "bim.disable_editing_address()" + Then nothing happens + +Scenario: Edit address + Given an empty IFC project + When I press "bim.add_person" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" + And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" + And I press "bim.enable_editing_address(address={address})" + And I press "bim.edit_address()" + Then nothing happens diff --git a/src/blenderbim/test/bim/module/owner/__init__.py b/src/blenderbim/test/bim/module/owner/__init__.py deleted file mode 100644 index fb33323db9..0000000000 --- a/src/blenderbim/test/bim/module/owner/__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/owner/test_operator.py b/src/blenderbim/test/bim/module/owner/test_operator.py deleted file mode 100644 index d75eab8854..0000000000 --- a/src/blenderbim/test/bim/module/owner/test_operator.py +++ /dev/null @@ -1,279 +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 TestAddPerson(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - When I press "bim.add_person" - Then nothing interesting happens - """ - - -class TestRemovePerson(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - When I press "bim.remove_person(person={person})" - Then nothing interesting happens - """ - - -class TestAddPersonAttribute(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - When I press "bim.add_person_attribute(name='MiddleNames')" - And I press "bim.add_person_attribute(name='PrefixTitles')" - And I press "bim.add_person_attribute(name='SuffixTitles')" - Then nothing interesting happens - """ - - -class TestRemovePersonAttribute(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - When I press "bim.add_person_attribute(name='MiddleNames')" - And I press "bim.remove_person_attribute(name='MiddleNames', id=0)" - And I press "bim.add_person_attribute(name='PrefixTitles')" - And I press "bim.remove_person_attribute(name='PrefixTitles', id=0)" - And I press "bim.add_person_attribute(name='SuffixTitles')" - And I press "bim.remove_person_attribute(name='SuffixTitles', id=0)" - Then nothing interesting happens - """ - - -class TestEnableEditingPerson(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - When I press "bim.enable_editing_person(person={person})" - Then "scene.BIMOwnerProperties.active_person_id" is "{person}" - """ - - -class TestDisableEditingPerson(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.enable_editing_person(person={person})" - When I press "bim.disable_editing_person" - Then "scene.BIMOwnerProperties.active_person_id" is "0" - """ - - -class TestEditPerson(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.enable_editing_person(person={person})" - When I press "bim.edit_person" - Then "scene.BIMOwnerProperties.active_person_id" is "0" - """ - - -class TestAddRole(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - When I press "bim.add_role(parent={person})" - Then nothing interesting happens - """ - - -class TestRemoveRole(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_role(parent={person})" - And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" - When I press "bim.remove_role(role={role})" - Then nothing interesting happens - """ - - -class TestEnableEditingRole(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_role(parent={person})" - And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" - When I press "bim.enable_editing_role(role={role})" - Then nothing interesting happens - """ - - -class TestDisableEditingRole(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_role(parent={person})" - And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" - And I press "bim.enable_editing_role(role={role})" - When I press "bim.disable_editing_role()" - Then nothing interesting happens - """ - - -class TestEditRole(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_role(parent={person})" - And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()" - And I press "bim.enable_editing_role(role={role})" - When I press "bim.edit_role()" - Then nothing interesting happens - """ - - -class TestAddAddress(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - When I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - Then nothing interesting happens - """ - - -class TestAddAddressAttribute(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" - And I press "bim.enable_editing_address(address={address})" - When I press "bim.add_address_attribute(name='AddressLines')" - Then nothing interesting happens - """ - - -class TestRemoveAddressAttribute(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" - And I press "bim.enable_editing_address(address={address})" - And I press "bim.add_address_attribute(name='AddressLines')" - When I press "bim.remove_address_attribute(name='AddressLines', id=0)" - Then nothing interesting happens - """ - - -class TestRemoveAddress(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" - When I press "bim.remove_address(address={address})" - Then nothing interesting happens - """ - - -class TestEnableEditingAddress(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" - When I press "bim.enable_editing_address(address={address})" - Then nothing interesting happens - """ - - -class TestDisableEditingAddress(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" - And I press "bim.enable_editing_address(address={address})" - When I press "bim.disable_editing_address()" - Then nothing interesting happens - """ - - -class TestEditAddress(test.bim.bootstrap.NewFile): - @test.bim.bootstrap.scenario - def test_run(self): - return """ - Given an empty IFC project - And I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" - And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')" - And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()" - And I press "bim.enable_editing_address(address={address})" - When I press "bim.edit_address()" - Then nothing interesting happens - """ diff --git a/src/blenderbim/test/bim/test_feature.py b/src/blenderbim/test/bim/test_feature.py new file mode 100644 index 0000000000..944bc51110 --- /dev/null +++ b/src/blenderbim/test/bim/test_feature.py @@ -0,0 +1,83 @@ +# 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 os +import bpy +from blenderbim.bim.ifc import IfcStore +from pytest_bdd import scenarios, given, when, then, parsers + +scenarios("feature") + +variables = {"cwd": os.getcwd(), "ifc": "IfcStore.get_file()"} + + +def replace_variables(value): + for key, new_value in variables.items(): + value = value.replace("{" + key + "}", str(new_value)) + return value + + +@given("an empty IFC project") +def an_empty_ifc_project(): + IfcStore.purge() + bpy.ops.wm.read_homefile(app_template="") + 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) + bpy.ops.bim.create_project() + + +@when(parsers.parse('I press "{operator}"')) +def i_press_operator(operator): + operator = replace_variables(operator) + if "(" in operator: + exec(f"bpy.ops.{operator}") + else: + exec(f"bpy.ops.{operator}()") + + +@when(parsers.parse('the variable "{key}" is "{value}"')) +def the_variable_key_is_value(key, value): + variables[key] = eval(replace_variables(value)) + + +@then("nothing happens") +def nothing_happens(): + pass + + +@then(parsers.parse('"{prop}" is "{value}"')) +def prop_is_value(prop, value): + value = replace_variables(value) + is_value = False + try: + exec(f'assert bpy.context.{prop} == "{value}"') + is_value = True + except: + try: + exec(f"assert bpy.context.{prop} == {value}") + is_value = True + except: + try: + exec(f"assert list(bpy.context.{prop}) == {value}") + is_value = True + except: + pass + if not is_value: + actual_value = eval(f"bpy.context.{prop}") + assert False, f"Value is {actual_value}"