Skip to content

Commit dae377f

Browse files
authored
add hook implementation (fixes #321 fixes #378 via #383)
2 parents 4cd702c + e07a148 commit dae377f

File tree

4 files changed

+91
-16
lines changed

4 files changed

+91
-16
lines changed

allure-behave/src/hooks.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import inspect
2+
import threading
3+
import allure_commons
4+
from allure_commons.logger import AllureFileLogger
5+
from allure_behave.listener import AllureListener
6+
7+
HOOKS = [
8+
"before_feature",
9+
"after_feature",
10+
"before_scenario",
11+
"after_scenario",
12+
"before_step",
13+
"after_step"
14+
]
15+
16+
_storage = threading.local()
17+
18+
19+
def wrapper(original, allured):
20+
def hook(*args, **kwargs):
21+
allured(*args, **kwargs)
22+
return original(*args, **kwargs)
23+
24+
return hook
25+
26+
27+
def allure_report(result_dir="allure_results"):
28+
allure_hooks = AllureHooks(result_dir)
29+
frame = inspect.currentframe()
30+
try:
31+
for hook_name in HOOKS:
32+
if hook_name in frame.f_back.f_locals:
33+
frame.f_back.f_locals[hook_name] = wrapper(frame.f_back.f_locals[hook_name],
34+
getattr(allure_hooks, hook_name))
35+
else:
36+
frame.f_back.f_locals[hook_name] = getattr(allure_hooks, hook_name)
37+
finally:
38+
del frame
39+
40+
41+
class AllureHooks(object):
42+
def __init__(self, result_dir):
43+
self.listener = AllureListener({})
44+
45+
if not hasattr(_storage, 'file_logger'):
46+
_storage.file_logger = AllureFileLogger(result_dir)
47+
allure_commons.plugin_manager.register(_storage.file_logger)
48+
49+
allure_commons.plugin_manager.register(self.listener)
50+
51+
def before_feature(self, context, feature):
52+
self.listener.start_feature()
53+
54+
def after_feature(self, context, feature):
55+
self.listener.stop_feature()
56+
57+
def before_scenario(self, context, scenario):
58+
self.listener.start_scenario(scenario)
59+
60+
def after_scenario(self, context, scenario):
61+
self.listener.stop_scenario(scenario)
62+
63+
def before_step(self, context, step):
64+
self.listener.start_behave_step(step)
65+
66+
def after_step(self, context, step):
67+
self.listener.stop_behave_step(step)

allure-behave/src/listener.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def __init__(self, behave_config):
3333
self.behave_config = behave_config
3434
self.logger = AllureReporter()
3535
self.current_step_uuid = None
36+
self.current_scenario_uuid = None
3637
self.execution_context = Context()
3738
self.fixture_context = Context()
3839
self.steps = deque()
@@ -82,12 +83,15 @@ def stop_feature(self):
8283

8384
@allure_commons.hookimpl
8485
def start_test(self, parent_uuid, uuid, name, parameters, context):
85-
scenario = context['scenario']
86+
self.start_scenario(context['scenario'])
87+
88+
def start_scenario(self, scenario):
89+
self.current_scenario_uuid = uuid4()
8690
self.fixture_context.enter()
8791
self.execution_context.enter()
88-
self.execution_context.append(uuid)
92+
self.execution_context.append(self.current_scenario_uuid)
8993

90-
test_case = TestResult(uuid=uuid, start=now())
94+
test_case = TestResult(uuid=self.current_scenario_uuid, start=now())
9195
test_case.name = scenario_name(scenario)
9296
test_case.historyId = scenario_history_id(scenario)
9397
test_case.description = '\n'.join(scenario.description)
@@ -98,31 +102,34 @@ def start_test(self, parent_uuid, uuid, name, parameters, context):
98102
test_case.labels.append(Label(name=LabelType.FRAMEWORK, value='behave'))
99103
test_case.labels.append(Label(name=LabelType.LANGUAGE, value=platform_label()))
100104

101-
self.logger.schedule_test(uuid, test_case)
105+
self.logger.schedule_test(self.current_scenario_uuid, test_case)
102106

103107
@allure_commons.hookimpl
104108
def stop_test(self, parent_uuid, uuid, name, context, exc_type, exc_val, exc_tb):
105-
scenario = context['scenario']
109+
self.stop_scenario(context['scenario'])
110+
111+
def stop_scenario(self, scenario):
106112
if scenario.status == 'skipped' and not self.behave_config.show_skipped:
107-
self.logger.drop_test(uuid)
113+
self.logger.drop_test(self.current_scenario_uuid)
108114
else:
109115
status = scenario_status(scenario)
110116
status_details = scenario_status_details(scenario)
111117

112118
self.flush_steps()
113-
test_result = self.logger.get_test(uuid)
119+
test_result = self.logger.get_test(self.current_scenario_uuid)
114120
test_result.stop = now()
115121
test_result.status = status
116122
test_result.statusDetails = status_details
117-
self.logger.close_test(uuid)
123+
self.logger.close_test(self.current_scenario_uuid)
118124
self.current_step_uuid = None
119125

120126
for group in self.fixture_context.exit():
121-
group.children.append(uuid)
127+
group.children.append(self.current_scenario_uuid)
122128
self.logger.stop_group(group.uuid)
123129

124130
self.execution_context.exit()
125-
self.execution_context.append(uuid)
131+
self.execution_context.append(self.current_scenario_uuid)
132+
self.current_scenario_uuid = None
126133

127134
def schedule_step(self, step):
128135
self.steps.append(step)

allure-behave/src/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def get_status(exception):
8787
def step_status_details(result):
8888
if result.exception:
8989
# workaround for https://github.com/behave/behave/pull/616
90-
trace = result.exc_traceback if type(result.exc_traceback) == list else format_traceback(result.exc_traceback)
90+
trace = "\n".join(result.exc_traceback) if type(result.exc_traceback) == list else format_traceback(
91+
result.exc_traceback)
9192
return StatusDetails(message=format_exception(type(result.exception), result.exception), trace=trace)
9293

9394
elif result.status == 'undefined':

allure-behave/tox.ini

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ commands=
4141
pip uninstall -y behave
4242
pip install git+git://github.com/behave/behave.git@refs/pull/616/head
4343
rm -rf {envtmpdir}/*
44-
behave --processes 3 \
45-
--parallel-element feature \
46-
-f allure_behave.formatter:AllureFormatter \
47-
-o {envtmpdir}/allrue-result \
48-
-f pretty {posargs: ./features}
44+
behave --processes 4 \
45+
--parallel-element feature {posargs: ./features}
46+
; -f allure_behave.formatter:AllureFormatter \
47+
; -o {envtmpdir}/allrue-result \
48+
; -f pretty {posargs: ./features}
4949

5050
[testenv:behave-master]
5151
passenv = HOME

0 commit comments

Comments
 (0)