Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion allure-pytest/src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ def get_marker_value(item, keyword):


def allure_title(item):
return getattr(item.obj, "__allure_display_name__", None)
return getattr(
getattr(item, "obj", None),
"__allure_display_name__",
None
)


def allure_description(item):
Expand Down
5 changes: 2 additions & 3 deletions tests/allure_behave/behave_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def load_step_definitions(self, extra_step_paths=None):
"step_matcher": matchers.step_matcher,
}

# To support the decorators (i.e., @given) with no imports
# To support the decorators (e.g., @given) with no imports
setup_step_decorators(step_globals, self.step_registry)

default_matcher = matchers.current_matcher
Expand Down Expand Up @@ -113,7 +113,7 @@ class AllureBehaveRunner(AllureFrameworkRunner):
LOGGER_PATH = "allure_behave.formatter.AllureFileLogger"

def __init__(self, request: FixtureRequest, pytester: Pytester):
super().__init__(request, pytester)
super().__init__(request, pytester, AllureBehaveRunner.LOGGER_PATH)

def run_behave(
self,
Expand Down Expand Up @@ -181,7 +181,6 @@ def run_behave(
testplan_content=testplan_content,
testplan_path=testplan_path,
testplan_rst_id=testplan_rst_id,
logger_path=AllureBehaveRunner.LOGGER_PATH,
options=options
)

Expand Down
8 changes: 2 additions & 6 deletions tests/allure_nose2/nose2_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,14 @@ class AllureNose2Runner(AllureFrameworkRunner):
LOGGER_PATH = "allure_nose2.plugin.AllureFileLogger"

def __init__(self, request: FixtureRequest, pytester: Pytester):
super().__init__(request, pytester)
super().__init__(request, pytester, AllureNose2Runner.LOGGER_PATH)

def run_docstring(self):
docstring = self._find_docstring()
example_code = script_from_examples(docstring)
spec = importlib.machinery.ModuleSpec(self.request.node.name, None)
module = importlib.util.module_from_spec(spec)
return self._run(
module,
example_code,
logger_path=AllureNose2Runner.LOGGER_PATH
)
return self._run(module, example_code)

def _run_framework(self, module, example):
# We execute the example here because the _run_framework runs in a
Expand Down
Empty file.
7 changes: 7 additions & 0 deletions tests/allure_pytest/defects/issue733_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from allure_pytest.utils import allure_title


def test_no_allure_title_error_if_item_obj_missing():
item_with_no_obj_attr_stub = object()

assert allure_title(item_with_no_obj_attr_stub) is None
9 changes: 2 additions & 7 deletions tests/allure_pytest/pytest_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class AllurePytestRunner(AllureFrameworkRunner):
DOCTEST_RESULT_KEY = StashKey()

def __init__(self, request: FixtureRequest, pytester: Pytester):
self.logger_path = AllurePytestRunner.LOGGER_PATH
super().__init__(request, pytester)
super().__init__(request, pytester, AllurePytestRunner.LOGGER_PATH)
self.select_plugins("allure_pytest")

def enable_plugins(self, *plugins: str) -> None:
Expand Down Expand Up @@ -159,11 +158,7 @@ def run_pytest(
*cli_args
]
self.__generate_testfiles(testfile_literals)
return self._run(
pytest_args,
testplan_content=testplan,
logger_path=self.logger_path
)
return self._run(pytest_args, testplan_content=testplan)

def _run_framework(self, options):
with altered_env(PYTEST_DISABLE_PLUGIN_AUTOLOAD="true"):
Expand Down
2 changes: 1 addition & 1 deletion tests/allure_pytest_bdd/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
@pytest.fixture
def allure_pytest_bdd_runner(request, pytester):
runner = AllurePytestRunner(request, pytester)
runner.logger_path = "allure_pytest_bdd.plugin.AllureFileLogger"
runner.imported_logger_paths = ["allure_pytest_bdd.plugin.AllureFileLogger"]
runner.select_plugins("pytest-bdd", "allure_pytest_bdd")
yield runner
3 changes: 1 addition & 2 deletions tests/allure_robotframework/robot_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class AllureRobotRunner(AllureFrameworkRunner):
LOGGER_PATH = "allure_robotframework.robot_listener.AllureFileLogger"

def __init__(self, request: FixtureRequest, pytester: Pytester):
super().__init__(request, pytester)
super().__init__(request, pytester, AllureRobotRunner.LOGGER_PATH)

def run_robotframework(
self,
Expand Down Expand Up @@ -75,7 +75,6 @@ def run_robotframework(
testplan_content=testplan_content,
testplan_path=testplan_path,
testplan_rst_id=testplan_rst_id,
logger_path=AllureRobotRunner.LOGGER_PATH,
options=self.__resolve_options(options)
)

Expand Down
59 changes: 39 additions & 20 deletions tests/e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import shutil
import warnings
from abc import abstractmethod
from contextlib import contextmanager
from contextlib import contextmanager, ExitStack
from pathlib import Path
from pytest import FixtureRequest, Pytester, MonkeyPatch
from typing import Tuple, Mapping, TypeVar, Generator, Callable, Union
Expand Down Expand Up @@ -54,7 +54,7 @@ def allure_plugin_context():

@contextmanager
def allure_in_memory_context(
path: str = None
*paths: str
) -> Generator[AllureMemoryLogger, None, None]:
"""Creates a context to test an allure integration.

Expand All @@ -70,28 +70,30 @@ def allure_in_memory_context(
restored.

Arguments:
path (str): a path to a class to replace.
Defaults to :code:`"allure_commons.logger.AllureFileLogger"`.
Provide this argument if the integration under test imports the
logger using the
:code:`from allure_commons.logger import AllureFileLogger` syntax.
*paths (str): paths to classes to replace with the in-memory logger in
addition to :code:`"allure_commons.logger.AllureFileLogger"`.
Provide these if the integration under test imports the logger using
the :code:`from allure_commons.logger import AllureFileLogger`
syntax.

Yields:
AllureMemoryLogger: an instance of the in-memory logger, where an output
will be collected.
AllureMemoryLogger: an instance of the in-memory logger, where the
output is collected.

"""

if path is None:
path = "allure_commons.logger.AllureFileLogger"

# Plugin context must be set first, because mock patching may cause
# module loading, thus, side effects, including allure decorators evaluation
# (and that requires all plugins of nested allure to already be in place).
paths = ("allure_commons.logger.AllureFileLogger",) + paths
with allure_plugin_context():
with mock.patch(path) as ReporterMock:
ReporterMock.return_value = AllureMemoryLogger()
yield ReporterMock.return_value
logger = AllureMemoryLogger()
with ExitStack() as stack:
for path in paths:
stack.enter_context(
mock.patch(path)
).return_value = logger
yield logger


class AllureFileContextValue:
Expand Down Expand Up @@ -336,20 +338,38 @@ class AllureFrameworkRunner:
"""An abstract base class for framework test runners to test allure
integrations.

Attributes:
request (FixtureRequest): an instance of the request fixture.
pytester (Pytester): an instance of the pytester fixture.
allure_results (AllureMemoryLogger | AllureReport): the latest collected
allure results.
in_memory (bool): if `True`, the next run collects the results in memory
(:attr:`AllureFrameworkRunner.allure_results` is AllureMemoryLogger).
Otherwise, the next run creates allure result files and collects the
report from them
(:attr:`AllureFrameworkRunner.allure_results` is AllureReport).
*imported_logger_paths: a sequence of paths to provide to
:func:`allure_in_memory_context`.

"""
def __init__(self, request: FixtureRequest, pytester: Pytester):
def __init__(
self,
request: FixtureRequest,
pytester: Pytester,
*imported_logger_paths
):
self.request = request
self.pytester = pytester
self.allure_results = None
self.in_memory = True
self.imported_logger_paths = list(imported_logger_paths)

def _run(
self,
*args,
testplan_content: dict = None,
testplan_path: PathlikeT = None,
testplan_rst_id: str = None,
logger_path: str = None,
**kwargs
) -> AllureMemoryLogger:
"""Runs the framework and collect the allure results.
Expand Down Expand Up @@ -380,7 +400,6 @@ def _run(
)
with altered_env(ALLURE_TESTPLAN_PATH=testplan_path):
output = self.__run_and_collect_results_in_memory(
logger_path,
args,
kwargs
) if self.in_memory else self.__run_and_collect_results_from_fs(
Expand Down Expand Up @@ -572,8 +591,8 @@ def _cache_docstring_test_result(
node.stash[cache_key] = result
return result

def __run_and_collect_results_in_memory(self, logger_path, args, kwargs):
with allure_in_memory_context(logger_path) as output:
def __run_and_collect_results_in_memory(self, args, kwargs):
with allure_in_memory_context(*self.imported_logger_paths) as output:
self._run_framework(*args, **kwargs)
return output

Expand Down