Merge branch 'master' of git://github.com/Elizaveta239/pytest into Elizaveta239-master
Fixed merge conflict in CHANGELOG
This commit is contained in:
commit
40fa7b25c5
1
AUTHORS
1
AUTHORS
|
@ -26,6 +26,7 @@ Daniel Nuri
|
||||||
Dave Hunt
|
Dave Hunt
|
||||||
David Mohr
|
David Mohr
|
||||||
Eduardo Schettino
|
Eduardo Schettino
|
||||||
|
Elizaveta Shashkova
|
||||||
Eric Siegerman
|
Eric Siegerman
|
||||||
Florian Bruhin
|
Florian Bruhin
|
||||||
Edison Gustavo Muenz
|
Edison Gustavo Muenz
|
||||||
|
|
|
@ -123,6 +123,10 @@
|
||||||
- fix issue890: changed extension of all documentation files from ``txt`` to
|
- fix issue890: changed extension of all documentation files from ``txt`` to
|
||||||
``rst``. Thanks to Abhijeet for the PR.
|
``rst``. Thanks to Abhijeet for the PR.
|
||||||
|
|
||||||
|
- fix issue714: add ability to apply indirect=True parameter on particular argnames.
|
||||||
|
Thanks Elizaveta239.
|
||||||
|
|
||||||
|
|
||||||
2.7.3 (compared to 2.7.2)
|
2.7.3 (compared to 2.7.2)
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|
|
@ -779,11 +779,12 @@ class CallSpec2(object):
|
||||||
def id(self):
|
def id(self):
|
||||||
return "-".join(map(str, filter(None, self._idlist)))
|
return "-".join(map(str, filter(None, self._idlist)))
|
||||||
|
|
||||||
def setmulti(self, valtype, argnames, valset, id, keywords, scopenum,
|
def setmulti(self, valtypes, argnames, valset, id, keywords, scopenum,
|
||||||
param_index):
|
param_index):
|
||||||
for arg,val in zip(argnames, valset):
|
for arg,val in zip(argnames, valset):
|
||||||
self._checkargnotcontained(arg)
|
self._checkargnotcontained(arg)
|
||||||
getattr(self, valtype)[arg] = val
|
valtype_for_arg = valtypes[arg]
|
||||||
|
getattr(self, valtype_for_arg)[arg] = val
|
||||||
self.indices[arg] = param_index
|
self.indices[arg] = param_index
|
||||||
self._arg2scopenum[arg] = scopenum
|
self._arg2scopenum[arg] = scopenum
|
||||||
if val is _notexists:
|
if val is _notexists:
|
||||||
|
@ -850,7 +851,7 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||||
""" Add new invocations to the underlying test function using the list
|
""" Add new invocations to the underlying test function using the list
|
||||||
of argvalues for the given argnames. Parametrization is performed
|
of argvalues for the given argnames. Parametrization is performed
|
||||||
during the collection phase. If you need to setup expensive resources
|
during the collection phase. If you need to setup expensive resources
|
||||||
see about setting indirect=True to do it rather at test setup time.
|
see about setting indirect to do it rather at test setup time.
|
||||||
|
|
||||||
:arg argnames: a comma-separated string denoting one or more argument
|
:arg argnames: a comma-separated string denoting one or more argument
|
||||||
names, or a list/tuple of argument strings.
|
names, or a list/tuple of argument strings.
|
||||||
|
@ -862,7 +863,9 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||||
where each tuple-element specifies a value for its respective
|
where each tuple-element specifies a value for its respective
|
||||||
argname.
|
argname.
|
||||||
|
|
||||||
:arg indirect: if True each argvalue corresponding to an argname will
|
:arg indirect: The list of argnames or boolean. A list of arguments'
|
||||||
|
names (subset of argnames). If True the list contains all names from
|
||||||
|
the argnames. Each argvalue corresponding to an argname in this list will
|
||||||
be passed as request.param to its respective argname fixture
|
be passed as request.param to its respective argname fixture
|
||||||
function so that it can perform more expensive setups during the
|
function so that it can perform more expensive setups during the
|
||||||
setup phase of a test rather than at collection time.
|
setup phase of a test rather than at collection time.
|
||||||
|
@ -907,13 +910,23 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||||
if scope is None:
|
if scope is None:
|
||||||
scope = "function"
|
scope = "function"
|
||||||
scopenum = scopes.index(scope)
|
scopenum = scopes.index(scope)
|
||||||
if not indirect:
|
valtypes = {}
|
||||||
|
if indirect is True:
|
||||||
|
valtypes = dict.fromkeys(argnames, "params")
|
||||||
|
elif indirect is False:
|
||||||
|
valtypes = dict.fromkeys(argnames, "funcargs")
|
||||||
#XXX should we also check for the opposite case?
|
#XXX should we also check for the opposite case?
|
||||||
for arg in argnames:
|
for arg in argnames:
|
||||||
if arg not in self.fixturenames:
|
if arg not in self.fixturenames:
|
||||||
raise ValueError("%r uses no fixture %r" %(
|
raise ValueError("%r uses no fixture %r" %(
|
||||||
self.function, arg))
|
self.function, arg))
|
||||||
valtype = indirect and "params" or "funcargs"
|
elif isinstance(indirect, (tuple, list)):
|
||||||
|
valtypes = dict.fromkeys(argnames, "funcargs")
|
||||||
|
for arg in indirect:
|
||||||
|
if arg not in argnames:
|
||||||
|
raise ValueError("indirect given to %r: fixture %r doesn't exist" %(
|
||||||
|
self.function, arg))
|
||||||
|
valtypes[arg] = "params"
|
||||||
idfn = None
|
idfn = None
|
||||||
if callable(ids):
|
if callable(ids):
|
||||||
idfn = ids
|
idfn = ids
|
||||||
|
@ -928,7 +941,7 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||||
for param_index, valset in enumerate(argvalues):
|
for param_index, valset in enumerate(argvalues):
|
||||||
assert len(valset) == len(argnames)
|
assert len(valset) == len(argnames)
|
||||||
newcallspec = callspec.copy(self)
|
newcallspec = callspec.copy(self)
|
||||||
newcallspec.setmulti(valtype, argnames, valset, ids[param_index],
|
newcallspec.setmulti(valtypes, argnames, valset, ids[param_index],
|
||||||
newkeywords.get(param_index, {}), scopenum,
|
newkeywords.get(param_index, {}), scopenum,
|
||||||
param_index)
|
param_index)
|
||||||
newcalls.append(newcallspec)
|
newcalls.append(newcallspec)
|
||||||
|
|
|
@ -280,6 +280,46 @@ The first invocation with ``db == "DB1"`` passed while the second with ``db == "
|
||||||
|
|
||||||
.. regendoc:wipe
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
Apply indirect on particular arguments
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
Very often parametrization uses more than one argument name. There is opportunity to apply ``indirect``
|
||||||
|
parameter on particular arguments. It can be done by passing list or tuple of
|
||||||
|
arguments' names to ``indirect``. In the example below there is a function ``test_indirect`` which uses
|
||||||
|
two fixtures: ``x`` and ``y``. Here we give to indirect the list, which contains the name of the
|
||||||
|
fixture ``x``. The indirect parameter will be applied to this argument only, and the value ``a``
|
||||||
|
will be passed to respective fixture function.
|
||||||
|
|
||||||
|
# content of test_indirect_list.py
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def x(request):
|
||||||
|
return request.param * 3
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def y(request):
|
||||||
|
return request.param * 2
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
|
||||||
|
def test_indirect(x,y):
|
||||||
|
assert x == 'aaa'
|
||||||
|
assert y == 'b'
|
||||||
|
|
||||||
|
The result of this test will be successful:
|
||||||
|
|
||||||
|
$ py.test test_indirect_list.py --collect-only
|
||||||
|
============================= test session starts ==============================
|
||||||
|
platform linux2 -- Python 2.7.3, pytest-2.8.0.dev4, py-1.4.30, pluggy-0.3.0
|
||||||
|
rootdir: /home/elizabeth/work/pytest, inifile: tox.ini
|
||||||
|
collected 1 items
|
||||||
|
<Module 'testing/test_argnames.py'>
|
||||||
|
<Function 'test_simple[a-b]'>
|
||||||
|
|
||||||
|
=============================== in 0.02 seconds ===============================
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
Parametrizing test methods through per-class configuration
|
Parametrizing test methods through per-class configuration
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,7 @@ class TestMetafunc:
|
||||||
assert metafunc._calls[0].id == "0-2"
|
assert metafunc._calls[0].id == "0-2"
|
||||||
assert metafunc._calls[1].id == "0-3"
|
assert metafunc._calls[1].id == "0-3"
|
||||||
|
|
||||||
|
@pytest.mark.issue714
|
||||||
def test_parametrize_indirect(self):
|
def test_parametrize_indirect(self):
|
||||||
def func(x, y): pass
|
def func(x, y): pass
|
||||||
metafunc = self.Metafunc(func)
|
metafunc = self.Metafunc(func)
|
||||||
|
@ -220,6 +221,65 @@ class TestMetafunc:
|
||||||
assert metafunc._calls[0].params == dict(x=1,y=2, unnamed=1)
|
assert metafunc._calls[0].params == dict(x=1,y=2, unnamed=1)
|
||||||
assert metafunc._calls[1].params == dict(x=1,y=3, unnamed=1)
|
assert metafunc._calls[1].params == dict(x=1,y=3, unnamed=1)
|
||||||
|
|
||||||
|
@pytest.mark.issue714
|
||||||
|
def test_parametrize_indirect_list(self):
|
||||||
|
def func(x, y): pass
|
||||||
|
metafunc = self.Metafunc(func)
|
||||||
|
metafunc.parametrize('x, y', [('a', 'b')], indirect=['x'])
|
||||||
|
assert metafunc._calls[0].funcargs == dict(y='b')
|
||||||
|
assert metafunc._calls[0].params == dict(x='a')
|
||||||
|
|
||||||
|
@pytest.mark.issue714
|
||||||
|
def test_parametrize_indirect_list_all(self):
|
||||||
|
def func(x, y): pass
|
||||||
|
metafunc = self.Metafunc(func)
|
||||||
|
metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'y'])
|
||||||
|
assert metafunc._calls[0].funcargs == {}
|
||||||
|
assert metafunc._calls[0].params == dict(x='a', y='b')
|
||||||
|
|
||||||
|
@pytest.mark.issue714
|
||||||
|
def test_parametrize_indirect_list_empty(self):
|
||||||
|
def func(x, y): pass
|
||||||
|
metafunc = self.Metafunc(func)
|
||||||
|
metafunc.parametrize('x, y', [('a', 'b')], indirect=[])
|
||||||
|
assert metafunc._calls[0].funcargs == dict(x='a', y='b')
|
||||||
|
assert metafunc._calls[0].params == {}
|
||||||
|
|
||||||
|
@pytest.mark.issue714
|
||||||
|
def test_parametrize_indirect_list_functional(self, testdir):
|
||||||
|
"""
|
||||||
|
Test parametrization with 'indirect' parameter applied on
|
||||||
|
particular arguments.
|
||||||
|
|
||||||
|
:param testdir: the instance of Testdir class, a temporary
|
||||||
|
test directory.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def x(request):
|
||||||
|
return request.param * 3
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def y(request):
|
||||||
|
return request.param * 2
|
||||||
|
@pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
|
||||||
|
def test_simple(x,y):
|
||||||
|
assert len(x) == 3
|
||||||
|
assert len(y) == 1
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest("-v")
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*test_simple*a-b*",
|
||||||
|
"*1 passed*",
|
||||||
|
])
|
||||||
|
|
||||||
|
@pytest.mark.issue714
|
||||||
|
def test_parametrize_indirect_list_error(self, testdir):
|
||||||
|
def func(x, y): pass
|
||||||
|
metafunc = self.Metafunc(func)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'z'])
|
||||||
|
|
||||||
def test_addcalls_and_parametrize_indirect(self):
|
def test_addcalls_and_parametrize_indirect(self):
|
||||||
def func(x, y): pass
|
def func(x, y): pass
|
||||||
metafunc = self.Metafunc(func)
|
metafunc = self.Metafunc(func)
|
||||||
|
|
Loading…
Reference in New Issue