Skip to content

Commit 4598820

Browse files
author
Sylvain MARIE
committed
Fixed compatibility with pytest 2.x
1 parent c4515dd commit 4598820

File tree

3 files changed

+66
-29
lines changed

3 files changed

+66
-29
lines changed

pytest_cases/common.py

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from warnings import warn
88

99
import pytest
10-
from _pytest.mark import ParameterSet
10+
1111

1212
# Create a symbol that will work to create a fixture containing 'yield', whatever the pytest version
1313
# Note: if more prevision is needed, use if LooseVersion(pytest.__version__) < LooseVersion('3.0.0')
@@ -79,9 +79,17 @@ def get_pytest_parametrize_marks(f):
7979
mark_info = getattr(f, 'parametrize', None)
8080
if mark_info is not None:
8181
# mark_info.args contains a list of (name, values)
82-
return tuple(_ParametrizationMark(_LegacyMark(mark_info.args[2*i], mark_info.args[2*i + 1],
83-
**mark_info.kwargs))
84-
for i in range(len(mark_info.args) // 2))
82+
if len(mark_info.args) % 2 != 0:
83+
raise ValueError("internal pytest compatibility error - please report")
84+
nb_parameters = len(mark_info.args) // 2
85+
if nb_parameters > 1 and len(mark_info.kwargs) > 0:
86+
raise ValueError("Unfortunately with this old pytest version it is not possible to have several "
87+
"parametrization decorators")
88+
res = []
89+
for i in range(nb_parameters):
90+
param_name, param_values = mark_info.args[2*i:2*(i+1)]
91+
res.append(_ParametrizationMark(_LegacyMark(param_name, param_values, **mark_info.kwargs)))
92+
return tuple(res)
8593
else:
8694
return ()
8795

@@ -126,16 +134,28 @@ def get_test_ids_from_param_values(param_names,
126134

127135

128136
# ---- ParameterSet api ---
129-
def is_marked_parameter_value(v):
130-
return isinstance(v, ParameterSet)
137+
try: # pytest 3.x+
138+
from _pytest.mark import ParameterSet
139+
def is_marked_parameter_value(v):
140+
return isinstance(v, ParameterSet)
141+
142+
def get_marked_parameter_marks(v):
143+
return v.marks
144+
145+
def get_marked_parameter_values(v):
146+
return v.values
131147

148+
except ImportError: # pytest 2.x
149+
from _pytest.mark import MarkDecorator
132150

133-
def get_marked_parameter_marks(v):
134-
return v.marks
151+
def is_marked_parameter_value(v):
152+
return isinstance(v, MarkDecorator)
135153

154+
def get_marked_parameter_marks(v):
155+
return [v]
136156

137-
def get_marked_parameter_values(v):
138-
return v.values
157+
def get_marked_parameter_values(v):
158+
return v.args[1:]
139159

140160

141161
# ---- tools to reapply marks on test parameter values, whatever the pytest version ----
@@ -180,18 +200,22 @@ def transform_marks_into_decorators(marks):
180200
try:
181201
for m in marks:
182202
md = pytest.mark.MarkDecorator()
183-
if LooseVersion(pytest.__version__) >= LooseVersion('3.0.0'):
184-
md.mark = m
203+
if isinstance(m, type(md)):
204+
# already a decorator, we can use it
205+
marks_mod.append(m)
185206
else:
186-
md.name = m.name
187-
# md.markname = m.name
188-
md.args = m.args
189-
md.kwargs = m.kwargs
190-
191-
# markinfodecorator = getattr(pytest.mark, markinfo.name)
192-
# markinfodecorator(*markinfo.args)
193-
194-
marks_mod.append(md)
207+
if LooseVersion(pytest.__version__) >= LooseVersion('3.0.0'):
208+
md.mark = m
209+
else:
210+
md.name = m.name
211+
# md.markname = m.name
212+
md.args = m.args
213+
md.kwargs = m.kwargs
214+
215+
# markinfodecorator = getattr(pytest.mark, markinfo.name)
216+
# markinfodecorator(*markinfo.args)
217+
218+
marks_mod.append(md)
195219
except Exception as e:
196220
warn("Caught exception while trying to mark case: [%s] %s" % (type(e), e))
197221
return marks_mod

pytest_cases/main.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,9 @@ def pytest_fixture_plus(scope="function",
309309
try:
310310
paramids = tuple(m.param_ids)
311311
except TypeError:
312-
paramids = tuple(m.param_ids(v) for v in m.param_values)
312+
paramids = tuple(m.param_ids(v) for v in _pvalues)
313313
else:
314-
paramids = get_test_ids_from_param_values(_pnames, m.param_values)
314+
paramids = get_test_ids_from_param_values(_pnames, _pvalues)
315315
params_ids.append(paramids)
316316

317317
# (3) generate the ids and values, possibly reapplying marks
@@ -336,6 +336,9 @@ def pytest_fixture_plus(scope="function",
336336
if len(ms) > 0:
337337
final_values[i] = make_marked_parameter_value(final_values[i], marks=ms)
338338

339+
if len(final_values) != len(final_ids):
340+
raise ValueError("Internal error related to fixture parametrization- please report")
341+
339342
# (4) wrap the fixture function so as to remove the parameter names and add 'request' if needed
340343
all_param_names = tuple(v for l in params_names_or_name_combinations for v in l)
341344

pytest_cases/tests/simple/test_fixtures.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from distutils.version import LooseVersion
12
import pytest
23
from pytest_cases.tests.simple import test_main_cases
34

@@ -42,12 +43,21 @@ def test_with_cases_decorated_legacy(my_case_fixture_legacy):
4243
err_checker(err_info.value)
4344

4445

45-
@pytest_fixture_plus
46-
@cases_data(module=test_main_cases)
47-
@pytest.mark.parametrize('a', [True])
48-
def my_case_fixture(case_data, a, request):
49-
"""Getting data will now be executed BEFORE the test (outside of the test duration)"""
50-
return case_data.get()
46+
if LooseVersion(pytest.__version__) >= LooseVersion('3.0.0'):
47+
@pytest_fixture_plus
48+
@cases_data(module=test_main_cases)
49+
@pytest.mark.parametrize('a', [True])
50+
def my_case_fixture(case_data, a, request):
51+
"""Getting data will now be executed BEFORE the test (outside of the test duration)"""
52+
return case_data.get()
53+
else:
54+
# we cant double-parametrize with pytest 2.x: the ids get messed up
55+
@pytest_fixture_plus
56+
@cases_data(module=test_main_cases)
57+
# @pytest.mark.parametrize('a', [True])
58+
def my_case_fixture(case_data, request):
59+
"""Getting data will now be executed BEFORE the test (outside of the test duration)"""
60+
return case_data.get()
5161

5262

5363
def test_with_cases_decorated(my_case_fixture):

0 commit comments

Comments
 (0)