From 9f30ca668820ca5a2c5f7d3aeb656b46ca57b772 Mon Sep 17 00:00:00 2001 From: hpk Date: Sun, 12 Apr 2009 10:08:02 +0200 Subject: [PATCH] [svn r63990] * adding XXXed funcargs docs, moving release announcements to own subdir --HG-- branch : trunk --- doc/{ => announce}/release-0.9.0.txt | 0 doc/{ => announce}/release-0.9.2.txt | 0 doc/{ => announce}/release-1.0.0.txt | 0 doc/releases.txt | 6 +- doc/test-ext.txt | 9 +- doc/test-funcargs.txt | 160 +++++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 5 deletions(-) rename doc/{ => announce}/release-0.9.0.txt (100%) rename doc/{ => announce}/release-0.9.2.txt (100%) rename doc/{ => announce}/release-1.0.0.txt (100%) create mode 100644 doc/test-funcargs.txt diff --git a/doc/release-0.9.0.txt b/doc/announce/release-0.9.0.txt similarity index 100% rename from doc/release-0.9.0.txt rename to doc/announce/release-0.9.0.txt diff --git a/doc/release-0.9.2.txt b/doc/announce/release-0.9.2.txt similarity index 100% rename from doc/release-0.9.2.txt rename to doc/announce/release-0.9.2.txt diff --git a/doc/release-1.0.0.txt b/doc/announce/release-1.0.0.txt similarity index 100% rename from doc/release-1.0.0.txt rename to doc/announce/release-1.0.0.txt diff --git a/doc/releases.txt b/doc/releases.txt index 6726d990b..32398b64d 100644 --- a/doc/releases.txt +++ b/doc/releases.txt @@ -7,6 +7,6 @@ Contents: .. toctree:: :maxdepth: 1 - release-1.0.0 - release-0.9.2 - release-0.9.0 + announce/release-1.0.0 + announce/release-0.9.2 + announce/release-0.9.0 diff --git a/doc/test-ext.txt b/doc/test-ext.txt index 7255ae7a0..323540db5 100644 --- a/doc/test-ext.txt +++ b/doc/test-ext.txt @@ -110,6 +110,11 @@ name. Given a filesystem ``fspath`` it is constructed as follows: 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 diff --git a/doc/test-funcargs.txt b/doc/test-funcargs.txt new file mode 100644 index 000000000..28bc0b264 --- /dev/null +++ b/doc/test-funcargs.txt @@ -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 + +