diff --git a/.flake8 b/.flake8 index 0b443177..70cbc719 100644 --- a/.flake8 +++ b/.flake8 @@ -7,3 +7,5 @@ exclude = ./tests/allure_behave/acceptance/behave_support/background/background_steps.py per-file-ignores = ./allure-python-commons/src/model2.py:A003 + ./allure-python-commons/src/types.py:A005 + ./allure-robotframework/src/listener/types.py:A005 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ece3d161..aab9cb8e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -69,7 +69,7 @@ jobs: - name: Cache commons id: commons - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: dist/ key: commons-${{ github.sha }} @@ -89,7 +89,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.12" @@ -124,7 +124,7 @@ jobs: - name: Get commons from cache id: commons - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: dist/ key: commons-${{ github.sha }} @@ -165,7 +165,7 @@ jobs: - name: Get commons from cache id: commons - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: dist/ key: commons-${{ github.sha }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8a850832..10b3295f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/allure-behave/src/listener.py b/allure-behave/src/listener.py index 927c72a8..b9a86d55 100644 --- a/allure-behave/src/listener.py +++ b/allure-behave/src/listener.py @@ -22,10 +22,6 @@ from allure_behave.utils import get_fullname from allure_behave.utils import TEST_PLAN_SKIP_REASON from allure_behave.utils import get_hook_name -import behave -from packaging import version - -BEHAVE_1_2_7_OR_GREATER = version.parse(behave.__version__) > version.parse("1.2.6") class AllureListener: @@ -101,10 +97,8 @@ def stop_test(self, parent_uuid, uuid, name, context, exc_type, exc_val, exc_tb) self.stop_scenario(context['scenario']) def stop_scenario(self, scenario): - if BEHAVE_1_2_7_OR_GREATER: - should_run = scenario.should_run_with_tags(self.behave_config.tag_expression) - else: - should_run = scenario.should_run_with_tags(self.behave_config.tags) + tag_expression = self.__get_tag_expression(self.behave_config) + should_run = scenario.should_run_with_tags(tag_expression) should_run = should_run and scenario.should_run_with_name_select(self.behave_config) should_drop_skipped_by_option = scenario.status == 'skipped' and not self.behave_config.show_skipped should_drop_excluded = self.hide_excluded and (scenario.skip_reason == TEST_PLAN_SKIP_REASON or not should_run) @@ -213,6 +207,14 @@ def add_link(self, url, link_type, name): def stop_session(self): self.group_context.exit() + @staticmethod + def __get_tag_expression(config): + tag_expression = getattr(config, "tag_expression", None) + if tag_expression is None: + # Behave 1.2.6 and earlier + return getattr(config, "tags") + return tag_expression + class GroupContext: def __init__(self, logger): diff --git a/allure-pytest/src/compat.py b/allure-pytest/src/compat.py new file mode 100644 index 00000000..bf7db2dd --- /dev/null +++ b/allure-pytest/src/compat.py @@ -0,0 +1,34 @@ +"""Provides compatibility with different pytest versions.""" + +from inspect import signature + +__GETFIXTUREDEFS_2ND_PAR_IS_STR = None + + +def getfixturedefs(fixturemanager, name, item): + """Calls FixtureManager.getfixturedefs in a way compatible with Python + versions before and after the change described in pytest-dev/pytest#11785. + """ + getfixturedefs = fixturemanager.getfixturedefs + itemarg = __resolve_getfixturedefs_2nd_arg(getfixturedefs, item) + return getfixturedefs(name, itemarg) + + +def __resolve_getfixturedefs_2nd_arg(getfixturedefs, item): + # Starting from pytest 8.1, getfixturedefs requires the item itself. + # In earlier versions it requires the nodeid string. + return item.nodeid if __2nd_parameter_is_str(getfixturedefs) else item + + +def __2nd_parameter_is_str(getfixturedefs): + global __GETFIXTUREDEFS_2ND_PAR_IS_STR + if __GETFIXTUREDEFS_2ND_PAR_IS_STR is None: + __GETFIXTUREDEFS_2ND_PAR_IS_STR =\ + __get_2nd_parameter_type(getfixturedefs) is str + return __GETFIXTUREDEFS_2ND_PAR_IS_STR + + +def __get_2nd_parameter_type(fn): + return list( + signature(fn).parameters.values() + )[1].annotation diff --git a/allure-pytest/src/listener.py b/allure-pytest/src/listener.py index eb222bc0..11153630 100644 --- a/allure-pytest/src/listener.py +++ b/allure-pytest/src/listener.py @@ -1,6 +1,5 @@ import pytest import doctest -from packaging import version import allure_commons from allure_commons.utils import now @@ -8,6 +7,7 @@ from allure_commons.utils import represent from allure_commons.utils import platform_label from allure_commons.utils import host_tag, thread_tag +from allure_commons.utils import md5 from allure_commons.reporter import AllureReporter from allure_commons.model2 import TestStepResult, TestResult, TestBeforeResult, TestAfterResult from allure_commons.model2 import TestResultContainer @@ -25,7 +25,7 @@ from allure_pytest.utils import get_pytest_report_status from allure_pytest.utils import format_allure_link from allure_pytest.utils import get_history_id -from allure_commons.utils import md5 +from allure_pytest.compat import getfixturedefs class AllureListener: @@ -349,23 +349,13 @@ def _test_fixtures(item): if hasattr(item, "_request") and hasattr(item._request, "fixturenames"): for name in item._request.fixturenames: - fixturedefs_pytest = _getfixturedefs(fixturemanager, name, item) + fixturedefs_pytest = getfixturedefs(fixturemanager, name, item) if fixturedefs_pytest: fixturedefs.extend(fixturedefs_pytest) return fixturedefs -def _getfixturedefs(fixturemanager, name, item): - # See pytest-dev/pytest#11785 - itemarg = item if __is_pytest8_1_or_greater() else item.nodeid - return fixturemanager.getfixturedefs(name, itemarg) - - -def __is_pytest8_1_or_greater(): - return version.parse(pytest.__version__) >= version.parse("8.1") - - def _exception_brokes_test(exception): return not isinstance(exception, ( AssertionError, diff --git a/tests/allure_pytest/acceptance/capture/capture_attach_test.py b/tests/allure_pytest/acceptance/capture/capture_attach_test.py index 64f538f4..c17a4de8 100644 --- a/tests/allure_pytest/acceptance/capture/capture_attach_test.py +++ b/tests/allure_pytest/acceptance/capture/capture_attach_test.py @@ -90,10 +90,9 @@ def test_capture_log(allure_pytest_runner: AllurePytestRunner, logging): ... logger.info("Start step") """ - params = [] if logging else ["-p", "no:logging"] + log_level = "INFO" if logging else "WARNING" allure_results = allure_pytest_runner.run_docstring( - "--log-level=INFO", - *params + f"--log-level={log_level}", ) if_logging_ = is_ if logging else is_not diff --git a/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py b/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py index 2a744b70..c14a8d1a 100644 --- a/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py +++ b/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py @@ -134,10 +134,10 @@ def then_the_postconditions_are_held(): """ ) - params = [] if logging else ["-p", "no:logging"] + log_level = "INFO" if logging else "WARNING" allure_results = allure_pytest_bdd_runner.run_pytest( ("scenario.feature", feature_content), - steps_content, cli_args=("--log-level=INFO", *params) + steps_content, cli_args=(f"--log-level={log_level}",) ) if_logging_ = is_ if logging else is_not