A funcarg is the short name for “test function argument”. Like any other Python function a test function can receive one or multiple arguments. When py.test prepares running a test function it looks at the neccessary function arguments, locates and calls factories which then provide the values to be passed to the function.
Let’s look at a simple self-contained example that you can put into a test module:
# content of ./test_simplefactory.py
def pytest_funcarg__myfuncarg(request):
return 42
def test_function(myfuncarg):
assert myfuncarg == 17
Running the test looks like this:
$ py.test test_simplefactory.py
=========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev30
test path 1: test_simplefactory.py
test_simplefactory.py F
================================= FAILURES =================================
______________________________ test_function _______________________________
myfuncarg = 42
def test_function(myfuncarg):
> assert myfuncarg == 17
E assert 42 == 17
test_simplefactory.py:5: AssertionError
========================= 1 failed in 0.02 seconds =========================
This means that the test function was called with a myfuncarg value of 42 and the assert fails accordingly. Here is how py.test calls the test function:
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”).
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:
add finalizer function to be called after test function finished execution.
return a testing resource managed by setup & teardown calls. scope and extrakey determine when the teardown function will be called so that subsequent calls to setup would recreate the resource.
Parameters: |
|
---|
apply a marker to a single test function invocation. This method is useful if you don’t want to have a keyword/marker on all function invocations.
Parameters: | marker – a _pytest.mark.MarkDecorator object created by a call to py.test.mark.NAME(...). |
---|
Retrieve a function argument by name for this test function invocation. This allows one function argument factory to call another function argument factory. If there are two funcarg factories for the same test function argument the first factory may use getfuncargvalue to call the second one and do something additional with the resource.
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:
Let’s consider a test module which uses the pytest_generate_tests hook to generate several calls to the same test function:
# content of test_example.py
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
Running this:
$ py.test test_example.py
=========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev30
test path 1: test_example.py
test_example.py .........F
================================= FAILURES =================================
_______________________________ test_func[9] _______________________________
numiter = 9
def test_func(numiter):
> assert numiter < 9
E assert 9 < 9
test_example.py:7: AssertionError
==================== 1 failed, 9 passed in 0.03 seconds ====================
Note that the pytest_generate_tests(metafunc) hook is called during the test collection phase which is separate from the actual test running. Let’s just look at what is collected:
$ py.test --collectonly test_example.py
<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]'>
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 ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev30 -- /home/hpk/venv/0/bin/python
test path 1: test_example.py
test_example.py:6: test_func[7] PASSED
======================== 9 tests deselected by '7' =========================
================== 1 passed, 9 deselected in 0.01 seconds ==================
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
add a new call to the underlying test function during the collection phase of a test run.
Parameters: |
|
---|