mid-scale refactoring to make request API available directly on items.

This commit was slightly tricky because i want to backward
compatibility especially for the oejskit plugin which
uses Funcarg-filling for non-Function objects.
This commit is contained in:
holger krekel
2012-06-25 17:35:33 +02:00
parent 227d847216
commit 91b6f2bda8
16 changed files with 529 additions and 399 deletions
+28 -41
View File
@@ -11,26 +11,27 @@ Injecting objects into test functions (funcargs)
Dependency injection through function arguments
=================================================
py.test lets you inject objects into test functions and precisely
control their life cycle in relation to the test execution. It is
also possible to run a test function multiple times with different objects.
py.test lets you inject objects into test invocations and precisely
control their life cycle in relation to the overall test execution. Moreover,
you can run a test function multiple times injecting different objects.
The basic mechanism for injecting objects is also called the
*funcarg mechanism* because objects are ultimately injected
by calling a test function with it as an argument. Unlike the
classical xUnit approach *funcargs* relate more to `Dependency Injection`_
because they help to de-couple test code from objects required for
them to execute.
them to execute. At test writing time you do not need to care for the
details of how your required resources are constructed or if they
live through a function, class, module or session scope.
.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection
To create a value with which to call a test function a factory function
is called which gets full access to the test function context and can
register finalizers or invoke lifecycle-caching helpers. The factory
can be implemented in same test class or test module, or in a
per-directory ``conftest.py`` file or even in an external plugin. This
allows full de-coupling of test code and objects needed for test
execution.
can be implemented in same test class or test module, in a
per-directory ``conftest.py`` file or in an external plugin. This
allows total de-coupling of test and setup code.
A test function may be invoked multiple times in which case we
speak of :ref:`parametrized testing <parametrizing-tests>`. This can be
@@ -38,7 +39,7 @@ 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.
py.test comes with :ref:`builtinfuncargs` and there are some refined usages in the examples section.
py.test comes with some :ref:`builtinfuncargs` and there are some refined usages in the examples section.
.. _funcarg:
@@ -55,10 +56,8 @@ Let's look at a simple self-contained test module::
assert myfuncarg == 17
This test function needs an injected object named ``myfuncarg``.
py.test will discover and call the factory named
``pytest_funcarg__myfuncarg`` within the same module in this case.
Running the test looks like this::
py.test will automatically discover and call the ``pytest_funcarg__myfuncarg``
factory. Running the test looks like this::
$ py.test test_simplefactory.py
=========================== test session starts ============================
@@ -79,9 +78,9 @@ Running the test looks like this::
test_simplefactory.py:5: AssertionError
========================= 1 failed in 0.01 seconds =========================
This means that indeed the test function was called with a ``myfuncarg``
argument value of ``42`` and the assert fails. Here is how py.test
comes to call the test function this way:
This shows that the test function was called with a ``myfuncarg``
argument value of ``42`` and the assert fails as expected. Here is
how py.test comes to call the test function this way:
1. py.test :ref:`finds <test discovery>` the ``test_function`` because
of the ``test_`` prefix. The test function needs a function argument
@@ -99,13 +98,22 @@ 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 always issue::
.. Note::
py.test --funcargs test_simplefactory.py
You can always issue::
to see available function arguments (which you can also
think of as "resources").
py.test --funcargs test_simplefactory.py
to see available function arguments.
The request object passed to factories
-----------------------------------------
Each funcarg factory receives a :py:class:`~_pytest.main.Request` object which
provides methods to manage caching and finalization in the context of the
test invocation as well as several attributes of the the underlying test item. In fact, as of version pytest-2.3, the request API is implemented on all Item
objects and therefore the request object has general :py:class:`Node attributes and methods <_pytest.main.Node>` attributes. This is a backward compatible
change so no changes are neccessary for pre-2.3 funcarg factories.
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
@@ -116,27 +124,6 @@ think of as "resources").
.. _`funcarg factory`:
.. _factory:
The funcarg **request** object
=============================================
Each funcarg factory receives a **request** object 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`:
.. _`parametrized test functions`: