diff --git a/src/_balder/collector.py b/src/_balder/collector.py index 993689fb..feefd475 100644 --- a/src/_balder/collector.py +++ b/src/_balder/collector.py @@ -675,14 +675,19 @@ def _exchange_strings_with_objects(self): This method exchanges all strings (that can be used in decorators) are exchanged with their real objects. It secures this for all :class:`Device` and :class:`VDevice` references inside the session. """ + all_scenarios = [scenario for scenario in self.all_collected_scenarios_with_mro + if issubclass(scenario, Scenario) and scenario != Scenario] + all_setups = [setup for setup in self.all_collected_setups_with_mro + if issubclass(setup, Setup) and setup != Setup] + # resolve connection Device strings (for all devices that are directly defined inside the scenario/setup) - for cur_scenario_or_setup in self.all_scenarios_and_setups: + for cur_scenario_or_setup in all_scenarios + all_setups: cur_scenario_or_setup_controller = NormalScenarioSetupController.get_for(cur_scenario_or_setup) for cur_device in cur_scenario_or_setup_controller.get_all_inner_device_classes(): DeviceController.get_for(cur_device).resolve_connection_device_strings() # resolve connection VDevice strings (for all absolute devices of this scenario/setup) - for cur_scenario_or_setup in self.all_scenarios_and_setups: + for cur_scenario_or_setup in all_scenarios + all_setups: cur_scenario_or_setup_controller = NormalScenarioSetupController.get_for(cur_scenario_or_setup) for cur_device in cur_scenario_or_setup_controller.get_all_abs_inner_device_classes(): DeviceController.get_for(cur_device).resolve_mapped_vdevice_strings() diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/__init__.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/__init__.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/balderglob.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/balderglob.py new file mode 100644 index 00000000..232be40a --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/balderglob.py @@ -0,0 +1,150 @@ +from typing import Literal, Union, List +from datetime import datetime + +import pathlib +import balder +import argparse +import logging +from multiprocessing import Queue +from .lib.utils import FixtureReturn + +logger = logging.getLogger(__file__) + + +class MyTestException(Exception): + pass + + +class RuntimeObserver: + """This is a helper object, that will be used from this test environment to observe the execution order""" + queue: Union[Queue, None] = None + + error_throwing = {} + + @staticmethod + def add_entry(file: Union[str, pathlib.Path], cls: object, meth: callable, msg: str, + category: Literal["fixture", "testcase", "feature"] = None, + part: Literal["construction", "teardown"] = None): + """ + adds a new entry and sends it over the queue + + :param file: the full filepath where the log will be generated + + :param cls: the class object, the entry is generated in + + :param meth: the method name, the entry is generated in + + :param msg: the message that should be inserted into the entry + + :param category: optional string of the category the entry is from + + :param part: optional string of the sub part the entry is from + """ + if hasattr(meth, 'fn'): + meth = meth.fn + new_dataset = { + "timestamp": datetime.now(), "file": file, "cls": "" if cls is None else cls.__name__, + "meth": meth.__name__, "msg": msg, "category": category, "part": part + } + logger.info("{:22} | {:20} | {:30} | {:12} | {:15} | {}".format( + pathlib.Path(file).parts[-1], "" if cls is None else cls.__name__, "" if meth is None else meth.__name__, + "" if category is None else category, "" if part is None else part, "" if msg is None else msg)) + + RuntimeObserver.queue.put(new_dataset) + # check if we have to throw the error + error_throwing_required = len(RuntimeObserver.error_throwing) > 0 + for cur_key in RuntimeObserver.error_throwing.keys(): + new_dataset_val = new_dataset[cur_key] + if callable(new_dataset_val): + new_dataset_val = new_dataset_val.__name__ + if new_dataset_val != RuntimeObserver.error_throwing[cur_key]: + error_throwing_required = False + break + if error_throwing_required: + raise MyTestException(f'raise test triggered exception for `{str(RuntimeObserver.error_throwing)}`') + + +class MyErrorThrowingPlugin(balder.BalderPlugin): + """ + This is a plugin that reads the values from console arguments and sets these values into the + :class:`RuntimeObserver`. The static method `RuntimeObserver.add_entry` will automatically throw an exception on the + given position. + """ + + def addoption(self, argument_parser: argparse.ArgumentParser): + argument_parser.add_argument('--test-error-file', help='the file id, the error should be thrown in') + argument_parser.add_argument('--test-error-cls', help='the class id, the error should be thrown in') + argument_parser.add_argument('--test-error-meth', help='the meth id, the error should be thrown in') + argument_parser.add_argument('--test-error-part', help='the part (`construct` or `teardown`), the error should ' + 'be thrown in - only for fixtures') + + def modify_collected_pyfiles(self, pyfiles: List[pathlib.Path]) -> List[pathlib.Path]: + # use this method to set the values + RuntimeObserver.error_throwing = {} + if self.balder_session.parsed_args.test_error_file: + path = pathlib.Path(self.balder_session.parsed_args.test_error_file) + if not path.is_absolute(): + path = str(self.balder_session.working_dir.joinpath(path)) + RuntimeObserver.error_throwing['file'] = path + if self.balder_session.parsed_args.test_error_cls: + RuntimeObserver.error_throwing['cls'] = self.balder_session.parsed_args.test_error_cls + if self.balder_session.parsed_args.test_error_meth: + RuntimeObserver.error_throwing['meth'] = self.balder_session.parsed_args.test_error_meth + if self.balder_session.parsed_args.test_error_part: + RuntimeObserver.error_throwing['part'] = self.balder_session.parsed_args.test_error_part + return pyfiles + + +@balder.fixture(level="session") +def balderglob_fixture_session(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_session, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_SESSION + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_session, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="setup") +def balderglob_fixture_setup(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_setup, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_SETUP + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_setup, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="scenario") +def balderglob_fixture_scenario(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_scenario, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_SCENARIO + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_scenario, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="variation") +def balderglob_fixture_variation(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_variation, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_VARIATION + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_variation, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="testcase") +def balderglob_fixture_testcase(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_testcase, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_TESTCASE + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_testcase, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/__init__.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/connections.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/connections.py new file mode 100644 index 00000000..cf1e8b61 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/connections.py @@ -0,0 +1,11 @@ +import balder + + +@balder.insert_into_tree() +class AConnection(balder.Connection): + pass + + +@balder.insert_into_tree() +class BConnection(balder.Connection): + pass diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/features.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/features.py new file mode 100644 index 00000000..3dd9bd9b --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/features.py @@ -0,0 +1,46 @@ +import balder +from ..balderglob import RuntimeObserver + + +class FeatureI(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureI, FeatureI.do_something, "enter `FeatureI.do_something`", category="feature") + + +class FeatureIOverwritten(FeatureI): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureIOverwritten, FeatureIOverwritten.do_something, "enter `FeatureIChild.do_something`", + category="feature") + + +class FeatureII(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureII, FeatureII.do_something, "enter `FeatureII.do_something`", category="feature") + + +class NewlyDefinedFeature(balder.Feature): + """this feature will be instantiated in `ScenarioAChild` (and not in `ScenarioAParent`)""" + def do_something(self): + RuntimeObserver.add_entry( + __file__, NewlyDefinedFeature, NewlyDefinedFeature.do_something, "enter `NewlyDefinedFeature.do_something`", + category="feature") + + +class FeatureIII(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureIII, FeatureIII.do_something, "enter `FeatureIII.do_something`", category="feature") + + +class FeatureIV(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureIV, FeatureIV.do_something, "enter `FeatureIV.do_something`", category="feature") diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/utils.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/utils.py new file mode 100644 index 00000000..fe4559af --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/lib/utils.py @@ -0,0 +1,22 @@ + + +class FixtureReturn: + """helper const class for return values""" + BALDERGLOB_SESSION = "balderglob_session_fixt" + BALDERGLOB_SETUP = "balderglob_setup_fixt" + BALDERGLOB_SCENARIO = "balderglob_scenario_fixt" + BALDERGLOB_VARIATION = "balderglob_variation_fixt" + BALDERGLOB_TESTCASE = "balderglob_testcase_fixt" + + SETUP_SESSION = "setup_session_fixt" + SETUP_SETUP = "setup_setup_fixt" + SETUP_SCENARIO = "setup_scenario_fixt" + SETUP_VARIATION = "setup_variation_fixt" + SETUP_TESTCASE = "setup_testcase_fixt" + + SCENARIO_SESSION = "scenario_session_fixt" + SCENARIO_SETUP = "scenario_setup_fixt" + SCENARIO_SCENARIO = "scenario_scenario_fixt" + SCENARIO_VARIATION = "scenario_variation_fixt" + SCENARIO_TESTCASE = "scenario_testcase_fixt" + diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/__init__.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a_child.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a_child.py new file mode 100644 index 00000000..b1f8a00e --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a_child.py @@ -0,0 +1,122 @@ +import balder +import logging +from ..lib.features import FeatureIOverwritten, FeatureII, NewlyDefinedFeature +from ..lib.connections import AConnection +from ..balderglob import RuntimeObserver +from .scenario_a_parent import ScenarioAParent + +logger = logging.getLogger(__file__) + + +class ScenarioAChild(ScenarioAParent): + """This is the CHILD scenario of category A""" + + class ScenarioDevice1(ScenarioAParent.ScenarioDevice1): + i = FeatureIOverwritten() + + @balder.connect(ScenarioDevice1, over_connection=AConnection) + class ScenarioDevice2(ScenarioAParent.ScenarioDevice2): + ii = FeatureII() + new = NewlyDefinedFeature() + + def test_a_1(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.test_a_1, category="testcase", + msg=f"execute Test `{ScenarioAChild.test_a_1.__qualname__}`") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + def test_a_2(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.test_a_2, category="testcase", + msg=f"execute Test `{ScenarioAChild.test_a_2.__qualname__}`") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + @balder.fixture(level="session") + def fixture_session(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_session, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_session, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + @balder.fixture(level="setup") + def fixture_setup(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_setup, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_setup, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + @balder.fixture(level="scenario") + def fixture_scenario(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_scenario, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_scenario, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + @balder.fixture(level="variation") + def fixture_variation(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_variation, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_variation, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + @balder.fixture(level="testcase") + def fixture_testcase(self): + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_testcase, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAChild, ScenarioAChild.fixture_testcase, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + self.ScenarioDevice2.new.do_something() diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a_parent.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a_parent.py new file mode 100644 index 00000000..a7c97e50 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a_parent.py @@ -0,0 +1,109 @@ +import balder +import logging +from ..lib.features import FeatureI, FeatureII +from ..lib.connections import AConnection +from ..balderglob import RuntimeObserver + +logger = logging.getLogger(__file__) + + +class ScenarioAParent(balder.Scenario): + """This is the PARENT scenario of category A""" + + class ScenarioDevice1(balder.Device): + i = FeatureI() + + @balder.connect('ScenarioDevice1', over_connection=AConnection) + class ScenarioDevice2(balder.Device): + ii = FeatureII() + # the newly-feature is not defined here + + def test_a_1(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.test_a_1, category="testcase", + msg=f"execute Test `{ScenarioAParent.test_a_1.__qualname__}`") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + def test_a_2(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.test_a_2, category="testcase", + msg=f"execute Test `{ScenarioAParent.test_a_2.__qualname__}`") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="session") + def fixture_session(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_session, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_session, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="setup") + def fixture_setup(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_setup, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_setup, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="scenario") + def fixture_scenario(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_scenario, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_scenario, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="variation") + def fixture_variation(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_variation, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_variation, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="testcase") + def fixture_testcase(self): + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_testcase, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioAParent, ScenarioAParent.fixture_testcase, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/__init__.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_a.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_a.py new file mode 100644 index 00000000..a19cd19a --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_a.py @@ -0,0 +1,109 @@ +import balder +import logging +from .setup_features import SetupFeatureI, SetupFeatureII, NewlySetupFeature +from ..lib.connections import AConnection +from ..balderglob import RuntimeObserver + +logger = logging.getLogger(__name__) + + +class SetupA(balder.Setup): + """This is a setup of category A (exactly the same as scenario A)""" + + class SetupDevice1(balder.Device): + s_i = SetupFeatureI() + + @balder.connect(SetupDevice1, over_connection=AConnection) + class SetupDevice2(balder.Device): + s_ii = SetupFeatureII() + s_new = NewlySetupFeature() + + @balder.fixture(level="session") + def fixture_session(self): + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_session, category="fixture", part="construction", + msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_session, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + @balder.fixture(level="setup") + def fixture_setup(self): + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_setup, category="fixture", part="construction", + msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_setup, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + @balder.fixture(level="scenario") + def fixture_scenario(self): + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_scenario, category="fixture", part="construction", + msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_scenario, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + @balder.fixture(level="variation") + def fixture_variation(self): + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_variation, category="fixture", part="construction", + msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_variation, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + @balder.fixture(level="testcase") + def fixture_testcase(self): + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_testcase, category="fixture", part="construction", + msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupA, SetupA.fixture_testcase, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.s_new.do_something() diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/__init__.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/__init__.py new file mode 100644 index 00000000..8925ccf6 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/__init__.py @@ -0,0 +1,9 @@ +from .feature_i import SetupFeatureI +from .feature_ii import SetupFeatureII +from .newly_setup_feature import NewlySetupFeature + +__all__ = [ + "SetupFeatureI", + "SetupFeatureII", + "NewlySetupFeature" +] diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i.py new file mode 100644 index 00000000..a40b0a04 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i.py @@ -0,0 +1,10 @@ +from ...lib.features import FeatureIOverwritten +from ...balderglob import RuntimeObserver + + +class SetupFeatureI(FeatureIOverwritten): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, SetupFeatureI, SetupFeatureI.do_something, "enter `SetupFeatureI.do_something`", + category="feature") diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_ii.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_ii.py new file mode 100644 index 00000000..a38e27c7 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_ii.py @@ -0,0 +1,10 @@ +from ...lib.features import FeatureII +from ...balderglob import RuntimeObserver + + +class SetupFeatureII(FeatureII): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, SetupFeatureII, SetupFeatureII.do_something, "enter `SetupFeatureII.do_something`", + category="feature") diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/newly_setup_feature.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/newly_setup_feature.py new file mode 100644 index 00000000..75fb6776 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/newly_setup_feature.py @@ -0,0 +1,10 @@ +from ...lib.features import NewlyDefinedFeature +from ...balderglob import RuntimeObserver + + +class NewlySetupFeature(NewlyDefinedFeature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, NewlySetupFeature, NewlySetupFeature.do_something, "enter `NewlySetupFeature.do_something`", + category="feature") diff --git a/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/test_0_scenario_correctly_using_str_dev_ref_in_parent.py b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/test_0_scenario_correctly_using_str_dev_ref_in_parent.py new file mode 100644 index 00000000..7c75bf04 --- /dev/null +++ b/tests/scenario_inheritance/test_0_scenario_correctly_using_str_dev_ref_in_parent/test_0_scenario_correctly_using_str_dev_ref_in_parent.py @@ -0,0 +1,227 @@ +from _balder.testresult import ResultState +from _balder.balder_session import BalderSession + +from tests.test_utilities.base_0_envtester_class import Base0EnvtesterClass + + +class Test0ScenarioCorrectlyUsingStrDevRefInParent(Base0EnvtesterClass): + """ + This testcase executes the basic envtester environment but uses an inherited scenario `ScenarioAChild`. Within this + scenario we define an additional feature class that was not known in parent scenario `ScenarioAParent`. In addition + to that, the environment overwrites an existing feature within the `ScenarioAChild`-Device that is a child class of + the overwritten one. + Compared to `test_0_scenario_correctly_overwrite_and_add_feature`, this environment uses string references within + the parent scenario `ScenarioAParent`. + + The test secures that it can be executed correctly and without an error. + """ + + @property + def expected_data(self) -> tuple: + return ( + # FIXTURE-CONSTRUCTION: balderglob_fixture_session + {"file": "balderglob.py", "meth": "balderglob_fixture_session", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_session + {"cls": "SetupA", "meth": "fixture_session", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioAChild.fixture_session + {"cls": "ScenarioAChild", "meth": "fixture_session", "part": "construction"}, + {"cls": "FeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlyDefinedFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: balderglob_fixture_setup + {"file": "balderglob.py", "meth": "balderglob_fixture_setup", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_setup + {"cls": "SetupA", "meth": "fixture_setup", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioAChild.fixture_setup + {"cls": "ScenarioAChild", "meth": "fixture_setup", "part": "construction"}, + {"cls": "FeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlyDefinedFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: balderglob_fixture_scenario + {"file": "balderglob.py", "meth": "balderglob_fixture_scenario", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_scenario + {"cls": "SetupA", "meth": "fixture_scenario", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioAChild.fixture_scenario + {"cls": "ScenarioAChild", "meth": "fixture_scenario", "part": "construction"}, + {"cls": "FeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlyDefinedFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: balderglob_fixture_variation + {"file": "balderglob.py", "meth": "balderglob_fixture_variation", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_variation + {"cls": "SetupA", "meth": "fixture_variation", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioAChild.fixture_variation + {"cls": "ScenarioAChild", "meth": "fixture_variation", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + [ + ( + # FIXTURE-CONSTRUCTION: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_testcase + {"cls": "SetupA", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioAChild.fixture_testcase + {"cls": "ScenarioAChild", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # TESTCASE: ScenarioAChild.test_a_1 + {"cls": "ScenarioAChild", "meth": "test_a_1"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: ScenarioAChild.fixture_testcase + {"cls": "ScenarioAChild", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_testcase + {"cls": "SetupA", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "teardown"}, + ), + ( + # FIXTURE-CONSTRUCTION: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_testcase + {"cls": "SetupA", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioAChild.fixture_testcase + {"cls": "ScenarioAChild", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # TESTCASE: ScenarioAChild.test_a_2 + {"cls": "ScenarioAChild", "meth": "test_a_2"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: ScenarioAChild.fixture_testcase + {"cls": "ScenarioAChild", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_testcase + {"cls": "SetupA", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "teardown"}, + ), + ], + # FIXTURE-TEARDOWN: ScenarioAChild.fixture_variation + {"cls": "ScenarioAChild", "meth": "fixture_variation", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_variation + {"cls": "SetupA", "meth": "fixture_variation", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_variation + {"file": "balderglob.py", "meth": "balderglob_fixture_variation", "part": "teardown"}, + # FIXTURE-TEARDOWN: ScenarioAChild.fixture_scenario + {"cls": "ScenarioAChild", "meth": "fixture_scenario", "part": "teardown"}, + {"cls": "FeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlyDefinedFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_scenario + {"cls": "SetupA", "meth": "fixture_scenario", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_scenario + {"file": "balderglob.py", "meth": "balderglob_fixture_scenario", "part": "teardown"}, + # FIXTURE-TEARDOWN: ScenarioAChild.fixture_setup + {"cls": "ScenarioAChild", "meth": "fixture_setup", "part": "teardown"}, + {"cls": "FeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlyDefinedFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_setup + {"cls": "SetupA", "meth": "fixture_setup", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_setup + {"file": "balderglob.py", "meth": "balderglob_fixture_setup", "part": "teardown"}, + # FIXTURE-TEARDOWN: ScenarioAChild.fixture_session + {"cls": "ScenarioAChild", "meth": "fixture_session", "part": "teardown"}, + {"cls": "FeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlyDefinedFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_session + {"cls": "SetupA", "meth": "fixture_session", "part": "teardown"}, + {"cls": "SetupFeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "NewlySetupFeature", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_session + {"file": "balderglob.py", "meth": "balderglob_fixture_session", "part": "teardown"}, + ) + + @staticmethod + def validate_finished_session(session: BalderSession): + + # check result states everywhere (have to be SUCCESS everywhere + assert session.executor_tree.executor_result == ResultState.SUCCESS, \ + "test session does not terminates with success" + + assert session.executor_tree.construct_result.result == ResultState.SUCCESS, \ + "global executor tree construct part does not set ResultState.SUCCESS" + assert session.executor_tree.body_result.result == ResultState.SUCCESS, \ + "global executor tree body part does not set ResultState.SUCCESS" + assert session.executor_tree.teardown_result.result == ResultState.SUCCESS, \ + "global executor tree teardown part does not set ResultState.SUCCESS" + for cur_setup_executor in session.executor_tree.get_setup_executors(): + assert cur_setup_executor.executor_result == ResultState.SUCCESS, \ + "the setup executor does not have result SUCCESS" + + assert cur_setup_executor.construct_result.result == ResultState.SUCCESS + assert cur_setup_executor.body_result.result == ResultState.SUCCESS + assert cur_setup_executor.teardown_result.result == ResultState.SUCCESS + + for cur_scenario_executor in cur_setup_executor.get_scenario_executors(): + assert cur_scenario_executor.executor_result == ResultState.SUCCESS, \ + "the scenario executor does not have result SUCCESS" + + assert cur_scenario_executor.construct_result.result == ResultState.SUCCESS + assert cur_scenario_executor.body_result.result == ResultState.SUCCESS + assert cur_scenario_executor.teardown_result.result == ResultState.SUCCESS + + for cur_variation_executor in cur_scenario_executor.get_variation_executors(): + assert cur_variation_executor.executor_result == ResultState.SUCCESS, \ + "the variation executor does not have result SUCCESS" + + assert cur_variation_executor.construct_result.result == ResultState.SUCCESS + assert cur_variation_executor.body_result.result == ResultState.SUCCESS + assert cur_variation_executor.teardown_result.result == ResultState.SUCCESS + + for cur_testcase_executor in cur_variation_executor.get_testcase_executors(): + assert cur_testcase_executor.executor_result == ResultState.SUCCESS, \ + "the testcase executor does not have result SUCCESS" + + assert cur_testcase_executor.construct_result.result == ResultState.SUCCESS + assert cur_testcase_executor.body_result.result == ResultState.SUCCESS + assert cur_testcase_executor.teardown_result.result == ResultState.SUCCESS diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/__init__.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/__init__.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/balderglob.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/balderglob.py new file mode 100644 index 00000000..232be40a --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/balderglob.py @@ -0,0 +1,150 @@ +from typing import Literal, Union, List +from datetime import datetime + +import pathlib +import balder +import argparse +import logging +from multiprocessing import Queue +from .lib.utils import FixtureReturn + +logger = logging.getLogger(__file__) + + +class MyTestException(Exception): + pass + + +class RuntimeObserver: + """This is a helper object, that will be used from this test environment to observe the execution order""" + queue: Union[Queue, None] = None + + error_throwing = {} + + @staticmethod + def add_entry(file: Union[str, pathlib.Path], cls: object, meth: callable, msg: str, + category: Literal["fixture", "testcase", "feature"] = None, + part: Literal["construction", "teardown"] = None): + """ + adds a new entry and sends it over the queue + + :param file: the full filepath where the log will be generated + + :param cls: the class object, the entry is generated in + + :param meth: the method name, the entry is generated in + + :param msg: the message that should be inserted into the entry + + :param category: optional string of the category the entry is from + + :param part: optional string of the sub part the entry is from + """ + if hasattr(meth, 'fn'): + meth = meth.fn + new_dataset = { + "timestamp": datetime.now(), "file": file, "cls": "" if cls is None else cls.__name__, + "meth": meth.__name__, "msg": msg, "category": category, "part": part + } + logger.info("{:22} | {:20} | {:30} | {:12} | {:15} | {}".format( + pathlib.Path(file).parts[-1], "" if cls is None else cls.__name__, "" if meth is None else meth.__name__, + "" if category is None else category, "" if part is None else part, "" if msg is None else msg)) + + RuntimeObserver.queue.put(new_dataset) + # check if we have to throw the error + error_throwing_required = len(RuntimeObserver.error_throwing) > 0 + for cur_key in RuntimeObserver.error_throwing.keys(): + new_dataset_val = new_dataset[cur_key] + if callable(new_dataset_val): + new_dataset_val = new_dataset_val.__name__ + if new_dataset_val != RuntimeObserver.error_throwing[cur_key]: + error_throwing_required = False + break + if error_throwing_required: + raise MyTestException(f'raise test triggered exception for `{str(RuntimeObserver.error_throwing)}`') + + +class MyErrorThrowingPlugin(balder.BalderPlugin): + """ + This is a plugin that reads the values from console arguments and sets these values into the + :class:`RuntimeObserver`. The static method `RuntimeObserver.add_entry` will automatically throw an exception on the + given position. + """ + + def addoption(self, argument_parser: argparse.ArgumentParser): + argument_parser.add_argument('--test-error-file', help='the file id, the error should be thrown in') + argument_parser.add_argument('--test-error-cls', help='the class id, the error should be thrown in') + argument_parser.add_argument('--test-error-meth', help='the meth id, the error should be thrown in') + argument_parser.add_argument('--test-error-part', help='the part (`construct` or `teardown`), the error should ' + 'be thrown in - only for fixtures') + + def modify_collected_pyfiles(self, pyfiles: List[pathlib.Path]) -> List[pathlib.Path]: + # use this method to set the values + RuntimeObserver.error_throwing = {} + if self.balder_session.parsed_args.test_error_file: + path = pathlib.Path(self.balder_session.parsed_args.test_error_file) + if not path.is_absolute(): + path = str(self.balder_session.working_dir.joinpath(path)) + RuntimeObserver.error_throwing['file'] = path + if self.balder_session.parsed_args.test_error_cls: + RuntimeObserver.error_throwing['cls'] = self.balder_session.parsed_args.test_error_cls + if self.balder_session.parsed_args.test_error_meth: + RuntimeObserver.error_throwing['meth'] = self.balder_session.parsed_args.test_error_meth + if self.balder_session.parsed_args.test_error_part: + RuntimeObserver.error_throwing['part'] = self.balder_session.parsed_args.test_error_part + return pyfiles + + +@balder.fixture(level="session") +def balderglob_fixture_session(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_session, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_SESSION + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_session, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="setup") +def balderglob_fixture_setup(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_setup, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_SETUP + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_setup, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="scenario") +def balderglob_fixture_scenario(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_scenario, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_SCENARIO + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_scenario, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="variation") +def balderglob_fixture_variation(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_variation, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_VARIATION + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_variation, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") + + +@balder.fixture(level="testcase") +def balderglob_fixture_testcase(): + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_testcase, "begin execution CONSTRUCTION of fixture", + category="fixture", part="construction") + + yield FixtureReturn.BALDERGLOB_TESTCASE + + RuntimeObserver.add_entry(__file__, None, balderglob_fixture_testcase, "begin execution TEARDOWN of fixture", + category="fixture", part="teardown") diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/__init__.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/connections.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/connections.py new file mode 100644 index 00000000..cf1e8b61 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/connections.py @@ -0,0 +1,11 @@ +import balder + + +@balder.insert_into_tree() +class AConnection(balder.Connection): + pass + + +@balder.insert_into_tree() +class BConnection(balder.Connection): + pass diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/features.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/features.py new file mode 100644 index 00000000..fae8ae25 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/features.py @@ -0,0 +1,30 @@ +import balder +from ..balderglob import RuntimeObserver + + +class FeatureI(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureI, FeatureI.do_something, "enter `FeatureI.do_something`", category="feature") + + +class FeatureII(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureII, FeatureII.do_something, "enter `FeatureII.do_something`", category="feature") + + +class FeatureIII(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureIII, FeatureIII.do_something, "enter `FeatureIII.do_something`", category="feature") + + +class FeatureIV(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, FeatureIV, FeatureIV.do_something, "enter `FeatureIV.do_something`", category="feature") diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/utils.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/utils.py new file mode 100644 index 00000000..fe4559af --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/lib/utils.py @@ -0,0 +1,22 @@ + + +class FixtureReturn: + """helper const class for return values""" + BALDERGLOB_SESSION = "balderglob_session_fixt" + BALDERGLOB_SETUP = "balderglob_setup_fixt" + BALDERGLOB_SCENARIO = "balderglob_scenario_fixt" + BALDERGLOB_VARIATION = "balderglob_variation_fixt" + BALDERGLOB_TESTCASE = "balderglob_testcase_fixt" + + SETUP_SESSION = "setup_session_fixt" + SETUP_SETUP = "setup_setup_fixt" + SETUP_SCENARIO = "setup_scenario_fixt" + SETUP_VARIATION = "setup_variation_fixt" + SETUP_TESTCASE = "setup_testcase_fixt" + + SCENARIO_SESSION = "scenario_session_fixt" + SCENARIO_SETUP = "scenario_setup_fixt" + SCENARIO_SCENARIO = "scenario_scenario_fixt" + SCENARIO_VARIATION = "scenario_variation_fixt" + SCENARIO_TESTCASE = "scenario_testcase_fixt" + diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/scenarios/__init__.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/scenarios/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a.py new file mode 100644 index 00000000..eedd55ab --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/scenarios/scenario_a.py @@ -0,0 +1,108 @@ +import balder +import logging +from ..lib.features import FeatureI, FeatureII +from ..lib.connections import AConnection +from ..balderglob import RuntimeObserver + +logger = logging.getLogger(__file__) + + +class ScenarioA(balder.Scenario): + """This is the scenario of category A""" + + class ScenarioDevice1(balder.Device): + i = FeatureI() + + @balder.connect(ScenarioDevice1, over_connection=AConnection) + class ScenarioDevice2(balder.Device): + ii = FeatureII() + + def test_a_1(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.test_a_1, category="testcase", + msg=f"execute Test `{ScenarioA.test_a_1.__qualname__}`") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + def test_a_2(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.test_a_2, category="testcase", + msg=f"execute Test `{ScenarioA.test_a_2.__qualname__}`") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="session") + def fixture_session(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_session, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_session, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="setup") + def fixture_setup(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_setup, category="fixture", part="construction", + msg="begin execution CONSTRUCTION of fixture") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_setup, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="scenario") + def fixture_scenario(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_scenario, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_scenario, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="variation") + def fixture_variation(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_variation, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_variation, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + @balder.fixture(level="testcase") + def fixture_testcase(self): + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_testcase, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, ScenarioA, ScenarioA.fixture_testcase, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.ScenarioDevice1.i.do_something() + self.ScenarioDevice2.ii.do_something() diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/__init__.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_a_child.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_a_child.py new file mode 100644 index 00000000..1e7f4bff --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_a_child.py @@ -0,0 +1,110 @@ +import balder +import logging +from .setup_features import SetupFeatureIOverwritten, SetupFeatureII, SetupFeatureNew +from ..lib.connections import AConnection +from ..balderglob import RuntimeObserver +from .setup_a_parent import SetupAParent + +logger = logging.getLogger(__name__) + + +class SetupAChild(SetupAParent): + """This is a setup of category A (exactly the same as scenario A)""" + + class SetupDevice1(SetupAParent.SetupDevice1): + s_i = SetupFeatureIOverwritten() + + @balder.connect(SetupDevice1, over_connection=AConnection) + class SetupDevice2(SetupAParent.SetupDevice2): + s_ii = SetupFeatureII() + new = SetupFeatureNew() + + @balder.fixture(level="session") + def fixture_session(self): + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_session, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_session, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + @balder.fixture(level="setup") + def fixture_setup(self): + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_setup, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_setup, category="fixture", part="teardown", + msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + @balder.fixture(level="scenario") + def fixture_scenario(self): + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_scenario, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_scenario, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + @balder.fixture(level="variation") + def fixture_variation(self): + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_variation, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_variation, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + @balder.fixture(level="testcase") + def fixture_testcase(self): + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_testcase, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAChild, SetupAChild.fixture_testcase, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + self.SetupDevice2.new.do_something() diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_a_parent.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_a_parent.py new file mode 100644 index 00000000..345b4956 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_a_parent.py @@ -0,0 +1,98 @@ +import balder +import logging +from .setup_features import SetupFeatureI, SetupFeatureII +from ..lib.connections import AConnection +from ..balderglob import RuntimeObserver + +logger = logging.getLogger(__name__) + + +class SetupAParent(balder.Setup): + """This is a setup of category A (exactly the same as scenario A)""" + + class SetupDevice1(balder.Device): + s_i = SetupFeatureI() + + @balder.connect('SetupDevice1', over_connection=AConnection) + class SetupDevice2(balder.Device): + s_ii = SetupFeatureII() + + @balder.fixture(level="session") + def fixture_session(self): + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_session, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_session, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + @balder.fixture(level="setup") + def fixture_setup(self): + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_setup, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_setup, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + @balder.fixture(level="scenario") + def fixture_scenario(self): + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_scenario, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_scenario, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + @balder.fixture(level="variation") + def fixture_variation(self): + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_variation, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_variation, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + @balder.fixture(level="testcase") + def fixture_testcase(self): + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_testcase, category="fixture", + part="construction", msg="begin execution CONSTRUCTION of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() + + yield + + RuntimeObserver.add_entry(__file__, SetupAParent, SetupAParent.fixture_testcase, category="fixture", + part="teardown", msg="begin execution TEARDOWN of fixture") + + self.SetupDevice1.s_i.do_something() + self.SetupDevice2.s_ii.do_something() diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/__init__.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/__init__.py new file mode 100644 index 00000000..5c1fa884 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/__init__.py @@ -0,0 +1,11 @@ +from .feature_i import SetupFeatureI +from .feature_ii import SetupFeatureII +from .feature_i_overwritten import SetupFeatureIOverwritten +from .feature_new import SetupFeatureNew + +__all__ = [ + "SetupFeatureI", + "SetupFeatureII", + "SetupFeatureIOverwritten", + "SetupFeatureNew" +] diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i.py new file mode 100644 index 00000000..8f4cd2e5 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i.py @@ -0,0 +1,10 @@ +from ...lib.features import FeatureI +from ...balderglob import RuntimeObserver + + +class SetupFeatureI(FeatureI): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, SetupFeatureI, SetupFeatureI.do_something, "enter `SetupFeatureI.do_something`", + category="feature") diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i_overwritten.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i_overwritten.py new file mode 100644 index 00000000..d884ad1e --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_i_overwritten.py @@ -0,0 +1,10 @@ +from ...balderglob import RuntimeObserver +from .feature_i import SetupFeatureI + + +class SetupFeatureIOverwritten(SetupFeatureI): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, SetupFeatureIOverwritten, SetupFeatureIOverwritten.do_something, + "enter `SetupFeatureIOverwritten.do_something`", category="feature") diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_ii.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_ii.py new file mode 100644 index 00000000..a38e27c7 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_ii.py @@ -0,0 +1,10 @@ +from ...lib.features import FeatureII +from ...balderglob import RuntimeObserver + + +class SetupFeatureII(FeatureII): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, SetupFeatureII, SetupFeatureII.do_something, "enter `SetupFeatureII.do_something`", + category="feature") diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_new.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_new.py new file mode 100644 index 00000000..37af7316 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/env/setups/setup_features/feature_new.py @@ -0,0 +1,10 @@ +import balder +from ...balderglob import RuntimeObserver + + +class SetupFeatureNew(balder.Feature): + + def do_something(self): + RuntimeObserver.add_entry( + __file__, SetupFeatureNew, SetupFeatureNew.do_something, "enter `SetupFeatureNew.do_something`", + category="feature") diff --git a/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/test_0_setup_correctly_using_str_dev_ref_in_parent.py b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/test_0_setup_correctly_using_str_dev_ref_in_parent.py new file mode 100644 index 00000000..eb579988 --- /dev/null +++ b/tests/setup_inheritance/test_0_setup_correctly_using_str_dev_ref_in_parent/test_0_setup_correctly_using_str_dev_ref_in_parent.py @@ -0,0 +1,213 @@ +from _balder.testresult import ResultState +from _balder.balder_session import BalderSession + +from tests.test_utilities.base_0_envtester_class import Base0EnvtesterClass + + +class Test0SetupCorrectlyUsingStrDevRefInParent(Base0EnvtesterClass): + """ + This testcase executes the basic envtester environment but uses an inherited setup `SetupAChild`. Within this + setup we define an additional feature class that was not known in parent setup `SetupAParent`. In addition + to that, the environment overwrites an existing feature within the `SetupAChild`-Device that is a child class of + the overwritten one. + Compared to `test_0_setup_correctly_overwrite_and_add_feature`, this environment uses string references within + the parent setup `SetupAParent`. + + The test secures that it can be executed correctly and without an error. + """ + + @property + def expected_data(self) -> tuple: + return ( + # FIXTURE-CONSTRUCTION: balderglob_fixture_session + {"file": "balderglob.py", "meth": "balderglob_fixture_session", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_session + {"cls": "SetupAChild", "meth": "fixture_session", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioA.fixture_session + {"cls": "ScenarioA", "meth": "fixture_session", "part": "construction"}, + {"cls": "FeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: balderglob_fixture_setup + {"file": "balderglob.py", "meth": "balderglob_fixture_setup", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_setup + {"cls": "SetupAChild", "meth": "fixture_setup", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioA.fixture_setup + {"cls": "ScenarioA", "meth": "fixture_setup", "part": "construction"}, + {"cls": "FeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: balderglob_fixture_scenario + {"file": "balderglob.py", "meth": "balderglob_fixture_scenario", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_scenario + {"cls": "SetupAChild", "meth": "fixture_scenario", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioA.fixture_scenario + {"cls": "ScenarioA", "meth": "fixture_scenario", "part": "construction"}, + {"cls": "FeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: balderglob_fixture_variation + {"file": "balderglob.py", "meth": "balderglob_fixture_variation", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_variation + {"cls": "SetupAChild", "meth": "fixture_variation", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioA.fixture_variation + {"cls": "ScenarioA", "meth": "fixture_variation", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + [ + ( + # FIXTURE-CONSTRUCTION: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_testcase + {"cls": "SetupAChild", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioA.fixture_testcase + {"cls": "ScenarioA", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # TESTCASE: ScenarioA.test_a_1 + {"cls": "ScenarioA", "meth": "test_a_1"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: ScenarioA.fixture_testcase + {"cls": "ScenarioA", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_testcase + {"cls": "SetupAChild", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "teardown"}, + ), + ( + # FIXTURE-CONSTRUCTION: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "construction"}, + # FIXTURE-CONSTRUCTION: SetupA.fixture_testcase + {"cls": "SetupAChild", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-CONSTRUCTION: ScenarioA.fixture_testcase + {"cls": "ScenarioA", "meth": "fixture_testcase", "part": "construction"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # TESTCASE: ScenarioA.test_a_2 + {"cls": "ScenarioA", "meth": "test_a_2"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: ScenarioA.fixture_testcase + {"cls": "ScenarioA", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_testcase + {"cls": "SetupAChild", "meth": "fixture_testcase", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_testcase + {"file": "balderglob.py", "meth": "balderglob_fixture_testcase", "part": "teardown"}, + ), + ], + # FIXTURE-TEARDOWN: ScenarioA.fixture_variation + {"cls": "ScenarioA", "meth": "fixture_variation", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_variation + {"cls": "SetupAChild", "meth": "fixture_variation", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_variation + {"file": "balderglob.py", "meth": "balderglob_fixture_variation", "part": "teardown"}, + # FIXTURE-TEARDOWN: ScenarioA.fixture_scenario + {"cls": "ScenarioA", "meth": "fixture_scenario", "part": "teardown"}, + {"cls": "FeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_scenario + {"cls": "SetupAChild", "meth": "fixture_scenario", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_scenario + {"file": "balderglob.py", "meth": "balderglob_fixture_scenario", "part": "teardown"}, + # FIXTURE-TEARDOWN: ScenarioA.fixture_setup + {"cls": "ScenarioA", "meth": "fixture_setup", "part": "teardown"}, + {"cls": "FeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_setup + {"cls": "SetupAChild", "meth": "fixture_setup", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_setup + {"file": "balderglob.py", "meth": "balderglob_fixture_setup", "part": "teardown"}, + # FIXTURE-TEARDOWN: ScenarioA.fixture_session + {"cls": "ScenarioA", "meth": "fixture_session", "part": "teardown"}, + {"cls": "FeatureI", "meth": "do_something", "category": "feature"}, + {"cls": "FeatureII", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: SetupA.fixture_session + {"cls": "SetupAChild", "meth": "fixture_session", "part": "teardown"}, + {"cls": "SetupFeatureIOverwritten", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureII", "meth": "do_something", "category": "feature"}, + {"cls": "SetupFeatureNew", "meth": "do_something", "category": "feature"}, + # FIXTURE-TEARDOWN: balderglob_fixture_session + {"file": "balderglob.py", "meth": "balderglob_fixture_session", "part": "teardown"}, + ) + + @staticmethod + def validate_finished_session(session: BalderSession): + + # check result states everywhere (have to be SUCCESS everywhere) + assert session.executor_tree.executor_result == ResultState.SUCCESS, \ + "test session does not terminates with success" + + assert session.executor_tree.construct_result.result == ResultState.SUCCESS, \ + "global executor tree construct part does not set ResultState.SUCCESS" + assert session.executor_tree.body_result.result == ResultState.SUCCESS, \ + "global executor tree body part does not set ResultState.SUCCESS" + assert session.executor_tree.teardown_result.result == ResultState.SUCCESS, \ + "global executor tree teardown part does not set ResultState.SUCCESS" + for cur_setup_executor in session.executor_tree.get_setup_executors(): + assert cur_setup_executor.executor_result == ResultState.SUCCESS, \ + "the setup executor does not have result SUCCESS" + + assert cur_setup_executor.construct_result.result == ResultState.SUCCESS + assert cur_setup_executor.body_result.result == ResultState.SUCCESS + assert cur_setup_executor.teardown_result.result == ResultState.SUCCESS + + for cur_scenario_executor in cur_setup_executor.get_scenario_executors(): + assert cur_scenario_executor.executor_result == ResultState.SUCCESS, \ + "the scenario executor does not have result SUCCESS" + + assert cur_scenario_executor.construct_result.result == ResultState.SUCCESS + assert cur_scenario_executor.body_result.result == ResultState.SUCCESS + assert cur_scenario_executor.teardown_result.result == ResultState.SUCCESS + + for cur_variation_executor in cur_scenario_executor.get_variation_executors(): + assert cur_variation_executor.executor_result == ResultState.SUCCESS, \ + "the variation executor does not have result SUCCESS" + + assert cur_variation_executor.construct_result.result == ResultState.SUCCESS + assert cur_variation_executor.body_result.result == ResultState.SUCCESS + assert cur_variation_executor.teardown_result.result == ResultState.SUCCESS + + for cur_testcase_executor in cur_variation_executor.get_testcase_executors(): + assert cur_testcase_executor.executor_result == ResultState.SUCCESS, \ + "the testcase executor does not have result SUCCESS" + + assert cur_testcase_executor.construct_result.result == ResultState.SUCCESS + assert cur_testcase_executor.body_result.result == ResultState.SUCCESS + assert cur_testcase_executor.teardown_result.result == ResultState.SUCCESS