Skip to content

Commit f220f6e

Browse files
author
Sylvain MARIE
committed
@pytest_fixture_plus now correctly handles the NOT_USED when fixtures in the union do not contain any parameter. Fixes #38
1 parent ed15c44 commit f220f6e

File tree

2 files changed

+77
-38
lines changed

2 files changed

+77
-38
lines changed

pytest_cases/main_fixtures.py

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -433,46 +433,49 @@ def _create_fixture_without_marks(fixture_func, scope, autouse, **kwargs):
433433
:param kwargs:
434434
:return:
435435
"""
436-
if 'params' not in kwargs:
437-
# -- no parametrization: shortcut
438-
fix_creator = pytest.fixture if not isgeneratorfunction(fixture_func) else yield_fixture
439-
return fix_creator(scope=scope, autouse=autouse, **kwargs)(fixture_func)
436+
# IMPORTANT: even if 'params' is not in kwargs, the fixture
437+
# can be used in a fixture union and therefore a param will be received
438+
# on some calls (and the fixture will be called several times - only once for real)
439+
# - we have to handle the NOT_USED.
440+
441+
# --create a wrapper where we will be able to auto-detect
442+
# TODO we could put this in a dedicated wrapper 'ignore_unsused'..
443+
444+
old_sig = signature(fixture_func)
445+
# add request if needed
446+
func_needs_request = 'request' in old_sig.parameters
447+
if not func_needs_request:
448+
new_sig = add_signature_parameters(old_sig,
449+
first=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD))
440450
else:
441-
# --create a wrapper where we will be able to auto-detect
442-
# TODO we could put this in a dedicated wrapper 'ignore_unsused'..
443-
444-
old_sig = signature(fixture_func)
445-
# add request if needed
446-
func_needs_request = 'request' in old_sig.parameters
447-
if not func_needs_request:
448-
new_sig = add_signature_parameters(old_sig,
449-
first=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD))
450-
else:
451-
new_sig = old_sig
452-
if not isgeneratorfunction(fixture_func):
453-
# normal function with return statement
454-
@wraps(fixture_func, new_sig=new_sig)
455-
def wrapped_fixture_func(*args, **kwargs):
456-
request = kwargs['request'] if func_needs_request else kwargs.pop('request')
457-
if request.param is not NOT_USED:
458-
return fixture_func(*args, **kwargs)
459-
460-
# transform the created wrapper into a fixture
461-
fixture_decorator = pytest.fixture(scope=scope, autouse=autouse, **kwargs)
462-
return fixture_decorator(wrapped_fixture_func)
451+
new_sig = old_sig
452+
if not isgeneratorfunction(fixture_func):
453+
# normal function with return statement
454+
@wraps(fixture_func, new_sig=new_sig)
455+
def wrapped_fixture_func(*args, **kwargs):
456+
request = kwargs['request'] if func_needs_request else kwargs.pop('request')
457+
if getattr(request, 'param', None) is not NOT_USED:
458+
return fixture_func(*args, **kwargs)
463459

464-
else:
465-
# generator function (with a yield statement)
466-
@wraps(fixture_func, new_sig=new_sig)
467-
def wrapped_fixture_func(*args, **kwargs):
468-
request = kwargs['request'] if func_needs_request else kwargs.pop('request')
469-
if request.param is not NOT_USED:
470-
for res in fixture_func(*args, **kwargs):
471-
yield res
472-
473-
# transform the created wrapper into a fixture
474-
fixture_decorator = yield_fixture(scope=scope, autouse=autouse, **kwargs)
475-
return fixture_decorator(wrapped_fixture_func)
460+
# transform the created wrapper into a fixture
461+
fixture_decorator = pytest.fixture(scope=scope, autouse=autouse, **kwargs)
462+
return fixture_decorator(wrapped_fixture_func)
463+
464+
else:
465+
# generator function (with a yield statement)
466+
@wraps(fixture_func, new_sig=new_sig)
467+
def wrapped_fixture_func(*args, **kwargs):
468+
request = kwargs['request'] if func_needs_request else kwargs.pop('request')
469+
if getattr(request, 'param', None) is not NOT_USED:
470+
for res in fixture_func(*args, **kwargs):
471+
yield res
472+
else:
473+
# pytest expects a yield
474+
yield
475+
476+
# transform the created wrapper into a fixture
477+
fixture_decorator = yield_fixture(scope=scope, autouse=autouse, **kwargs)
478+
return fixture_decorator(wrapped_fixture_func)
476479

477480

478481
class _NotUsed:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from pytest_cases import pytest_fixture_plus, fixture_union
2+
3+
4+
state = -1
5+
6+
7+
@pytest_fixture_plus
8+
def a(request):
9+
global state
10+
assert state == 3
11+
state = 0
12+
yield
13+
state = 1
14+
15+
16+
@pytest_fixture_plus
17+
def b(request):
18+
global state
19+
state = 2
20+
yield
21+
state = 3
22+
23+
24+
c = fixture_union('c', [b, a])
25+
26+
# @pytest_fixture_plus
27+
# def c(b, a):
28+
# pass
29+
30+
31+
def test_all(c):
32+
pass
33+
34+
35+
def test_synthesis():
36+
assert state == 1

0 commit comments

Comments
 (0)