test_ok1/doc/test/funcargs.txt

161 lines
4.7 KiB
Plaintext
Raw Normal View History

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