From 3ae127801008b3ed232357aa2a18860d8d129c0c Mon Sep 17 00:00:00 2001 From: Albert Safin <38052075+betapl3b@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:50:36 +0300 Subject: [PATCH] Add pytest ParameterSet.id placeholder for @allure.title formatter (#787) Co-authored-by: Maxim <17935127+delatrie@users.noreply.github.com> --- .../examples/display_name/display_name.rst | 5 ++ allure-pytest/src/listener.py | 7 +- allure-pytest/src/utils.py | 10 ++- .../display_name/display_name_test.py | 88 +++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/allure-pytest/examples/display_name/display_name.rst b/allure-pytest/examples/display_name/display_name.rst index 9040f622..27aaf40a 100644 --- a/allure-pytest/examples/display_name/display_name.rst +++ b/allure-pytest/examples/display_name/display_name.rst @@ -17,3 +17,8 @@ Titles support placeholders for arguments. ... @pytest.mark.parametrize('param', [False]) ... def test_display_name_template(param): ... assert param + + >>> @allure.title("A test title with ParameterSet id {param_id}") + ... @pytest.mark.parametrize('param', [False], ids=["some_id"]) + ... def test_display_name_parameter_set_id(param): + ... assert param diff --git a/allure-pytest/src/listener.py b/allure-pytest/src/listener.py index cbde5243..63daf01d 100644 --- a/allure-pytest/src/listener.py +++ b/allure-pytest/src/listener.py @@ -103,7 +103,8 @@ def pytest_runtest_setup(self, item): uuid = self._cache.get(item.nodeid) test_result = self.allure_logger.get_test(uuid) params = self.__get_pytest_params(item) - test_result.name = allure_name(item, params) + param_id = self.__get_pytest_param_id(item) + test_result.name = allure_name(item, params, param_id) full_name = allure_full_name(item) test_result.fullName = full_name test_result.testCaseId = md5(full_name) @@ -307,6 +308,10 @@ def add_parameter(self, name, value, excluded, mode: ParameterMode): def __get_pytest_params(item): return item.callspec.params if hasattr(item, 'callspec') else {} + @staticmethod + def __get_pytest_param_id(item): + return item.callspec.id if hasattr(item, 'callspec') else None + def __apply_default_suites(self, item, test_result): default_suites = allure_suite_labels(item) existing_suites = { diff --git a/allure-pytest/src/utils.py b/allure-pytest/src/utils.py index ccbd4966..1e07cb49 100644 --- a/allure-pytest/src/utils.py +++ b/allure-pytest/src/utils.py @@ -110,12 +110,18 @@ def allure_package(item): return path.replace('/', '.') -def allure_name(item, parameters): +def allure_name(item, parameters, param_id=None): name = item.name title = allure_title(item) + param_id_kwargs = {} + if param_id: + # if param_id is an ASCII string, it could have been encoded by pytest (_pytest.compat.ascii_escaped) + if param_id.isascii(): + param_id = param_id.encode().decode("unicode-escape") + param_id_kwargs["param_id"] = param_id return SafeFormatter().format( title, - **{**parameters, **item.funcargs} + **{**param_id_kwargs, **parameters, **item.funcargs} ) if title else name diff --git a/tests/allure_pytest/acceptance/display_name/display_name_test.py b/tests/allure_pytest/acceptance/display_name/display_name_test.py index a0985b1d..de6e6eda 100644 --- a/tests/allure_pytest/acceptance/display_name/display_name_test.py +++ b/tests/allure_pytest/acceptance/display_name/display_name_test.py @@ -105,3 +105,91 @@ def test_failed_fixture_value_in_display_name(allure_pytest_runner: AllurePytest has_title("title with {fix}") ) ) + + +def test_param_id_in_display_name(allure_pytest_runner: AllurePytestRunner): + """ + >>> import allure + >>> import pytest + + >>> @pytest.mark.parametrize("name", [pytest.param("value", id="some id")]) + ... @allure.title('Title with id - {param_id}') + ... def test_param_id(name): + ... pass + """ + + allure_results = allure_pytest_runner.run_docstring() + + assert_that( + allure_results, + has_test_case( + "test_param_id", + has_title("Title with id - some id") + ) + ) + + +def test_no_param_id_in_display_name(allure_pytest_runner: AllurePytestRunner): + """ + >>> import allure + >>> import pytest + + >>> @pytest.mark.parametrize("param1, param2", [pytest.param("value1", "value2")]) + ... @allure.title('Title with id - {param_id}') + ... def test_no_param_id(param1, param2): + ... pass + """ + + allure_results = allure_pytest_runner.run_docstring() + + assert_that( + allure_results, + has_test_case( + "test_no_param_id", + has_title("Title with id - value1-value2") + ) + ) + + +def test_non_ascii_id_in_display_name(allure_pytest_runner: AllurePytestRunner): + """ + >>> import allure + >>> import pytest + + >>> @pytest.mark.parametrize("name", [pytest.param("value", id="Ид,本我,पहचान,بطاقة تعريف")]) + ... @allure.title('Title with non-ASCII id - {param_id}') + ... def test_non_ascii_param_id(name): + ... pass + """ + + allure_results = allure_pytest_runner.run_docstring() + + assert_that( + allure_results, + has_test_case( + "test_non_ascii_param_id", + has_title("Title with non-ASCII id - Ид,本我,पहचान,بطاقة تعريف") + ) + ) + + +def test_explicit_parameter_called_param_id_in_display_name(allure_pytest_runner: AllurePytestRunner): + """ + >>> import allure + >>> import pytest + + >>> @pytest.mark.parametrize("param_id", [pytest.param("param value", id="some id")]) + ... @allure.title('Title with id - {param_id}') + ... def test_explicit_parameter_called_param_id(param_id): + ... pass + """ + + allure_results = allure_pytest_runner.run_docstring() + + assert_that( + allure_results, + has_test_case( + "test_explicit_parameter_called_param_id", + has_title("Title with id - param value") + ) + )