Skip to content

Commit 1c69639

Browse files
author
Sylvain MARIE
committed
The ids arguments of fixture_union, param_fixture[s], etc. now also support infinite generators. Improved fix for #148
1 parent b996c20 commit 1c69639

File tree

5 files changed

+57
-27
lines changed

5 files changed

+57
-27
lines changed

pytest_cases/common_pytest.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,8 @@ def make_test_ids(global_ids, id_marks, argnames=None, argvalues=None, precomput
223223
"""
224224
if global_ids is not None:
225225
# overridden at global pytest.mark.parametrize level - this takes precedence.
226-
try: # an explicit list of ids ?
227-
p_ids = list(id for id, v in zip(global_ids, argvalues))
228-
except TypeError: # a callable to apply on the values
229-
p_ids = list(global_ids(v) for v in argvalues)
226+
# resolve possibly infinite generators of ids here
227+
p_ids = resolve_ids(global_ids, argvalues)
230228
else:
231229
# default: values-based
232230
if precomputed_ids is not None:
@@ -243,6 +241,16 @@ def make_test_ids(global_ids, id_marks, argnames=None, argvalues=None, precomput
243241
return p_ids
244242

245243

244+
def resolve_ids(ids, argvalues):
245+
"""Returns the list of ids to use by a parametrized fixture, based on the `ids` parameter and the `argvalues`"""
246+
247+
try: # an explicit list or generator of ids ?
248+
p_ids = list(id for id, v in zip(ids, argvalues))
249+
except TypeError: # a callable to apply on the values
250+
p_ids = list(ids(v) for v in argvalues)
251+
return p_ids
252+
253+
246254
def make_test_ids_from_param_values(param_names,
247255
param_values,
248256
):

pytest_cases/fixture_core1_unions.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
from funcsigs import signature, Parameter # noqa
1818

1919
try: # type hints, python 3+
20-
from typing import Callable, Union, Optional, Any, List, Iterable, Sequence # noqa
20+
from typing import Callable, Union, Optional, Any, List, Iterable, Sequence, Generator # noqa
2121
from types import ModuleType # noqa
2222
except ImportError:
2323
pass
2424

2525
from .common_mini_six import string_types
2626
from .common_pytest import get_fixture_name, is_marked_parameter_value, get_marked_parameter_values, pytest_fixture, \
27-
extract_parameterset_info, get_param_argnames_as_list, get_fixture_scope
27+
extract_parameterset_info, get_param_argnames_as_list, get_fixture_scope, resolve_ids
2828
from .fixture__creation import get_caller_module, check_name_available, WARN
2929

3030

@@ -208,7 +208,7 @@ def fixture_union(name, # type: str
208208
fixtures, # type: Iterable[Union[str, Callable]]
209209
scope="function", # type: str
210210
idstyle='explicit', # type: Optional[str]
211-
ids=None, # type: Union[Callable, List[str]]
211+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
212212
unpack_into=None, # type: Iterable[str]
213213
autouse=False, # type: bool
214214
hook=None, # type: Callable[[Callable], Callable]
@@ -292,7 +292,7 @@ def _fixture_union(fixtures_dest,
292292
unique_fix_alt_names, # type: List[str]
293293
scope="function", # type: str
294294
idstyle="explicit", # type: str
295-
ids=None, # type: Union[Callable, List[str]]
295+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
296296
autouse=False, # type: bool
297297
hook=None, # type: Callable[[Callable], Callable]
298298
caller=fixture_union, # type: Callable
@@ -338,9 +338,15 @@ def _new_fixture(request, **all_fixtures):
338338
raise TypeError("Union Fixture %s received invalid parameter type: %s. Please report this issue."
339339
"" % (name, _alternative.__class__))
340340

341+
if ids is None:
342+
ids = UnionIdMakers.get(idstyle)
343+
else:
344+
# resolve possibly infinite generators of ids here
345+
ids = resolve_ids(ids, fix_alternatives)
346+
341347
# finally create the fixture per se.
342348
_make_fix = pytest_fixture(scope=scope, params=fix_alternatives, autouse=autouse,
343-
ids=ids or UnionIdMakers.get(idstyle), hook=hook, **kwargs)
349+
ids=ids, hook=hook, **kwargs)
344350
new_union_fix = _make_fix(_new_fixture)
345351

346352
# Dynamically add fixture to caller's module as explained in https://github.com/pytest-dev/pytest/issues/2424

pytest_cases/fixture_core2.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,23 @@
2020
from funcsigs import signature, Parameter # noqa
2121

2222
try: # type hints, python 3+
23-
from typing import Callable, Union, Any, List, Iterable, Sequence # noqa
23+
from typing import Callable, Union, Any, List, Iterable, Sequence, Generator # noqa
2424
from types import ModuleType # noqa
2525
except ImportError:
2626
pass
2727

2828
from .common_pytest_lazy_values import get_lazy_args
2929
from .common_pytest import get_pytest_parametrize_marks, make_marked_parameter_value, get_param_argnames_as_list, \
30-
analyze_parameter_set, combine_ids, is_marked_parameter_value, get_marked_parameter_values, pytest_fixture
30+
analyze_parameter_set, combine_ids, is_marked_parameter_value, get_marked_parameter_values, pytest_fixture, \
31+
resolve_ids
3132
from .fixture__creation import get_caller_module, check_name_available, WARN, CHANGE
3233
from .fixture_core1_unions import ignore_unused, is_used_request, NOT_USED, _make_unpack_fixture
3334

3435

3536
def param_fixture(argname, # type: str
3637
argvalues, # type: Iterable[Any]
3738
autouse=False, # type: bool
38-
ids=None, # type: Union[Callable, List[str]]
39+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
3940
scope="function", # type: str
4041
hook=None, # type: Callable[[Callable], Callable]
4142
debug=False, # type: bool
@@ -89,7 +90,7 @@ def _create_param_fixture(fixtures_dest,
8990
argname, # type: str
9091
argvalues, # type: Sequence[Any]
9192
autouse=False, # type: bool
92-
ids=None, # type: Union[Callable, List[str]]
93+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
9394
scope="function", # type: str
9495
hook=None, # type: Callable[[Callable], Callable]
9596
auto_simplify=False,
@@ -134,7 +135,7 @@ def __param_fixture(request):
134135
def param_fixtures(argnames, # type: str
135136
argvalues, # type: Iterable[Any]
136137
autouse=False, # type: bool
137-
ids=None, # type: Union[Callable, List[str]]
138+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
138139
scope="function", # type: str
139140
hook=None, # type: Callable[[Callable], Callable]
140141
debug=False, # type: bool
@@ -192,7 +193,7 @@ def _create_params_fixture(fixtures_dest,
192193
argnames_lst, # type: Sequence[str]
193194
argvalues, # type: Sequence[Any]
194195
autouse=False, # type: bool
195-
ids=None, # type: Union[Callable, List[str]]
196+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
196197
scope="function", # type: str
197198
hook=None, # type: Callable[[Callable], Callable]
198199
debug=False, # type: bool
@@ -377,6 +378,11 @@ def _decorate_fixture_plus(fixture_func,
377378
# make the fixture union-aware
378379
wrapped_fixture_func = ignore_unused(fixture_func)
379380

381+
# resolve possibly infinite generators of ids here
382+
if 'params' in kwargs and 'ids' in kwargs:
383+
if kwargs['ids'] is not None:
384+
kwargs['ids'] = resolve_ids(kwargs['ids'], kwargs['params'])
385+
380386
# transform the created wrapper into a fixture
381387
return pytest_fixture(scope=scope, autouse=autouse, hook=hook, **kwargs)(wrapped_fixture_func)
382388

pytest_cases/fixture_parametrize_plus.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def _fixture_product(fixtures_dest,
3939
fixtures_or_values,
4040
fixture_positions,
4141
scope="function", # type: str
42-
ids=None, # type: Union[Callable, List[str]]
42+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
4343
unpack_into=None, # type: Iterable[str]
4444
autouse=False, # type: bool
4545
hook=None, # type: Callable[[Callable], Callable]
@@ -378,7 +378,7 @@ def __repr__(self):
378378
def _parametrize_plus(argnames=None,
379379
argvalues=None,
380380
indirect=False, # type: bool
381-
ids=None, # type: Union[Callable, List[str]]
381+
ids=None, # type: Union[Callable, List[str], Generator[str, None, None]]
382382
idstyle='explicit', # type: str
383383
idgen=_IDGEN, # type: Union[str, Callable]
384384
scope=None, # type: str
Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
11
import itertools as itt
22

3-
from pytest_cases import parametrize, fixture
3+
from pytest_cases import parametrize, fixture, param_fixtures, fixture_union
44

55

6-
def mygen():
6+
def mygen(name):
77
"""An infinite generator of ids"""
88
for i in itt.count():
9-
yield "x{%i}" % i
9+
yield "%s{%i}" % (name, i)
1010

1111

1212
@fixture()
13-
@parametrize("y", [0, 1], ids=("x{%i}" % i for i in itt.count()))
14-
@parametrize("x", [1, 2], ids=mygen())
13+
@parametrize("y", [0, 1], ids=("y{%i}" % i for i in itt.count()))
14+
@parametrize("x", [1, 2], ids=mygen("x"))
1515
def my_fixture(x, y):
1616
return x, y
1717

1818

19-
def test_foo(my_fixture):
19+
a = param_fixtures("a", ['aa', 'ab'], ids=mygen("a"))
20+
21+
22+
my_union = fixture_union("my_union", [a], ids=mygen("myunion"))
23+
24+
25+
def test_foo(my_fixture, my_union, a):
2026
pass
2127

2228

2329
def test_synthesis(module_results_dct):
2430
assert list(module_results_dct) == [
25-
'test_foo[x{0}-x{0}]',
26-
'test_foo[x{0}-x{1}]',
27-
'test_foo[x{1}-x{0}]',
28-
'test_foo[x{1}-x{1}]'
31+
'test_foo[x{0}-y{0}-myunion{0}-a{0}]',
32+
'test_foo[x{0}-y{0}-myunion{0}-a{1}]',
33+
'test_foo[x{0}-y{1}-myunion{0}-a{0}]',
34+
'test_foo[x{0}-y{1}-myunion{0}-a{1}]',
35+
'test_foo[x{1}-y{0}-myunion{0}-a{0}]',
36+
'test_foo[x{1}-y{0}-myunion{0}-a{1}]',
37+
'test_foo[x{1}-y{1}-myunion{0}-a{0}]',
38+
'test_foo[x{1}-y{1}-myunion{0}-a{1}]'
2939
]

0 commit comments

Comments
 (0)