Skip to content

Commit 08145b1

Browse files
authored
refactoring of function parameters handling (fixes allure-framework#220 fixes allure-framework#227 closes allure-framework#221 via allure-framework#242)
1 parent 1929847 commit 08145b1

8 files changed

Lines changed: 240 additions & 54 deletions

File tree

allure-behave/src/listener.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __del__(self):
4343

4444
@allure_commons.hookimpl
4545
def start_fixture(self, parent_uuid, uuid, name, parameters):
46-
parameters = [Parameter(name=param_name, value=param_value) for param_name, param_value in parameters]
46+
parameters = [Parameter(name=param_name, value=param_value) for param_name, param_value in parameters.items()]
4747

4848
if name in FIXTURES and not self.fixture_context:
4949
group = TestResultContainer(uuid=uuid4())
@@ -153,7 +153,7 @@ def flush_steps(self):
153153

154154
@allure_commons.hookimpl
155155
def start_step(self, uuid, title, params):
156-
parameters = [Parameter(name=name, value=value) for name, value in params]
156+
parameters = [Parameter(name=name, value=value) for name, value in params.items()]
157157
step = TestStepResult(name=title, start=now(), parameters=parameters)
158158
self.logger.start_step(None, uuid, step)
159159

allure-pytest/src/listener.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(self, config):
3333

3434
@allure_commons.hookimpl
3535
def start_step(self, uuid, title, params):
36-
parameters = [Parameter(name=name, value=value) for name, value in params]
36+
parameters = [Parameter(name=name, value=value) for name, value in params.items()]
3737
step = TestStepResult(name=title, start=now(), parameters=parameters)
3838
self.allure_logger.start_step(None, uuid, step)
3939

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import allure
2+
3+
4+
@allure.step("First step")
5+
def step_with_parameters(arg_param, kwarg_param=None):
6+
pass
7+
8+
9+
def test_defined_default_parameter():
10+
"""
11+
>>> from allure_commons.utils import represent
12+
>>> allure_report = getfixture('allure_report')
13+
>>> assert_that(allure_report,
14+
... has_test_case('test_defined_default_parameter',
15+
... has_step('First step',
16+
... has_parameter('arg_param', represent(1)),
17+
... has_parameter('kwarg_param', represent(2)),
18+
... )
19+
... )
20+
... )
21+
"""
22+
step_with_parameters(1, kwarg_param=2)
23+
24+
25+
def test_not_defined_default_parameter():
26+
"""
27+
>>> from allure_commons.utils import represent
28+
>>> allure_report = getfixture('allure_report')
29+
>>> assert_that(allure_report,
30+
... has_test_case('test_not_defined_default_parameter',
31+
... has_step('First step',
32+
... has_parameter('arg_param', represent(1)),
33+
... has_parameter('kwarg_param', represent(None)),
34+
... )
35+
... )
36+
... )
37+
"""
38+
step_with_parameters(1)
39+
40+
41+
def test_default_parameter_in_args():
42+
"""
43+
>>> from allure_commons.utils import represent
44+
>>> allure_report = getfixture('allure_report')
45+
>>> assert_that(allure_report,
46+
... has_test_case('test_default_parameter_in_args',
47+
... has_step('First step',
48+
... has_parameter('arg_param', represent(1)),
49+
... has_parameter('kwarg_param', represent(2)),
50+
... )
51+
... )
52+
... )
53+
"""
54+
step_with_parameters(1, 2)

allure-pytest/test/steps/parameters/step_parameters_test.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
"""
3-
>>> allure_report = getfixture('allure_report')
4-
"""
52

63
import allure
74
from struct import pack
@@ -12,23 +9,6 @@ def step_with_parameters(arg_param, default_parameter=777, kwarg_parameter=None)
129
pass
1310

1411

15-
def test_primitive_type_parameters():
16-
"""
17-
>>> from allure_commons.utils import represent
18-
>>> allure_report = getfixture('allure_report')
19-
>>> assert_that(allure_report,
20-
... has_test_case('test_primitive_type_parameters',
21-
... has_step('First step',
22-
... has_parameter('arg_param', represent(False)),
23-
... has_parameter('default_parameter', represent(777)),
24-
... has_parameter('kwarg_parameter', represent(555)),
25-
... )
26-
... )
27-
... )
28-
"""
29-
step_with_parameters(False, kwarg_parameter=555)
30-
31-
3212
def test_binary_type_parameters():
3313
"""
3414
>>> from struct import pack
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import allure
2+
3+
TEMPLATE = "{1} and {kwarg}"
4+
5+
6+
class TestClass(object):
7+
8+
@allure.step(title=TEMPLATE)
9+
def step_method(self, arg, kwarg=2):
10+
pass
11+
12+
def test_step_method_placeholders(self):
13+
"""
14+
>>> allure_report = getfixture('allure_report')
15+
>>> assert_that(allure_report,
16+
... has_test_case('test_step_method_placeholders',
17+
... has_step(TEMPLATE.format("self", 1, kwarg=2))
18+
... )
19+
... )
20+
"""
21+
self.step_method(1)

allure-pytest/tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ commands =
4444
# `tox -e demo -- -k test_single_feature_label` or
4545
# `tox -e demo -- ./test/steps/`
4646
[testenv:demo]
47-
#basepython = python3.5
47+
basepython = python3.5
4848

4949
passenv = HOME
5050

allure-python-commons/src/_allure.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from allure_commons._core import plugin_manager
44
from allure_commons.types import LabelType, LinkType
55
from allure_commons.utils import uuid4
6-
from allure_commons.utils import func_parameters
6+
from allure_commons.utils import func_parameters, represent
77

88

99
def safely(result):
@@ -112,9 +112,9 @@ def testcase(url, name=None):
112112

113113
def step(title):
114114
if callable(title):
115-
return StepContext(title.__name__, ({}, {}))(title)
115+
return StepContext(title.__name__, {})(title)
116116
else:
117-
return StepContext(title, ({}, {}))
117+
return StepContext(title, {})
118118

119119

120120
class StepContext:
@@ -125,10 +125,7 @@ def __init__(self, title, params):
125125
self.uuid = uuid4()
126126

127127
def __enter__(self):
128-
args, kwargs = self.params
129-
args.update(kwargs)
130-
params = list(args.items())
131-
plugin_manager.hook.start_step(uuid=self.uuid, title=self.title, params=params)
128+
plugin_manager.hook.start_step(uuid=self.uuid, title=self.title, params=self.params)
132129

133130
def __exit__(self, exc_type, exc_val, exc_tb):
134131
plugin_manager.hook.stop_step(uuid=self.uuid, title=self.title, exc_type=exc_type, exc_val=exc_val,
@@ -139,8 +136,8 @@ def __call__(self, func):
139136
def impl(*a, **kw):
140137
__tracebackhide__ = True
141138
params = func_parameters(func, *a, **kw)
142-
args, kwargs = params
143-
with StepContext(self.title.format(*args.values(), **kwargs), params):
139+
args = list(map(lambda x: represent(x), a))
140+
with StepContext(self.title.format(*args, **params), params):
144141
return func(*a, **kw)
145142
return impl
146143

@@ -166,9 +163,7 @@ def __init__(self, fixture_function, parent_uuid=None, name=None):
166163
self.parameters = None
167164

168165
def __call__(self, *args, **kwargs):
169-
_args, _kwargs = func_parameters(self._fixture_function, *args, **kwargs)
170-
_args.update(kwargs)
171-
self.parameters = list(_args.items())
166+
self.parameters = func_parameters(self._fixture_function, *args, **kwargs)
172167

173168
with self:
174169
return self._fixture_function(*args, **kwargs)
@@ -196,9 +191,7 @@ def __init__(self, _test, context):
196191
self.parameters = None
197192

198193
def __call__(self, *args, **kwargs):
199-
_args, _kwargs = func_parameters(self._test, *args, **kwargs)
200-
_args.update(_kwargs)
201-
self.parameters = list(_args.items())
194+
self.parameters = func_parameters(self._test, *args, **kwargs)
202195

203196
with self:
204197
return self._test(*args, **kwargs)

allure-python-commons/src/utils.py

Lines changed: 153 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,21 +106,159 @@ def represent(item):
106106
return repr(item)
107107

108108

109-
def func_parameters(func, *a, **kw):
110-
bowels = inspect.getargspec(func) if sys.version_info.major < 3 else inspect.getfullargspec(func)
111-
args_dict = dict(zip(bowels.args, map(represent, a)))
112-
try:
113-
del args_dict["self"]
114-
except KeyError:
115-
pass
116-
kwargs_dict = dict(zip(kw, list(map(lambda i: represent(kw[i]), kw))))
117-
try:
118-
del kwargs_dict["self"]
119-
except KeyError:
120-
pass
121-
kwarg_defaults = dict(zip(reversed(bowels.args), reversed(list(map(represent, bowels.defaults or ())))))
122-
kwarg_defaults.update(kwargs_dict)
123-
return args_dict, kwarg_defaults
109+
def func_parameters(func, *args, **kwargs):
110+
"""
111+
>>> def helper(func):
112+
... def wrapper(*args, **kwargs):
113+
... params = func_parameters(func, *args, **kwargs)
114+
... print(sorted(params.items()))
115+
... return func(*args, **kwargs)
116+
... return wrapper
117+
118+
>>> @helper
119+
... def args(a, b):
120+
... pass
121+
122+
>>> args(1, 2)
123+
[('a', '1'), ('b', '2')]
124+
125+
>>> args(*(1,2))
126+
[('a', '1'), ('b', '2')]
127+
128+
>>> args(1, b=2)
129+
[('a', '1'), ('b', '2')]
130+
131+
>>> @helper
132+
... def kwargs(a=1, b=2):
133+
... pass
134+
135+
>>> kwargs()
136+
[('a', '1'), ('b', '2')]
137+
138+
>>> kwargs(a=3, b=4)
139+
[('a', '3'), ('b', '4')]
140+
141+
>>> kwargs(b=4, a=3)
142+
[('a', '3'), ('b', '4')]
143+
144+
>>> kwargs(a=3)
145+
[('a', '3'), ('b', '2')]
146+
147+
>>> kwargs(b=4)
148+
[('a', '1'), ('b', '4')]
149+
150+
>>> @helper
151+
... def args_kwargs(a, b, c=3, d=4):
152+
... pass
153+
154+
>>> args_kwargs(1, 2)
155+
[('a', '1'), ('b', '2'), ('c', '3'), ('d', '4')]
156+
157+
>>> args_kwargs(1, 2, d=5)
158+
[('a', '1'), ('b', '2'), ('c', '3'), ('d', '5')]
159+
160+
>>> args_kwargs(1, 2, 5, 6)
161+
[('a', '1'), ('b', '2'), ('c', '5'), ('d', '6')]
162+
163+
>>> @helper
164+
... def varargs(*a):
165+
... pass
166+
167+
>>> varargs()
168+
[]
169+
170+
>>> varargs(1, 2)
171+
[('a', '(1, 2)')]
172+
173+
>>> @helper
174+
... def keywords(**a):
175+
... pass
176+
177+
>>> keywords()
178+
[]
179+
180+
>>> keywords(a=1, b=2)
181+
[('a', '1'), ('b', '2')]
182+
183+
>>> @helper
184+
... def args_varargs(a, b, *c):
185+
... pass
186+
187+
>>> args_varargs(1, 2)
188+
[('a', '1'), ('b', '2')]
189+
190+
>>> args_varargs(1, 2, 2)
191+
[('a', '1'), ('b', '2'), ('c', '(2,)')]
192+
193+
>>> @helper
194+
... def args_kwargs_varargs(a, b, c=3, **d):
195+
... pass
196+
197+
>>> args_kwargs_varargs(1, 2)
198+
[('a', '1'), ('b', '2'), ('c', '3')]
199+
200+
>>> args_kwargs_varargs(1, 2, 4, d=5, e=6)
201+
[('a', '1'), ('b', '2'), ('c', '4'), ('d', '5'), ('e', '6')]
202+
203+
>>> @helper
204+
... def args_kwargs_varargs_keywords(a, b=2, *c, **d):
205+
... pass
206+
207+
208+
>>> args_kwargs_varargs_keywords(1)
209+
[('a', '1'), ('b', '2')]
210+
211+
>>> args_kwargs_varargs_keywords(1, 2, 4, d=5, e=6)
212+
[('a', '1'), ('b', '2'), ('c', '(4,)'), ('d', '5'), ('e', '6')]
213+
214+
215+
>>> class Class(object):
216+
... @staticmethod
217+
... @helper
218+
... def static_args(a, b):
219+
... pass
220+
...
221+
... @classmethod
222+
... @helper
223+
... def method_args(cls, a, b):
224+
... pass
225+
...
226+
... @helper
227+
... def args(self, a, b):
228+
... pass
229+
230+
>>> cls = Class()
231+
232+
>>> cls.args(1, 2)
233+
[('a', '1'), ('b', '2')]
234+
235+
>>> cls.method_args(1, 2)
236+
[('a', '1'), ('b', '2')]
237+
238+
>>> cls.static_args(1, 2)
239+
[('a', '1'), ('b', '2')]
240+
241+
"""
242+
parameters = {}
243+
arg_spec = inspect.getargspec(func) if sys.version_info.major < 3 else inspect.getfullargspec(func)
244+
args_dict = dict(zip(arg_spec.args, args))
245+
246+
if arg_spec.defaults:
247+
kwargs_defaults_dict = dict(zip(arg_spec.args[len(args):], arg_spec.defaults))
248+
parameters.update(kwargs_defaults_dict)
249+
250+
if arg_spec.varargs:
251+
varargs = args[len(arg_spec.args):]
252+
parameters.update({arg_spec.varargs: varargs} if varargs else {})
253+
254+
if arg_spec.args and arg_spec.args[0] in ['cls', 'self']:
255+
args_dict.pop(arg_spec.args[0], None)
256+
257+
parameters.update(kwargs)
258+
parameters.update(args_dict)
259+
260+
items = parameters.iteritems() if sys.version_info.major < 3 else parameters.items()
261+
return dict(map(lambda kv: (kv[0], represent(kv[1])), items))
124262

125263

126264
def format_traceback(exc_traceback):

0 commit comments

Comments
 (0)