move funcarg factory to a new FuncargManager object at session level

This commit is contained in:
holger krekel
2012-07-19 09:20:14 +02:00
parent c7ee6e71ab
commit 4e4b507472
7 changed files with 212 additions and 273 deletions

View File

@@ -3,84 +3,32 @@ Implementation plan for resources
------------------------------------------
1. Revert FuncargRequest to the old form, unmerge item/request
2. make setup functions be discovered at collection time
3. make funcarg factories be discovered at collection time
4. Introduce funcarg marker
5. Introduce funcarg scope parameter
6. Introduce funcarg parametrize parameter
(done)
2. make funcarg factories be discovered at collection time
3. Introduce funcarg marker
4. Introduce funcarg scope parameter
5. Introduce funcarg parametrize parameter
6. make setup functions be discovered at collection time
7. (Introduce a pytest_fixture_protocol/setup_funcargs hook)
methods and data structures
--------------------------------
A FuncarcDB holds all information about funcarg definitions,
parametrization and the places where funcargs are required. It can
answer the following questions:
* given a node and a funcargname, return a paramlist so that collection
can perform parametrization (parametrized nodes?)
* given a node (possibly containing a param), perform a funcargrequest
and return the value
* if funcargname is an empty string, it matches general setup.
pytest could perform 2-pass collection:
- first perform normal collection (no parametrization at all!), populate
FuncargDB
- walk through the node tree and ask FuncargDB for each node for
required funcargs and their parameters - clone subtrees (deepcopy) and
substitute the un-parametrized node with parametrized ones
A FuncarcManager holds all information about funcarg definitions
including parametrization and scope definitions. It implements
a pytest_generate_tests hook which performs parametrization as appropriate.
as a simple example, let's consider a tree where a test function requires
a "abc" funcarg and its factory defines it as parametrized and scoped
for Modules. When the 2nd collection pass asks FuncargDB to return
params for the test module, it will know that the test functions in it
requires "abc" and that is it parametrized and defined for module scope.
Therefore parametrization of the module node is performed, substituting
the node with multiple module nodes ("test_module.py[1]", ...).
When test_module.py[1] is setup() it will call all its (parametrized)
factories and populate a funcargs dictionary, mapping funcargnames to values.
When a test function below test_module.py[1] is executed, it looks up
its required arguments from the thus populated funcargs dictionary.
Let's add to this example a second funcarg "def" that has a per-function parametrization. When the 2nd collection pass asks FuncargDB to return
params for the test function, it will know that the test functions in it
requires "def" and that is it parametrized and defined for function scope.
Therefore parametrization of the function node is performed, substituting
the node with multiple function nodes ("test_function[1]", ...).
When test_function[1] is setup() it will call all its (parametrized)
factories and populate a funcargs dictionary. The "def" will only appear
in the funcargs dict seen by test_function[1]. When test_function[1]
executes, it will use its funcargs.
where
* ``nodeidbase`` is a basestring; for all nodeids matching
startswith(nodeidbase) it defines a (scopecls, factorylist) tuple
* ``scopecls`` is a node class for the which the factorylist s defined
* ``param`` is a parametrizing parameter for the factorylist
* ``factorylist`` is a list of factories which will be used to perform
a funcarg request
* the whole list is sorted by length of nodeidbase (longest first)
for Modules. When collections hits the function item, it creates
the metafunc object, and calls funcargdb.pytest_generate_tests(metafunc)
which looks up available funcarg factories and their scope and parametrization.
This information is equivalent to what can be provided today directly
at the function site and it should thus be relatively straight forward
to implement the additional way of defining parametrization/scoping.
conftest loading:
each funcarg-factory will populate FuncargDefs which keeps references
to all definitions the funcarg2 marked function or pytest_funcarg__
scope can be a string or a nodenames-tuple.
scopestring -> list of (funcargname, factorylist)
nodenames -> (funcargname, list of factories)
It needs to be a list because factories can decorate
For any given node and a required funcarg it is thus
easy to lookup a list of matching factories.
each funcarg-factory will populate the session.funcargmanager
When a test item is collected, it grows a dictionary
(funcargname2factorycalllist). A factory lookup is performed