From dc95ff5cbaea0414131f656b36d60e49d0582bfa Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 19 Mar 2024 16:53:45 +0200 Subject: [PATCH 1/4] Attach stdout, stderr and log to the report --- allure-pytest-bdd/src/pytest_bdd_listener.py | 9 +- .../acceptance/capture/__init__.py | 0 .../acceptance/capture/capture_attach_test.py | 148 ++++++++++++++++++ 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 tests/allure_pytest_bdd/acceptance/capture/__init__.py create mode 100644 tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py diff --git a/allure-pytest-bdd/src/pytest_bdd_listener.py b/allure-pytest-bdd/src/pytest_bdd_listener.py index 9a4f5fac..e92fcbcd 100644 --- a/allure-pytest-bdd/src/pytest_bdd_listener.py +++ b/allure-pytest-bdd/src/pytest_bdd_listener.py @@ -5,7 +5,8 @@ from allure_commons.model2 import Label from allure_commons.model2 import Status -from allure_commons.types import LabelType +from allure_commons.types import LabelType, AttachmentType +from allure_commons.reporter import AllureReporter from allure_commons.utils import platform_label from allure_commons.utils import host_tag, thread_tag from allure_commons.utils import md5 @@ -114,6 +115,12 @@ def pytest_runtest_makereport(self, item, call): if test_result.status == Status.PASSED and status != Status.PASSED: test_result.status = status test_result.statusDetails = status_details + if report.caplog: + self.attach_data(report.caplog, "log", AttachmentType.TEXT, None) + if report.capstdout: + self.attach_data(report.capstdout, "stdout", AttachmentType.TEXT, None) + if report.capstderr: + self.attach_data(report.capstderr, "stderr", AttachmentType.TEXT, None) if report.when == 'teardown': self.lifecycle.write_test_case(uuid=uuid) diff --git a/tests/allure_pytest_bdd/acceptance/capture/__init__.py b/tests/allure_pytest_bdd/acceptance/capture/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py b/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py new file mode 100644 index 00000000..21d1b726 --- /dev/null +++ b/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py @@ -0,0 +1,148 @@ +import pytest +from hamcrest import assert_that +from hamcrest import all_of, is_, is_not +from hamcrest import has_property, has_value +from hamcrest import contains_string +from tests.allure_pytest.pytest_runner import AllurePytestRunner + + +@pytest.mark.parametrize("capture", ["sys", "fd", "no"]) +def test_capture_stdout_in_bdd(allure_pytest_bdd_runner: AllurePytestRunner, capture): + feature_content = ( + """ + Feature: Basic allure-pytest-bdd usage + Scenario: Simple passed example + Given the preconditions are satisfied + When the action is invoked + Then the postconditions are held + """ + ) + steps_content = ( + """ + from pytest_bdd import scenario, given, when, then + @scenario("scenario.feature", "Simple passed example") + def test_scenario_passes(): + pass + + @given("the preconditions are satisfied") + def given_the_preconditions_are_satisfied(): + print("Print from given step") + + @when("the action is invoked") + def when_the_action_is_invoked(): + print("Print from when step") + + @then("the postconditions are held") + def then_the_postconditions_are_held(): + print("Print from then step") + """ + ) + + allure_results = allure_pytest_bdd_runner.run_pytest( + ("scenario.feature", feature_content), + steps_content, cli_args=(f"--capture={capture}",) + ) + if_pytest_capture_ = is_not if capture == "no" else is_ + + assert_that( + allure_results, + has_property( + "attachments", + all_of( + if_pytest_capture_(has_value(contains_string("Print from given step"))), + if_pytest_capture_(has_value(contains_string("Print from when step"))), + if_pytest_capture_(has_value(contains_string("Print from then step"))) + ) + ) + ) + + +# @pytest.mark.parametrize("capture", ["sys", "fd"]) +# def test_capture_empty_stdout(allure_pytest_runner: AllurePytestRunner, capture): +# """ +# >>> import pytest +# >>> import allure +# +# >>> @pytest.fixture +# ... def fixture(request): +# ... def finalizer(): +# ... pass +# ... request.addfinalizer(finalizer) +# +# >>> def test_capture_stdout_example(fixture): +# ... with allure.step("Step"): +# ... pass +# """ +# +# allure_results = allure_pytest_runner.run_docstring(f"--capture={capture}") +# +# assert_that( +# allure_results, +# has_property("attachments", empty()) +# ) +# +# +# @pytest.mark.parametrize("logging", [True, False]) +# def test_capture_log(allure_pytest_runner: AllurePytestRunner, logging): +# """ +# >>> import logging +# >>> import pytest +# >>> import allure +# +# >>> logger = logging.getLogger(__name__) +# +# >>> @pytest.fixture +# ... def fixture(request): +# ... logger.info("Start fixture") +# ... def finalizer(): +# ... logger.info("Stop fixture") +# ... request.addfinalizer(finalizer) +# +# >>> def test_capture_log_example(fixture): +# ... logger.info("Start test") +# ... with allure.step("Step"): +# ... logger.info("Start step") +# """ +# +# params = [] if logging else ["-p", "no:logging"] +# allure_results = allure_pytest_runner.run_docstring( +# "--log-level=INFO", +# *params +# ) +# +# if_logging_ = is_ if logging else is_not +# +# assert_that( +# allure_results, +# has_property( +# "attachments", +# all_of( +# if_logging_(has_value(contains_string("Start fixture"))), +# if_logging_(has_value(contains_string("Stop fixture"))), +# if_logging_(has_value(contains_string("Start test"))), +# if_logging_(has_value(contains_string("Start step"))) +# ) +# ) +# ) +# +# +# def test_capture_disabled(allure_pytest_runner: AllurePytestRunner): +# """ +# >>> import logging +# >>> logger = logging.getLogger(__name__) +# +# >>> def test_capture_disabled_example(): +# ... logger.info("Start logging") +# ... #print ("Start printing") +# +# """ +# +# allure_results = allure_pytest_runner.run_docstring( +# "--log-level=INFO", +# "--allure-no-capture" +# ) +# +# assert_that( +# allure_results, +# has_property("attachments", empty()) +# ) From 9ceb6215b784720ebad4e750f4dfbc7f18a4647a Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 19 Mar 2024 16:54:58 +0200 Subject: [PATCH 2/4] Deleted unused import --- allure-pytest-bdd/src/pytest_bdd_listener.py | 1 - 1 file changed, 1 deletion(-) diff --git a/allure-pytest-bdd/src/pytest_bdd_listener.py b/allure-pytest-bdd/src/pytest_bdd_listener.py index e92fcbcd..d4c73115 100644 --- a/allure-pytest-bdd/src/pytest_bdd_listener.py +++ b/allure-pytest-bdd/src/pytest_bdd_listener.py @@ -6,7 +6,6 @@ from allure_commons.model2 import Status from allure_commons.types import LabelType, AttachmentType -from allure_commons.reporter import AllureReporter from allure_commons.utils import platform_label from allure_commons.utils import host_tag, thread_tag from allure_commons.utils import md5 From d7a16da9cb28bd00cf8228888b72e2e252d9757c Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 19 Mar 2024 17:15:41 +0200 Subject: [PATCH 3/4] Added more tests --- .../acceptance/capture/capture_attach_test.py | 189 +++++++++--------- 1 file changed, 99 insertions(+), 90 deletions(-) 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 21d1b726..3af1e0b1 100644 --- a/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py +++ b/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py @@ -1,5 +1,5 @@ import pytest -from hamcrest import assert_that +from hamcrest import assert_that, empty from hamcrest import all_of, is_, is_not from hamcrest import has_property, has_value from hamcrest import contains_string @@ -57,92 +57,101 @@ def then_the_postconditions_are_held(): ) -# @pytest.mark.parametrize("capture", ["sys", "fd"]) -# def test_capture_empty_stdout(allure_pytest_runner: AllurePytestRunner, capture): -# """ -# >>> import pytest -# >>> import allure -# -# >>> @pytest.fixture -# ... def fixture(request): -# ... def finalizer(): -# ... pass -# ... request.addfinalizer(finalizer) -# -# >>> def test_capture_stdout_example(fixture): -# ... with allure.step("Step"): -# ... pass -# """ -# -# allure_results = allure_pytest_runner.run_docstring(f"--capture={capture}") -# -# assert_that( -# allure_results, -# has_property("attachments", empty()) -# ) -# -# -# @pytest.mark.parametrize("logging", [True, False]) -# def test_capture_log(allure_pytest_runner: AllurePytestRunner, logging): -# """ -# >>> import logging -# >>> import pytest -# >>> import allure -# -# >>> logger = logging.getLogger(__name__) -# -# >>> @pytest.fixture -# ... def fixture(request): -# ... logger.info("Start fixture") -# ... def finalizer(): -# ... logger.info("Stop fixture") -# ... request.addfinalizer(finalizer) -# -# >>> def test_capture_log_example(fixture): -# ... logger.info("Start test") -# ... with allure.step("Step"): -# ... logger.info("Start step") -# """ -# -# params = [] if logging else ["-p", "no:logging"] -# allure_results = allure_pytest_runner.run_docstring( -# "--log-level=INFO", -# *params -# ) -# -# if_logging_ = is_ if logging else is_not -# -# assert_that( -# allure_results, -# has_property( -# "attachments", -# all_of( -# if_logging_(has_value(contains_string("Start fixture"))), -# if_logging_(has_value(contains_string("Stop fixture"))), -# if_logging_(has_value(contains_string("Start test"))), -# if_logging_(has_value(contains_string("Start step"))) -# ) -# ) -# ) -# -# -# def test_capture_disabled(allure_pytest_runner: AllurePytestRunner): -# """ -# >>> import logging -# >>> logger = logging.getLogger(__name__) -# -# >>> def test_capture_disabled_example(): -# ... logger.info("Start logging") -# ... #print ("Start printing") -# -# """ -# -# allure_results = allure_pytest_runner.run_docstring( -# "--log-level=INFO", -# "--allure-no-capture" -# ) -# -# assert_that( -# allure_results, -# has_property("attachments", empty()) -# ) +@pytest.mark.parametrize("capture", ["sys", "fd"]) +def test_capture_empty_stdout(allure_pytest_bdd_runner: AllurePytestRunner, capture): + feature_content = ( + """ + Feature: Basic allure-pytest-bdd usage + Scenario: Simple passed example + Given the preconditions are satisfied + When the action is invoked + Then the postconditions are held + """ + ) + steps_content = ( + """ + from pytest_bdd import scenario, given, when, then + @scenario("scenario.feature", "Simple passed example") + def test_scenario_passes(): + pass + + @given("the preconditions are satisfied") + def given_the_preconditions_are_satisfied(): + pass + + @when("the action is invoked") + def when_the_action_is_invoked(): + pass + + @then("the postconditions are held") + def then_the_postconditions_are_held(): + pass + """ + ) + + allure_results = allure_pytest_bdd_runner.run_pytest( + ("scenario.feature", feature_content), + steps_content, cli_args=(f"--capture={capture}",) + ) + + assert_that( + allure_results, + has_property("attachments", empty()) + ) + + +@pytest.mark.parametrize("logging", [True, False]) +def test_capture_log(allure_pytest_bdd_runner: AllurePytestRunner, logging): + feature_content = ( + """ + Feature: Basic allure-pytest-bdd usage + Scenario: Simple passed example + Given the preconditions are satisfied + When the action is invoked + Then the postconditions are held + """ + ) + steps_content = ( + """ + import logging + from pytest_bdd import scenario, given, when, then + + logger = logging.getLogger(__name__) + + @scenario("scenario.feature", "Simple passed example") + def test_scenario_passes(): + pass + + @given("the preconditions are satisfied") + def given_the_preconditions_are_satisfied(): + logging.info("Logging from given step") + + @when("the action is invoked") + def when_the_action_is_invoked(): + logging.info("Logging from when step") + + @then("the postconditions are held") + def then_the_postconditions_are_held(): + logging.info("Logging from then step") + """ + ) + + params = [] if logging else ["-p", "no:logging"] + allure_results = allure_pytest_bdd_runner.run_pytest( + ("scenario.feature", feature_content), + steps_content, cli_args=("--log-level=INFO", *params) + ) + + if_logging_ = is_ if logging else is_not + + assert_that( + allure_results, + has_property( + "attachments", + all_of( + if_logging_(has_value(contains_string("Logging from given step"))), + if_logging_(has_value(contains_string("Logging from when step"))), + if_logging_(has_value(contains_string("Logging from then step"))), + ) + ) + ) From 5014e3ec7efa15991158a5c9a10ad9a2f3c46133 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 19 Mar 2024 17:20:07 +0200 Subject: [PATCH 4/4] Fixed linting --- .../allure_pytest_bdd/acceptance/capture/capture_attach_test.py | 2 -- 1 file changed, 2 deletions(-) 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 3af1e0b1..2a744b70 100644 --- a/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py +++ b/tests/allure_pytest_bdd/acceptance/capture/capture_attach_test.py @@ -115,9 +115,7 @@ def test_capture_log(allure_pytest_bdd_runner: AllurePytestRunner, logging): """ import logging from pytest_bdd import scenario, given, when, then - logger = logging.getLogger(__name__) - @scenario("scenario.feature", "Simple passed example") def test_scenario_passes(): pass