Allow parameterised fixtures to give paramemter IDs

This is just like the markers etc already can do.
This commit is contained in:
Floris Bruynooghe 2013-12-15 22:15:15 +00:00
parent 1b7c70eab4
commit 0c737e3de0
3 changed files with 54 additions and 8 deletions

View File

@ -1,6 +1,9 @@
Unreleased Unreleased
----------------------------------- -----------------------------------
- Allow parameterized fixtures to specify the ID of the parameters by
adding an ids argument to pytest.fixture() and pytest.yield_fixture().
- fix issue404 by always using the binary xml escape in the junitxml plugin - fix issue404 by always using the binary xml escape in the junitxml plugin
2.5.0 2.5.0

View File

@ -35,11 +35,13 @@ def getimfunc(func):
class FixtureFunctionMarker: class FixtureFunctionMarker:
def __init__(self, scope, params, autouse=False, yieldctx=False): def __init__(self, scope, params,
autouse=False, yieldctx=False, ids=None):
self.scope = scope self.scope = scope
self.params = params self.params = params
self.autouse = autouse self.autouse = autouse
self.yieldctx = yieldctx self.yieldctx = yieldctx
self.ids = ids
def __call__(self, function): def __call__(self, function):
if inspect.isclass(function): if inspect.isclass(function):
@ -49,7 +51,7 @@ class FixtureFunctionMarker:
return function return function
def fixture(scope="function", params=None, autouse=False): def fixture(scope="function", params=None, autouse=False, ids=None):
""" (return a) decorator to mark a fixture factory function. """ (return a) decorator to mark a fixture factory function.
This decorator can be used (with or or without parameters) to define This decorator can be used (with or or without parameters) to define
@ -71,6 +73,10 @@ def fixture(scope="function", params=None, autouse=False):
can see it. If False (the default) then an explicit can see it. If False (the default) then an explicit
reference is needed to activate the fixture. reference is needed to activate the fixture.
:arg ids: list of string ids each corresponding to the argvalues
so that they are part of the test id. If no ids are provided
they will be generated automatically from the argvalues.
""" """
if callable(scope) and params is None and autouse == False: if callable(scope) and params is None and autouse == False:
# direct decoration # direct decoration
@ -78,9 +84,9 @@ def fixture(scope="function", params=None, autouse=False):
"function", params, autouse)(scope) "function", params, autouse)(scope)
if params is not None and not isinstance(params, (list, tuple)): if params is not None and not isinstance(params, (list, tuple)):
params = list(params) params = list(params)
return FixtureFunctionMarker(scope, params, autouse) return FixtureFunctionMarker(scope, params, autouse, ids=ids)
def yield_fixture(scope="function", params=None, autouse=False): def yield_fixture(scope="function", params=None, autouse=False, ids=None):
""" (return a) decorator to mark a yield-fixture factory function """ (return a) decorator to mark a yield-fixture factory function
(EXPERIMENTAL). (EXPERIMENTAL).
@ -94,7 +100,8 @@ def yield_fixture(scope="function", params=None, autouse=False):
return FixtureFunctionMarker( return FixtureFunctionMarker(
"function", params, autouse, yieldctx=True)(scope) "function", params, autouse, yieldctx=True)(scope)
else: else:
return FixtureFunctionMarker(scope, params, autouse, yieldctx=True) return FixtureFunctionMarker(scope, params, autouse,
yieldctx=True, ids=ids)
defaultfuncargprefixmarker = fixture() defaultfuncargprefixmarker = fixture()
@ -1623,7 +1630,8 @@ class FixtureManager:
for fixturedef in faclist: for fixturedef in faclist:
if fixturedef.params is not None: if fixturedef.params is not None:
metafunc.parametrize(argname, fixturedef.params, metafunc.parametrize(argname, fixturedef.params,
indirect=True, scope=fixturedef.scope) indirect=True, scope=fixturedef.scope,
ids=fixturedef.ids)
def pytest_collection_modifyitems(self, items): def pytest_collection_modifyitems(self, items):
# separate parametrized setups # separate parametrized setups
@ -1660,7 +1668,7 @@ class FixtureManager:
fixturedef = FixtureDef(self, nodeid, name, obj, fixturedef = FixtureDef(self, nodeid, name, obj,
marker.scope, marker.params, marker.scope, marker.params,
yieldctx=marker.yieldctx, yieldctx=marker.yieldctx,
unittest=unittest) unittest=unittest, ids=marker.ids)
faclist = self._arg2fixturedefs.setdefault(name, []) faclist = self._arg2fixturedefs.setdefault(name, [])
if fixturedef.has_location: if fixturedef.has_location:
faclist.append(fixturedef) faclist.append(fixturedef)
@ -1728,7 +1736,7 @@ def call_fixture_func(fixturefunc, request, kwargs, yieldctx):
class FixtureDef: class FixtureDef:
""" A container for a factory definition. """ """ A container for a factory definition. """
def __init__(self, fixturemanager, baseid, argname, func, scope, params, def __init__(self, fixturemanager, baseid, argname, func, scope, params,
yieldctx, unittest=False): yieldctx, unittest=False, ids=None):
self._fixturemanager = fixturemanager self._fixturemanager = fixturemanager
self.baseid = baseid or '' self.baseid = baseid or ''
self.has_location = baseid is not None self.has_location = baseid is not None
@ -1741,6 +1749,7 @@ class FixtureDef:
self.argnames = getfuncargnames(func, startindex=startindex) self.argnames = getfuncargnames(func, startindex=startindex)
self.yieldctx = yieldctx self.yieldctx = yieldctx
self.unittest = unittest self.unittest = unittest
self.ids = ids
self._finalizer = [] self._finalizer = []
def addfinalizer(self, finalizer): def addfinalizer(self, finalizer):

View File

@ -1989,6 +1989,40 @@ class TestFixtureMarker:
reprec = testdir.inline_run() reprec = testdir.inline_run()
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
def test_params_and_ids(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(params=[object(), object()],
ids=['alpha', 'beta'])
def fix(request):
return request.param
def test_foo(fix):
assert 1
""")
res = testdir.runpytest('-v')
res.stdout.fnmatch_lines([
'*test_foo*alpha*',
'*test_foo*beta*'])
def test_params_and_ids_yieldfixture(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.yield_fixture(params=[object(), object()],
ids=['alpha', 'beta'])
def fix(request):
yield request.param
def test_foo(fix):
assert 1
""")
res = testdir.runpytest('-v')
res.stdout.fnmatch_lines([
'*test_foo*alpha*',
'*test_foo*beta*'])
class TestRequestScopeAccess: class TestRequestScopeAccess:
pytestmark = pytest.mark.parametrize(("scope", "ok", "error"),[ pytestmark = pytest.mark.parametrize(("scope", "ok", "error"),[