diff --git a/allure-pytest/src/listener.py b/allure-pytest/src/listener.py index 0685b61a..84c7d082 100644 --- a/allure-pytest/src/listener.py +++ b/allure-pytest/src/listener.py @@ -219,6 +219,8 @@ def pytest_runtest_makereport(self, item, call): reason = report.wasxfail message = f"XPASS {reason}" if reason else "XPASS" status_details = StatusDetails(message=message) + elif status == Status.FAILED and report.longreprtext.startswith("[XPASS(strict)]"): + status_details = StatusDetails(message=report.longreprtext) if report.when == "setup": test_result.status = status diff --git a/tests/allure_pytest/acceptance/status/xfail_call_status_test.py b/tests/allure_pytest/acceptance/status/xfail_call_status_test.py index 88b17689..147770b5 100644 --- a/tests/allure_pytest/acceptance/status/xfail_call_status_test.py +++ b/tests/allure_pytest/acceptance/status/xfail_call_status_test.py @@ -1,3 +1,4 @@ +import pytest from hamcrest import assert_that from tests.allure_pytest.pytest_runner import AllurePytestRunner @@ -140,3 +141,79 @@ def test_xfail_with_reason_do_not_raise_mentioned_exception( ) ) ) + + +@pytest.mark.parametrize("reason", [None, "Some reason"]) +@pytest.mark.parametrize("strict_from_config", [False, True]) +def test_xfail_mark_strict(allure_pytest_runner: AllurePytestRunner, reason, strict_from_config): + marker_args = [] + if reason is not None: + marker_args.append(f"reason={reason!r}") + if not strict_from_config: + marker_args.append("strict=True") + marker_args = ", ".join(marker_args) + cli_args = ("-o", "xfail_strict=true") if strict_from_config else () + allure_results = allure_pytest_runner.run_pytest( + f""" + import pytest + + @pytest.mark.xfail({marker_args}) + def test_xfail_mark_strict_example(): + pass + """, + cli_args=cli_args + ) + + message = f"[XPASS(strict)] {reason}" if reason else "[XPASS(strict)]" + assert_that( + allure_results, + has_test_case( + "test_xfail_mark_strict_example", + with_status("failed"), + has_status_details(with_message_contains(message)) + ) + ) + + +def test_xfail_mark_strict_expected_failure(allure_pytest_runner: AllurePytestRunner): + """ + >>> import pytest + + >>> @pytest.mark.xfail(reason="Some reason", strict=True) + ... def test_xfail_mark_strict_expected_failure_example(): + ... assert False + """ + allure_results = allure_pytest_runner.run_docstring() + + assert_that( + allure_results, + has_test_case( + "test_xfail_mark_strict_expected_failure_example", + with_status("skipped"), + has_status_details( + with_message_contains("XFAIL Some reason"), + with_message_contains("AssertionError"), + with_trace_contains("def test_xfail_mark_strict_expected_failure_example():") + ) + ) + ) + + +def test_failure_mentioning_strict_xpass(allure_pytest_runner: AllurePytestRunner): + """ + >>> def test_failure_mentioning_strict_xpass_example(): + ... assert False, "[XPASS(strict)] is just an assertion message" + """ + allure_results = allure_pytest_runner.run_docstring() + + assert_that( + allure_results, + has_test_case( + "test_failure_mentioning_strict_xpass_example", + with_status("failed"), + has_status_details( + with_message_contains("AssertionError: [XPASS(strict)] is just an assertion message"), + with_trace_contains("def test_failure_mentioning_strict_xpass_example():") + ) + ) + )