2010-10-11 05:45:45 +08:00
|
|
|
==============================================================
|
2010-10-14 01:30:00 +08:00
|
|
|
creating and managing test function arguments
|
2010-10-11 05:45:45 +08:00
|
|
|
==============================================================
|
|
|
|
|
2010-11-13 18:10:45 +08:00
|
|
|
.. currentmodule:: _pytest.python
|
2010-10-11 05:45:45 +08:00
|
|
|
|
2010-11-06 06:37:25 +08:00
|
|
|
|
|
|
|
.. _`funcargs`:
|
2010-10-11 05:45:45 +08:00
|
|
|
.. _`funcarg mechanism`:
|
|
|
|
|
2010-11-25 19:11:10 +08:00
|
|
|
Dependency injection through function arguments
|
2010-10-11 05:45:45 +08:00
|
|
|
=================================================
|
|
|
|
|
2010-11-25 19:11:10 +08:00
|
|
|
py.test allows to inject values into test functions through the *funcarg
|
|
|
|
mechanism*: For each argument name in a test function signature a factory is
|
|
|
|
looked up and called to create the value. The factory can live in the
|
2010-12-07 22:25:25 +08:00
|
|
|
same test class, test module, in a per-directory ``conftest.py`` file or
|
2010-11-25 19:11:10 +08:00
|
|
|
in an external plugin. It has full access to the requesting test
|
|
|
|
function, can register finalizers and invoke lifecycle-caching
|
|
|
|
helpers. As can be expected from a systematic dependency
|
|
|
|
injection mechanism, this allows full de-coupling of resource and
|
|
|
|
fixture setup from test code, enabling more maintainable and
|
|
|
|
easy-to-modify test suites.
|
|
|
|
|
|
|
|
A test function may be invoked multiple times in which case we
|
|
|
|
speak of :ref:`parametrized testing <parametrizing-tests>`. This can be
|
|
|
|
very useful if you want to test e.g. against different database backends
|
|
|
|
or with multiple numerical arguments sets and want to reuse the same set
|
|
|
|
of test functions.
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
Basic funcarg example
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
Let's look at a simple self-contained example that you can put
|
|
|
|
into a test module::
|
|
|
|
|
2010-10-11 05:54:00 +08:00
|
|
|
# content of ./test_simplefactory.py
|
2010-10-11 05:45:45 +08:00
|
|
|
def pytest_funcarg__myfuncarg(request):
|
|
|
|
return 42
|
|
|
|
|
|
|
|
def test_function(myfuncarg):
|
|
|
|
assert myfuncarg == 17
|
|
|
|
|
2010-10-11 05:54:00 +08:00
|
|
|
Running the test looks like this::
|
|
|
|
|
|
|
|
$ py.test test_simplefactory.py
|
2010-10-12 16:59:04 +08:00
|
|
|
=========================== test session starts ============================
|
2010-11-26 20:26:56 +08:00
|
|
|
platform linux2 -- Python 2.6.5 -- pytest-2.0.0
|
|
|
|
collecting ... collected 1 items
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 05:45:45 +08:00
|
|
|
test_simplefactory.py F
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-12 16:59:04 +08:00
|
|
|
================================= FAILURES =================================
|
|
|
|
______________________________ test_function _______________________________
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 05:45:45 +08:00
|
|
|
myfuncarg = 42
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 05:45:45 +08:00
|
|
|
def test_function(myfuncarg):
|
|
|
|
> assert myfuncarg == 17
|
|
|
|
E assert 42 == 17
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 16:07:14 +08:00
|
|
|
test_simplefactory.py:5: AssertionError
|
2010-10-12 16:59:04 +08:00
|
|
|
========================= 1 failed in 0.02 seconds =========================
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
This means that the test function was called with a ``myfuncarg`` value
|
|
|
|
of ``42`` and the assert fails accordingly. Here is how py.test
|
2010-11-25 19:11:10 +08:00
|
|
|
comes to call the test function this way:
|
2010-10-11 05:45:45 +08:00
|
|
|
|
2010-11-25 19:11:10 +08:00
|
|
|
1. py.test :ref:`finds <test discovery>` the ``test_function`` because
|
|
|
|
of the ``test_`` prefix. The test function needs a function argument
|
|
|
|
named ``myfuncarg``. A matching factory function is discovered by
|
|
|
|
looking for the name ``pytest_funcarg__myfuncarg``.
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
2. ``pytest_funcarg__myfuncarg(request)`` is called and
|
|
|
|
returns the value for ``myfuncarg``.
|
|
|
|
|
2010-11-25 19:11:10 +08:00
|
|
|
3. the test function can now be called: ``test_function(42)``
|
|
|
|
and results in the above exception because of the assertion
|
|
|
|
mismatch.
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
Note that if you misspell a function argument or want
|
|
|
|
to use one that isn't available, you'll see an error
|
|
|
|
with a list of available function arguments. You can
|
|
|
|
also issue::
|
|
|
|
|
|
|
|
py.test --funcargs test_simplefactory.py
|
|
|
|
|
|
|
|
to see available function arguments (which you can also
|
|
|
|
think of as "resources").
|
|
|
|
|
|
|
|
|
|
|
|
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
|
|
|
|
|
|
|
.. _`blog post about the monkeypatch funcarg`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
|
|
|
.. _`xUnit style`: xunit_setup.html
|
|
|
|
|
|
|
|
|
|
|
|
.. _`funcarg factory`:
|
|
|
|
.. _factory:
|
|
|
|
|
|
|
|
The funcarg **request** object
|
|
|
|
=============================================
|
|
|
|
|
|
|
|
Each funcarg factory receives a **request** object which is tied to a
|
|
|
|
specific test function call. A request object is passed to a funcarg
|
|
|
|
factory and provides access to test configuration and context:
|
|
|
|
|
2010-11-13 18:10:45 +08:00
|
|
|
.. autoclass:: _pytest.python.FuncargRequest()
|
2010-10-17 05:59:38 +08:00
|
|
|
:members: function,cls,module,keywords,config
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
.. _`useful caching and finalization helpers`:
|
|
|
|
|
|
|
|
.. automethod:: FuncargRequest.addfinalizer
|
|
|
|
|
|
|
|
.. automethod:: FuncargRequest.cached_setup
|
|
|
|
|
|
|
|
.. automethod:: FuncargRequest.applymarker
|
|
|
|
|
|
|
|
.. automethod:: FuncargRequest.getfuncargvalue
|
|
|
|
|
|
|
|
|
|
|
|
.. _`test generators`:
|
|
|
|
.. _`parametrizing-tests`:
|
2010-11-25 19:11:10 +08:00
|
|
|
.. _`parametrized test functions`:
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
Parametrizing multiple calls to a test function
|
|
|
|
===========================================================
|
|
|
|
|
|
|
|
You can parametrize multiple runs of the same test
|
|
|
|
function by adding new test function calls with different
|
|
|
|
function argument values. Let's look at a simple self-contained
|
|
|
|
example:
|
|
|
|
|
|
|
|
Basic generated test example
|
|
|
|
----------------------------
|
|
|
|
|
2010-11-06 06:37:25 +08:00
|
|
|
Let's consider a test module which uses the ``pytest_generate_tests``
|
|
|
|
hook to generate several calls to the same test function::
|
2010-10-11 05:45:45 +08:00
|
|
|
|
2010-10-12 16:59:04 +08:00
|
|
|
# content of test_example.py
|
2010-10-11 05:45:45 +08:00
|
|
|
def pytest_generate_tests(metafunc):
|
|
|
|
if "numiter" in metafunc.funcargnames:
|
|
|
|
for i in range(10):
|
|
|
|
metafunc.addcall(funcargs=dict(numiter=i))
|
|
|
|
|
|
|
|
def test_func(numiter):
|
|
|
|
assert numiter < 9
|
|
|
|
|
2010-10-11 05:54:00 +08:00
|
|
|
Running this::
|
2010-10-11 05:45:45 +08:00
|
|
|
|
2010-10-11 05:54:00 +08:00
|
|
|
$ py.test test_example.py
|
2010-10-12 16:59:04 +08:00
|
|
|
=========================== test session starts ============================
|
2010-11-26 20:26:56 +08:00
|
|
|
platform linux2 -- Python 2.6.5 -- pytest-2.0.0
|
|
|
|
collecting ... collected 10 items
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 05:45:45 +08:00
|
|
|
test_example.py .........F
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-12 16:59:04 +08:00
|
|
|
================================= FAILURES =================================
|
|
|
|
_______________________________ test_func[9] _______________________________
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 05:45:45 +08:00
|
|
|
numiter = 9
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 05:45:45 +08:00
|
|
|
def test_func(numiter):
|
|
|
|
> assert numiter < 9
|
|
|
|
E assert 9 < 9
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-10-11 16:07:14 +08:00
|
|
|
test_example.py:7: AssertionError
|
2010-11-18 05:12:16 +08:00
|
|
|
==================== 1 failed, 9 passed in 0.03 seconds ====================
|
2010-10-13 18:26:14 +08:00
|
|
|
|
|
|
|
Note that the ``pytest_generate_tests(metafunc)`` hook is called during
|
2010-11-06 06:37:25 +08:00
|
|
|
the test collection phase which is separate from the actual test running.
|
|
|
|
Let's just look at what is collected::
|
2010-10-13 18:26:14 +08:00
|
|
|
|
|
|
|
$ py.test --collectonly test_example.py
|
2010-11-06 18:38:53 +08:00
|
|
|
<Module 'test_example.py'>
|
|
|
|
<Function 'test_func[0]'>
|
|
|
|
<Function 'test_func[1]'>
|
|
|
|
<Function 'test_func[2]'>
|
|
|
|
<Function 'test_func[3]'>
|
|
|
|
<Function 'test_func[4]'>
|
|
|
|
<Function 'test_func[5]'>
|
|
|
|
<Function 'test_func[6]'>
|
|
|
|
<Function 'test_func[7]'>
|
|
|
|
<Function 'test_func[8]'>
|
|
|
|
<Function 'test_func[9]'>
|
2010-10-13 18:26:14 +08:00
|
|
|
|
|
|
|
If you want to select only the run with the value ``7`` you could do::
|
|
|
|
|
|
|
|
$ py.test -v -k 7 test_example.py # or -k test_func[7]
|
|
|
|
=========================== test session starts ============================
|
2010-11-26 20:26:56 +08:00
|
|
|
platform linux2 -- Python 2.6.5 -- pytest-2.0.0 -- /home/hpk/venv/0/bin/python
|
|
|
|
collecting ... collected 10 items
|
2010-11-06 18:38:53 +08:00
|
|
|
|
2010-11-18 05:12:16 +08:00
|
|
|
test_example.py:6: test_func[7] PASSED
|
2010-11-06 18:38:53 +08:00
|
|
|
|
|
|
|
======================== 9 tests deselected by '7' =========================
|
|
|
|
================== 1 passed, 9 deselected in 0.01 seconds ==================
|
2010-10-11 05:45:45 +08:00
|
|
|
|
|
|
|
.. _`metafunc object`:
|
|
|
|
|
|
|
|
The **metafunc** object
|
|
|
|
-------------------------------------------
|
|
|
|
|
|
|
|
metafunc objects are passed to the ``pytest_generate_tests`` hook.
|
|
|
|
They help to inspect a testfunction and to generate tests
|
|
|
|
according to test configuration or values specified
|
|
|
|
in the class or module where a test function is defined:
|
|
|
|
|
|
|
|
``metafunc.funcargnames``: set of required function arguments for given function
|
|
|
|
|
|
|
|
``metafunc.function``: underlying python test function
|
|
|
|
|
|
|
|
``metafunc.cls``: class object where the test function is defined in or None.
|
|
|
|
|
|
|
|
``metafunc.module``: the module object where the test function is defined in.
|
|
|
|
|
|
|
|
``metafunc.config``: access to command line opts and general config
|
|
|
|
|
|
|
|
.. automethod:: Metafunc.addcall(funcargs=None, id=_notexists, param=_notexists)
|