==============================================================
creating and managing test function arguments
==============================================================

.. currentmodule:: _pytest.python


.. _`funcargs`:
.. _`funcarg mechanism`:

Test function arguments and factories
=================================================

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.

Basic funcarg example
-----------------------

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:

1. py.test discovers 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``.

2. ``pytest_funcarg__myfuncarg(request)`` is called and
   returns the value for ``myfuncarg``.

3. ``test_function(42)`` call is executed.

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:

.. autoclass:: _pytest.python.FuncargRequest()
    :members: function,cls,module,keywords,config

.. _`useful caching and finalization helpers`:

.. automethod:: FuncargRequest.addfinalizer

.. automethod:: FuncargRequest.cached_setup

.. automethod:: FuncargRequest.applymarker

.. automethod:: FuncargRequest.getfuncargvalue


.. _`test generators`:
.. _`parametrizing-tests`:

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
----------------------------

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 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)
