From e3466167f10bfdb2a00875fb7d31753d9c0fc76a Mon Sep 17 00:00:00 2001 From: Krisztian Notaisz <61833595+kn-ms@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:55:33 +0200 Subject: [PATCH] small improvements in json listing (#996) * small improvements - make graceful metadata collection, in some generated cases - split up the spaghetti a bit in the main wrapper --------- Co-authored-by: Krisztian Notaisz --- testplan/base.py | 45 ++++++++++++--------- testplan/testing/multitest/test_metadata.py | 24 +++++++---- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/testplan/base.py b/testplan/base.py index 3bebb77a3..0b04da6d7 100644 --- a/testplan/base.py +++ b/testplan/base.py @@ -495,29 +495,13 @@ def test_plan_inner_inner(): **options, ) try: - if arity(definition) == 2: - returned = definition(plan, plan.parser) - else: - returned = definition(plan) + returned = cls._prepare_plan(definition, plan) except Exception: print("Exception in test_plan definition, aborting plan..") plan.abort() raise - lister: MetadataBasedLister = plan.cfg.test_lister - if lister is not None and lister.metadata_based: - output = lister.get_output( - TestPlanMetadata( - plan.cfg.name, - plan.cfg.description, - plan.get_test_metadata(), - ) - ) - if plan.cfg.test_lister_output: - with open(plan.cfg.test_lister_output, "wt") as file: - file.write(output) - else: - TESTPLAN_LOGGER.user_info(output) + cls._do_listing(plan) plan_result = plan.run() plan_result.decorated_value = returned @@ -527,6 +511,31 @@ def test_plan_inner_inner(): return test_plan_inner + @classmethod + def _prepare_plan(cls, definition, plan): + if arity(definition) == 2: + returned = definition(plan, plan.parser) + else: + returned = definition(plan) + return returned + + @classmethod + def _do_listing(cls, plan): + lister: MetadataBasedLister = plan.cfg.test_lister + if lister is not None and lister.metadata_based: + output = lister.get_output( + TestPlanMetadata( + plan.cfg.name, + plan.cfg.description, + plan.get_test_metadata(), + ) + ) + if plan.cfg.test_lister_output: + with open(plan.cfg.test_lister_output, "wt") as file: + file.write(output) + else: + TESTPLAN_LOGGER.user_info(output) + test_plan = Testplan.main_wrapper diff --git a/testplan/testing/multitest/test_metadata.py b/testplan/testing/multitest/test_metadata.py index 1df02074c..4c79dcfec 100644 --- a/testplan/testing/multitest/test_metadata.py +++ b/testplan/testing/multitest/test_metadata.py @@ -2,6 +2,8 @@ from inspect import getsourcefile, getsourcelines from typing import List, Optional, Union +LOCATION_METADATA_ATTRIBUTE = "__location_metadata__" + @dataclass class LocationMetadata: @@ -11,16 +13,24 @@ class LocationMetadata: line_no: int @classmethod - def from_object(cls, obj): - object_name = obj.__name__ - file = getsourcefile(obj) - _, line_no = getsourcelines(obj) - return cls(object_name, file, line_no) + def from_object(cls, obj) -> "LocationMetadata": + # some cases where testcases /suites generated on the fly user can provide meaningfull metadata + # with attaching one to the object + if hasattr(obj, LOCATION_METADATA_ATTRIBUTE): + return getattr(obj, LOCATION_METADATA_ATTRIBUTE) + try: + object_name = obj.__name__ + file = getsourcefile(obj) + _, line_no = getsourcelines(obj) + except Exception: + return None # we do best effort here + else: + return cls(object_name, file, line_no) @dataclass class TestCaseStaticMetadata: - location: LocationMetadata + location: Optional[LocationMetadata] @dataclass @@ -38,7 +48,7 @@ class TestCaseMetadata(TestCaseStaticMetadata, BasicInfo): @dataclass class TestSuiteStaticMetadata: - location: LocationMetadata + location: Optional[LocationMetadata] @dataclass