Skip to content

Commit 55aef68

Browse files
authored
Add status and trace to fixtures (#159)
1 parent b1e6fe7 commit 55aef68

File tree

7 files changed

+103
-41
lines changed

7 files changed

+103
-41
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
.DS_Store
12
.idea
23
.tox
34
.cache
45
.python-version
56

67
*.pyc
7-
*.egg-info
8+
*.egg-info
9+
10+
*/build
11+
*/dist

allure-pytest/src/listener.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
from allure_commons.types import LabelType
1616
from allure_pytest.utils import allure_labels, allure_links, pytest_markers
1717
from allure_pytest.utils import allure_full_name, allure_package
18+
from allure_pytest.utils import get_status, get_status_details
19+
from allure_pytest.utils import get_outcome_status, get_outcome_status_details
1820

1921

2022
class AllureListener(object):
2123

22-
def __init__(self, config):
23-
self.config = config
24+
def __init__(self):
2425
self.allure_logger = AllureReporter()
2526
self._cache = ItemCache()
2627

@@ -32,14 +33,10 @@ def start_step(self, uuid, title, params):
3233

3334
@allure_commons.hookimpl
3435
def stop_step(self, uuid, exc_type, exc_val, exc_tb):
35-
status = Status.PASSED
36-
if exc_type is not None:
37-
if exc_type == pytest.skip.Exception:
38-
status = Status.SKIPPED
39-
else:
40-
status = Status.FAILED
41-
42-
self.allure_logger.stop_step(uuid, stop=now(), status=status)
36+
self.allure_logger.stop_step(uuid,
37+
stop=now(),
38+
status=get_status(exc_val),
39+
statusDetails=get_status_details(exc_type, exc_val, exc_tb))
4340

4441
@allure_commons.hookimpl
4542
def start_fixture(self, parent_uuid, uuid, name):
@@ -48,7 +45,10 @@ def start_fixture(self, parent_uuid, uuid, name):
4845

4946
@allure_commons.hookimpl
5047
def stop_fixture(self, parent_uuid, uuid, name, exc_type, exc_val, exc_tb):
51-
self.allure_logger.stop_after_fixture(uuid, stop=now())
48+
self.allure_logger.stop_after_fixture(uuid,
49+
stop=now(),
50+
status=get_status(exc_val),
51+
statusDetails=get_status_details(exc_type, exc_val, exc_tb))
5252

5353
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
5454
def pytest_runtest_protocol(self, item, nextitem):
@@ -69,6 +69,9 @@ def pytest_runtest_protocol(self, item, nextitem):
6969

7070
yield
7171

72+
for name, value in item.callspec.params.items() if hasattr(item, 'callspec') else ():
73+
self.allure_logger.update_test(uuid, parameters=Parameter(name, represent(value)))
74+
7275
test_case.labels.extend([Label(name=name, value=value) for name, value in allure_labels(item)])
7376
test_case.labels.extend([Label(name=LabelType.TAG, value=value) for value in pytest_markers(item)])
7477
test_case.labels.append(Label(name=LabelType.FRAMEWORK, value='pytest'))
@@ -86,11 +89,10 @@ def pytest_runtest_protocol(self, item, nextitem):
8689
@pytest.hookimpl(hookwrapper=True)
8790
def pytest_runtest_call(self, item):
8891
uuid = self._cache.get(item.nodeid)
89-
for name, value in item.callspec.params.items() if hasattr(item, 'callspec') else ():
90-
self.allure_logger.update_test(uuid, parameters=Parameter(name, represent(value)))
91-
9292
self.allure_logger.update_test(uuid, start=now())
93+
9394
yield
95+
9496
self.allure_logger.update_test(uuid, stop=now())
9597

9698
@pytest.hookimpl(hookwrapper=True)
@@ -110,12 +112,15 @@ def pytest_fixture_setup(self, fixturedef, request):
110112
before_fixture = TestBeforeResult(name=fixture_name, start=now())
111113
self.allure_logger.start_before_fixture(container_uuid, before_fixture_uuid, before_fixture)
112114

113-
yield
115+
outcome = yield
114116

115-
self.allure_logger.stop_before_fixture(before_fixture_uuid, stop=now())
117+
self.allure_logger.stop_before_fixture(before_fixture_uuid,
118+
stop=now(),
119+
status=get_outcome_status(outcome),
120+
statusDetails=get_outcome_status_details(outcome))
116121

117122
for index, finalizer in enumerate(fixturedef._finalizer or ()):
118-
name = u'{fixture}::{finalizer}'.format(fixture=fixturedef.argname, finalizer=finalizer.__name__)
123+
name = '{fixture}::{finalizer}'.format(fixture=fixturedef.argname, finalizer=finalizer.__name__)
119124
fixturedef._finalizer[index] = allure_commons.fixture(finalizer, parent_uuid=container_uuid, name=name)
120125

121126
@pytest.hookimpl(hookwrapper=True)

allure-pytest/src/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def pytest_configure(config):
9494
allure_commons.plugin_manager.register(test_helper)
9595

9696
if report_dir:
97-
test_listener = AllureListener(config)
97+
test_listener = AllureListener()
9898
config.pluginmanager.register(test_listener)
9999
allure_commons.plugin_manager.register(test_listener)
100100

allure-pytest/src/utils.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
from __future__ import unicode_literals
33

44
import os
5+
import pytest
56
from allure_commons.utils import represent
7+
from allure_commons.utils import format_exception, format_traceback
8+
from allure_commons.model2 import Status
9+
from allure_commons.model2 import StatusDetails
10+
611

712
ALLURE_UNIQUE_LABELS = ['severity', 'thread', 'host']
813
ALLURE_LABEL_PREFIX = 'allure_label'
@@ -63,3 +68,30 @@ def allure_full_name(nodeid):
6368
clazz = '.{clazz}'.format(clazz=parts[1]) if len(parts) > 2 else ''
6469
test = parts[-1]
6570
return '{package}{clazz}#{test}'.format(package=package, clazz=clazz, test=test)
71+
72+
73+
def get_outcome_status(outcome):
74+
_, exception, _ = outcome.excinfo or (None, None, None)
75+
return get_status(exception)
76+
77+
78+
def get_outcome_status_details(outcome):
79+
exception_type, exception, exception_traceback = outcome.excinfo or (None, None, None)
80+
return get_status_details(exception_type, exception, exception_traceback)
81+
82+
83+
def get_status(exception):
84+
if exception:
85+
if isinstance(exception, AssertionError):
86+
return Status.FAILED
87+
elif isinstance(exception, pytest.skip.Exception):
88+
return Status.SKIPPED
89+
return Status.PASSED
90+
91+
92+
def get_status_details(exception_type, exception, exception_traceback):
93+
if isinstance(exception, pytest.skip.Exception):
94+
return StatusDetails(message=exception.msg)
95+
elif exception:
96+
return StatusDetails(message=format_exception(exception_type, exception),
97+
trace=format_traceback(exception_traceback))

allure-pytest/test/fixtures/function_scope/finalizers_simple_test.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111

1212

1313
@pytest.fixture
14-
def fixture_with_finalizer_a(request):
15-
def finalizer_fixture_a():
14+
def fixture_with_passed_finalizer(request):
15+
def passed_finalizer():
1616
pass
17-
request.addfinalizer(finalizer_fixture_a)
17+
request.addfinalizer(passed_finalizer)
1818

1919

2020
@pytest.fixture
21-
def fixture_with_finalizer_b(request):
22-
def finalizer_fixture_b():
23-
pass
24-
request.addfinalizer(finalizer_fixture_b)
21+
def fixture_failed_finalizer(request):
22+
def failed_finalizer():
23+
assert False
24+
request.addfinalizer(failed_finalizer)
2525

2626

2727
@pytest.fixture
@@ -35,22 +35,29 @@ def second_finalizer():
3535
request.addfinalizer(second_finalizer)
3636

3737

38-
def test_two_fixures_with_finalizer(fixture_with_finalizer_a, fixture_with_finalizer_b):
38+
def test_two_fixures_with_finalizer(fixture_with_passed_finalizer, fixture_failed_finalizer):
3939
"""
4040
>>> allure_report = getfixture('allure_report')
4141
>>> assert_that(allure_report,
4242
... has_test_case('test_two_fixures_with_finalizer',
4343
... has_container(allure_report,
44-
... has_before('fixture_with_finalizer_a'),
44+
... has_before('fixture_with_passed_finalizer'),
4545
... has_after('{fixture}::{finalizer}'.format(
46-
... fixture='fixture_with_finalizer_a',
47-
... finalizer='finalizer_fixture_a'))
46+
... fixture='fixture_with_passed_finalizer',
47+
... finalizer='passed_finalizer'),
48+
... with_status('passed')
49+
... )
4850
... ),
4951
... has_container(allure_report,
52+
... has_before('fixture_failed_finalizer'),
5053
... has_after('{fixture}::{finalizer}'.format(
51-
... has_before('fixture_with_finalizer_b'),
52-
... fixture='fixture_with_finalizer_b',
53-
... finalizer='finalizer_fixture_b'))
54+
... fixture='fixture_failed_finalizer',
55+
... finalizer='failed_finalizer'),
56+
... with_status('failed'),
57+
... has_status_details(
58+
... with_status_message('AssertionError')
59+
... )
60+
... )
5461
... )
5562
... )
5663
... )

allure-pytest/test/fixtures/function_scope/fixtures_parametrization_test.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,28 @@
1212

1313
@pytest.fixture(params=[True, False])
1414
def parametrized_fixture(request):
15-
return request.param
15+
assert request.param
1616

1717

1818
def test_function_scope_parametrized_fixture(parametrized_fixture):
1919
"""
2020
>>> allure_report = getfixture('allure_report')
21-
>>> for param in [True, False]:
21+
>>> for passed in [True, False]:
2222
... assert_that(allure_report,
23-
... has_test_case('test_function_scope_parametrized_fixture[{param}]'.format(param=param),
24-
... has_parameter('parametrized_fixture', str(param))
23+
... has_test_case('test_function_scope_parametrized_fixture[{param}]'.format(param=passed),
24+
... has_parameter('parametrized_fixture', str(passed)),
25+
... has_container(allure_report,
26+
... has_before('parametrized_fixture',
27+
... with_status('passed' if passed else 'failed'),
28+
... has_status_details(
29+
... with_status_message('AssertionError')
30+
... ) if not passed else anything()
31+
... )
32+
... )
2533
... )
2634
... )
2735
"""
28-
assert parametrized_fixture
36+
pass
2937

3038

3139
@pytest.fixture(params=[True, False], ids=['param_true', 'param_false'])
@@ -60,4 +68,4 @@ def test_two_function_scope_parametrized_fixture(parametrized_fixture, parametri
6068
... )
6169
... )
6270
"""
63-
assert parametrized_fixture_with_ids and parametrized_fixture
71+
assert parametrized_fixture_with_ids and parametrized_fixture

allure-pytest/test/status/step_status_test.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@ def test_skip_in_deep_step():
2626
... has_step('Step1',
2727
... with_status('skipped'),
2828
... has_step('Step2',
29-
... with_status('skipped')
29+
... with_status('skipped'),
30+
... has_status_details(
31+
... with_status_message('oops!')
32+
... )
3033
... )
3134
... )
3235
... )
3336
... )
3437
"""
3538
with pytest.allure.step('Step1'):
3639
with pytest.allure.step('Step2'):
37-
pytest.skip()
40+
pytest.skip('oops!')
3841

3942

4043
def test_fail_in_step_after_step():
@@ -45,6 +48,9 @@ def test_fail_in_step_after_step():
4548
... with_status('failed'),
4649
... has_step('Step1',
4750
... with_status('failed'),
51+
... has_status_details(
52+
... with_status_message('AssertionError')
53+
... ),
4854
... has_step('Step2',
4955
... with_status('passed')
5056
... )

0 commit comments

Comments
 (0)