[svn r63990] * adding XXXed funcargs docs, moving release announcements to own subdir
--HG-- branch : trunk
This commit is contained in:
parent
7cc9419ab0
commit
9f30ca6688
|
@ -7,6 +7,6 @@ Contents:
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
release-1.0.0
|
announce/release-1.0.0
|
||||||
release-0.9.2
|
announce/release-0.9.2
|
||||||
release-0.9.0
|
announce/release-0.9.0
|
||||||
|
|
|
@ -110,6 +110,11 @@ name. Given a filesystem ``fspath`` it is constructed as follows:
|
||||||
Plugin hooks and events
|
Plugin hooks and events
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
See definitions at
|
.. automodule:: py.__.test.plugin.api
|
||||||
|
|
||||||
|
.. autoclass:: PluginHooks
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: Events
|
||||||
|
:members:
|
||||||
|
|
||||||
http://codespeak.net/svn/py/trunk/py/test/plugin/api.py
|
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
|
||||||
|
=====================================
|
||||||
|
Python test function arguments
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
py.test enables a new way to separate test configuration
|
||||||
|
and test setup from actual test code in test functions.
|
||||||
|
When it runs a test functions it will lookup function
|
||||||
|
arguments by name and provide a value.
|
||||||
|
Here is a simple example for such a test function:
|
||||||
|
|
||||||
|
def test_function(mysetup):
|
||||||
|
# work with mysetup
|
||||||
|
|
||||||
|
To provide a value py.test looks for a ``pytest_funcargs``
|
||||||
|
dictionary in the test module, for example::
|
||||||
|
|
||||||
|
class MySetup:
|
||||||
|
def __init__(self, pyfuncitem):
|
||||||
|
self.pyfuncitem = pyfuncitem
|
||||||
|
pytest_funcargs = {'mysetup': MySetup}
|
||||||
|
|
||||||
|
This is already enough to run the test. Of course
|
||||||
|
up until now our ``mysetup`` does not provide
|
||||||
|
much value. But it is now easy to add new
|
||||||
|
methods on the ``MySetup`` class that have
|
||||||
|
full access to the test collection process.
|
||||||
|
|
||||||
|
Plugins can register their funcargs via
|
||||||
|
the config object, usually upon initial configure::
|
||||||
|
|
||||||
|
class ConftestPlugin:
|
||||||
|
def pytest_configure(self, config):
|
||||||
|
config.register_funcargs(mysetup=MySetup)
|
||||||
|
|
||||||
|
If you provide a "funcarg" from a plugin you can
|
||||||
|
easily make methods depend on command line options
|
||||||
|
or environment settings. Here is a complete
|
||||||
|
example that allows to run tests involving
|
||||||
|
an SSH connection if an ssh host is specified::
|
||||||
|
|
||||||
|
class ConftestPlugin:
|
||||||
|
def pytest_addoption(self, parser):
|
||||||
|
parser.addoption("--ssh", action="store", default=None,
|
||||||
|
help="specify ssh host to run tests with")
|
||||||
|
|
||||||
|
def pytest_configure(self, config):
|
||||||
|
config.register_funcargs(mysetup=MySetup)
|
||||||
|
|
||||||
|
class MySetup:
|
||||||
|
def __init__(self, pyfuncitem):
|
||||||
|
self.pyfuncitem = pyfuncitem
|
||||||
|
def ssh_gateway(self):
|
||||||
|
host = pyfuncitem.config.option.ssh
|
||||||
|
if host is None:
|
||||||
|
py.test.skip("specify ssh host with --ssh to run this test")
|
||||||
|
return py.execnet.SshGateway(host)
|
||||||
|
|
||||||
|
Now any test functions can use the "mysetup" object, for example::
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
def test_function(self, mysetup):
|
||||||
|
ssh_gw = mysetup.ssh_gateway()
|
||||||
|
# work with ssh_gw
|
||||||
|
|
||||||
|
Without specifying a command line option the output looks like this::
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Lookup rules
|
||||||
|
======================
|
||||||
|
|
||||||
|
In order to run this test function a value for the
|
||||||
|
``mysetup`` needs to be found. Here is how py.test
|
||||||
|
finds a matching provider function:
|
||||||
|
|
||||||
|
1. see if there is a ``pytest_funcargs`` dictionary
|
||||||
|
which maps ``mysetup`` to a provider function.
|
||||||
|
if so, call the provider function.
|
||||||
|
|
||||||
|
XXX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
example
|
||||||
|
=====================
|
||||||
|
|
||||||
|
You can run a test file ``test_some.py`` with this content:
|
||||||
|
|
||||||
|
pytest_funcargs = {'myarg': (lambda pyfuncitem: 42)}
|
||||||
|
|
||||||
|
def test_something(myarg):
|
||||||
|
assert myarg == 42
|
||||||
|
|
||||||
|
You can also put this on a class:
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
pytest_funcargs = {'myarg': (lambda pyfuncitem: 42)}
|
||||||
|
|
||||||
|
def test_something(self, myarg):
|
||||||
|
assert myarg == 42
|
||||||
|
|
||||||
|
To separate funcarg setup you can also put a funcarg
|
||||||
|
definition into a conftest.py::
|
||||||
|
|
||||||
|
pytest_funcargs = {'myarg': decorate_myarg}
|
||||||
|
def decorate_myarg(pyfuncitem):
|
||||||
|
result = pyfuncitem.call_next_provider()
|
||||||
|
return result + 1
|
||||||
|
|
||||||
|
for registering funcargs from a plugin, talk to the
|
||||||
|
test configuration object like this::
|
||||||
|
|
||||||
|
class MyPlugin:
|
||||||
|
def pytest_configure(self, config):
|
||||||
|
config.register_funcargs(
|
||||||
|
myarg=decorate_myarg
|
||||||
|
)
|
||||||
|
|
||||||
|
a local helper funcarg for doing acceptance tests maybe
|
||||||
|
by running shell commands could look like this::
|
||||||
|
|
||||||
|
class MyPlugin:
|
||||||
|
def pytest_option(self, parser):
|
||||||
|
group = parser.addgroup("myproject acceptance tests")
|
||||||
|
group.addoption("-A", dest="acceptance", action="store_true",
|
||||||
|
help="run (slow) acceptance tests")
|
||||||
|
|
||||||
|
def pytest_configure(self, config):
|
||||||
|
config.register_funcargs(accept=AcceptFuncarg)
|
||||||
|
|
||||||
|
class AcceptFuncarg:
|
||||||
|
def __init__(self, pyfuncitem):
|
||||||
|
if not pyfuncitem.config.option.acceptance:
|
||||||
|
py.test.skip("specify -A to run acceptance tests")
|
||||||
|
self.tmpdir = pyfuncitem.config.maketempdir(pyfuncitem.name)
|
||||||
|
self._old = self.tmpdir.chdir()
|
||||||
|
pyfuncitem.addfinalizer(self.finalize)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
return py.process.cmdexec("echo hello")
|
||||||
|
|
||||||
|
def finalize(self):
|
||||||
|
self._old.chdir()
|
||||||
|
# cleanup any other resources
|
||||||
|
|
||||||
|
and the actual test function example:
|
||||||
|
|
||||||
|
def test_some_acceptance_aspect(accept):
|
||||||
|
accept.tmpdir.mkdir("somesub")
|
||||||
|
result = accept.run()
|
||||||
|
assert result
|
||||||
|
|
||||||
|
for registering funcargs from a plugin, talk to the
|
||||||
|
test configuration object like this::
|
||||||
|
|
||||||
|
XXX
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue