[svn r63200] new docs about testing
refactoring of documentation new entry page --HG-- branch : trunk
This commit is contained in:
parent
9bfdb42273
commit
887a837600
|
@ -1,6 +1,8 @@
|
|||
py lib contact and communication
|
||||
===================================
|
||||
|
||||
- You may also subscribe to `tetamap`_, where Holger Krekel
|
||||
often posts about testing and py.test related news.
|
||||
|
||||
- **#pylib on irc.freenode.net**: you are welcome
|
||||
to lurk or ask questions in this IRC channel, it also tracks py lib commits.
|
||||
|
@ -20,6 +22,8 @@ py lib contact and communication
|
|||
|
||||
.. _`get an account`:
|
||||
|
||||
.. _tetamap: http://tetamap.wordpress.com
|
||||
|
||||
|
||||
get an account on codespeak
|
||||
---------------------------
|
||||
|
|
|
@ -131,28 +131,6 @@ conftest.py configurations::
|
|||
|
||||
py.test --traceconfig
|
||||
|
||||
adding custom options
|
||||
+++++++++++++++++++++++
|
||||
|
||||
To register a project-specific command line option
|
||||
you may have the following code within a ``conftest.py`` file::
|
||||
|
||||
import py
|
||||
Option = py.test.config.Option
|
||||
option = py.test.config.addoptions("pypy options",
|
||||
Option('-V', '--view', action="store_true", dest="view", default=False,
|
||||
help="view translation tests' flow graphs with Pygame"),
|
||||
)
|
||||
|
||||
and you can then access ``option.view`` like this::
|
||||
|
||||
if option.view:
|
||||
print "view this!"
|
||||
|
||||
The option will be available if you type ``py.test -h``
|
||||
Note that you may only register upper case short
|
||||
options. ``py.test`` reserves all lower
|
||||
case short options for its own cross-project usage.
|
||||
|
||||
customizing the collecting and running process
|
||||
-----------------------------------------------
|
||||
|
@ -245,7 +223,7 @@ useful for calling application test machinery with different
|
|||
parameter sets but counting each of the calls as a separate
|
||||
tests.
|
||||
|
||||
.. _`generative tests`: test.html#generative-tests
|
||||
.. _`generative tests`: test-features.html#generative-tests
|
||||
|
||||
The other extension possibility is about
|
||||
specifying a custom test ``Item`` class which
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
Test configuration
|
||||
========================
|
||||
|
||||
using / specifying plugins
|
||||
-------------------------------
|
||||
|
||||
you can instruct py.test to use additional plugins by:
|
||||
|
||||
* setting the PYTEST_PLUGINS environment variable
|
||||
to a comma-separated list of plugins
|
||||
* XXX supplying "--plugins=NAME1,NAME2,..." at the command line
|
||||
* setting "pytest_plugins='name1', 'name2'" in
|
||||
``conftest.py`` files or in python test modules.
|
||||
|
||||
py.test will load all plugins along with their dependencies
|
||||
(plugins may specify "pytest_plugins" as well).
|
||||
|
||||
test option values
|
||||
test options and values
|
||||
-----------------------------
|
||||
|
||||
py.test will lookup the value of an option "NAME" in this order:
|
||||
You can see all available command line options by running::
|
||||
|
||||
py.test -h
|
||||
|
||||
py.test will lookup values of options in this order:
|
||||
|
||||
* option value supplied at command line
|
||||
* content of environment variable ``PYTEST_OPTION_NAME=...``
|
||||
* ``name = ...`` setting in the nearest ``conftest.py`` file.
|
||||
|
||||
This means that you can specify default options per-run,
|
||||
per shell session or per project directory.
|
||||
The name of an option usually is the one you find
|
||||
in the longform of the option, i.e. the name
|
||||
behind the ``--`` double-dash.
|
||||
|
||||
IOW, you can set default values for options per project, per
|
||||
home-directoray, per shell session or per test-run.
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
.. _`distribute tests across machines`:
|
||||
|
||||
``py.test`` can ad-hoc distribute test runs to multiple CPUs or remote
|
||||
machines. This allows to speed up development or to use special resources
|
||||
of remote machines. Before running tests remotely, ``py.test`` efficiently
|
||||
synchronizes your program source code to the remote place. All test results
|
||||
are reported back and displayed to your local test session. You may
|
||||
specify different Python versions and interpreters.
|
||||
|
||||
Speed up test runs by sending tests to multiple CPUs
|
||||
----------------------------------------------------------
|
||||
|
||||
To send tests to multiple CPUs, type::
|
||||
|
||||
py.test -n NUM
|
||||
|
||||
Especially for longer running tests or tests requiring
|
||||
a lot of IO this can lead to considerable speed ups.
|
||||
|
||||
Test on a different python interpreter
|
||||
----------------------------------------------------------
|
||||
|
||||
To send tests to a python2.4 process, you may type::
|
||||
|
||||
py.test --tx popen//python=python2.4
|
||||
|
||||
This will start a subprocess which is run with the "python2.4"
|
||||
Python interpreter, found in your system binary lookup path.
|
||||
|
||||
.. For convenience you may prepend ``3*`` to create three sub processes.
|
||||
|
||||
|
||||
Sending tests to remote SSH accounts
|
||||
------------------------------------
|
||||
|
||||
Suppose you have a package ``mypkg`` which contains some
|
||||
tests that you can successfully run locally. And you
|
||||
have a ssh-reachable machine ``myhost``. Then
|
||||
you can ad-hoc distribute your tests by typing::
|
||||
|
||||
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||
|
||||
This will synchronize your ``mypkg`` package directory
|
||||
to an remote ssh account and then locally collect tests
|
||||
and send them to remote places for execution.
|
||||
|
||||
You can specify multiple ``--rsyncdir`` directories
|
||||
to be sent to the remote side.
|
||||
|
||||
Sending tests to remote Socket Servers
|
||||
----------------------------------------
|
||||
|
||||
Download the single-module `socketserver.py`_ Python program
|
||||
and run it on the specified hosts like this::
|
||||
|
||||
python socketserver.py
|
||||
|
||||
It will tell you that it starts listening. You can now
|
||||
on your home machine specify this new socket host
|
||||
with something like this::
|
||||
|
||||
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||
|
||||
no remote installation requirements
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Synchronisation and running of tests only requires
|
||||
a bare Python installation on the remote side. No
|
||||
special software is installed - this is realized through the
|
||||
*zero installation* principle that the underlying
|
||||
`py.execnet`_ mechanisms implements.
|
||||
|
||||
|
||||
.. _`socketserver.py`: ../execnet/script/socketserver.py
|
||||
.. _`py.execnet`: execnet.html
|
||||
|
||||
Differences from local tests
|
||||
----------------------------
|
||||
|
||||
* Test order is rather random (instead of in file order).
|
||||
* the test process may hang due to network problems
|
||||
* you may not reference files outside of rsynced directory structures
|
||||
|
||||
Specifying test exec environments in a conftest.py
|
||||
-------------------------------------------------------------
|
||||
|
||||
Instead of specifying command line options, you can
|
||||
put options values in a ``conftest.py`` file like this::
|
||||
|
||||
pytest_option_tx = ['ssh=myhost//python=python2.5', 'popen//python=python2.5']
|
||||
pytest_option_dist = True
|
||||
|
||||
Any commandline ``--tx`` specifictions will add to the list of available execution
|
||||
environments.
|
||||
|
||||
Specifying "rsync" dirs in a conftest.py
|
||||
-------------------------------------------------------------
|
||||
|
||||
In your ``mypkg/conftest.py`` you may specify directories to synchronise
|
||||
or to exclude::
|
||||
|
||||
rsyncdirs = ['.', '../plugins']
|
||||
rsyncignore = ['_cache']
|
||||
|
||||
These directory specifications are relative to the directory
|
||||
where the ``conftest.py`` is found.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
Working Examples
|
||||
================
|
||||
|
||||
managing state at module, class and method level
|
||||
------------------------------------------------------------
|
||||
|
||||
Here is a working example for what goes on when you setup modules,
|
||||
classes and methods::
|
||||
|
||||
# [[from py/documentation/example/pytest/test_setup_flow_example.py]]
|
||||
|
||||
def setup_module(module):
|
||||
module.TestStateFullThing.classcount = 0
|
||||
|
||||
class TestStateFullThing:
|
||||
def setup_class(cls):
|
||||
cls.classcount += 1
|
||||
|
||||
def teardown_class(cls):
|
||||
cls.classcount -= 1
|
||||
|
||||
def setup_method(self, method):
|
||||
self.id = eval(method.func_name[5:])
|
||||
|
||||
def test_42(self):
|
||||
assert self.classcount == 1
|
||||
assert self.id == 42
|
||||
|
||||
def test_23(self):
|
||||
assert self.classcount == 1
|
||||
assert self.id == 23
|
||||
|
||||
def teardown_module(module):
|
||||
assert module.TestStateFullThing.classcount == 0
|
||||
|
||||
For this example the control flow happens as follows::
|
||||
|
||||
import test_setup_flow_example
|
||||
setup_module(test_setup_flow_example)
|
||||
setup_class(TestStateFullThing)
|
||||
instance = TestStateFullThing()
|
||||
setup_method(instance, instance.test_42)
|
||||
instance.test_42()
|
||||
setup_method(instance, instance.test_23)
|
||||
instance.test_23()
|
||||
teardown_class(TestStateFullThing)
|
||||
teardown_module(test_setup_flow_example)
|
||||
|
||||
Note that ``setup_class(TestStateFullThing)`` is called and not
|
||||
``TestStateFullThing.setup_class()`` which would require you
|
||||
to insert ``setup_class = classmethod(setup_class)`` to make
|
||||
your setup function callable. Did we mention that lazyness
|
||||
is a virtue?
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
|
||||
Learning by examples
|
||||
------------------------
|
||||
|
||||
XXX
|
||||
|
||||
adding custom options
|
||||
+++++++++++++++++++++++
|
||||
|
||||
py.test supports adding of standard optparse_ Options.
|
||||
A plugin may implement the ``addoption`` hook for registering
|
||||
custom options::
|
||||
|
||||
class ConftestPlugin:
|
||||
def pytest_addoption(self, parser):
|
||||
parser.addoption("-M", "--myopt", action="store",
|
||||
help="specify string to set myopt")
|
||||
|
||||
def pytest_configure(self, config):
|
||||
if config.option.myopt:
|
||||
# do action based on option value
|
||||
|
||||
.. _optparse: http://docs.python.org/library/optparse.html
|
||||
|
||||
Setting default values for test options
|
||||
-----------------------------------------
|
||||
|
||||
You can see all available command line options by running::
|
||||
|
||||
py.test -h
|
||||
|
||||
py.test will lookup values of options in this order:
|
||||
|
||||
* option value supplied at command line
|
||||
* content of environment variable ``PYTEST_OPTION_NAME=...``
|
||||
* ``name = ...`` setting in the nearest ``conftest.py`` file.
|
||||
|
||||
The name of an option usually is the one you find
|
||||
in the longform of the option, i.e. the name
|
||||
behind the ``--`` double-dash.
|
||||
|
||||
IOW, you can set default values for options per project, per
|
||||
home-directoray, per shell session or per test-run.
|
||||
|
||||
|
||||
|
||||
Plugin methods
|
||||
----------------------------------
|
||||
|
||||
A Plugin class may implement the following attributes and methods:
|
||||
|
||||
XXX
|
||||
|
||||
_`pytest event`:
|
||||
|
||||
Pytest Events
|
||||
-------------------
|
||||
|
||||
XXX
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
|
||||
Basic Features of ``py.test``
|
||||
=============================
|
||||
|
||||
automatic collection of tests on all levels
|
||||
-------------------------------------------
|
||||
|
||||
The automated test collection process walks the current
|
||||
directory (or the directory given as a command line argument)
|
||||
and all its subdirectories and collects python modules with a
|
||||
leading ``test_`` or trailing ``_test`` filename. From each
|
||||
test module every function with a leading ``test_`` or class with
|
||||
a leading ``Test`` name is collected. The collecting process can
|
||||
be customized at directory, module or class level. (see
|
||||
`collection process`_ for some implementation details).
|
||||
|
||||
.. _`generative tests`:
|
||||
.. _`collection process`: impl-test.html#collection-process
|
||||
|
||||
assert with the ``assert`` statement
|
||||
------------------------------------
|
||||
|
||||
``py.test`` allows to use the standard python
|
||||
``assert statement`` for verifying expectations
|
||||
and values in Python tests. For example, you can
|
||||
write the following in your tests::
|
||||
|
||||
assert hasattr(x, 'attribute')
|
||||
|
||||
to state that your object has a certain ``attribute``. In case this
|
||||
assertion fails you will see the value of ``x``. Intermediate
|
||||
values are computed by executing the assert expression a second time.
|
||||
If you execute code with side effects, e.g. read from a file like this::
|
||||
|
||||
assert f.read() != '...'
|
||||
|
||||
then you may get a warning from pytest if that assertions
|
||||
first failed and then succeeded.
|
||||
|
||||
asserting expected exceptions
|
||||
----------------------------------------------
|
||||
|
||||
In order to write assertions about exceptions, you use
|
||||
one of two forms::
|
||||
|
||||
py.test.raises(Exception, func, *args, **kwargs)
|
||||
py.test.raises(Exception, "func(*args, **kwargs)")
|
||||
|
||||
both of which execute the given function with args and kwargs and
|
||||
asserts that the given ``Exception`` is raised. The reporter will
|
||||
provide you with helpful output in case of failures such as *no
|
||||
exception* or *wrong exception*.
|
||||
|
||||
dynamically skipping tests
|
||||
----------------------------------------
|
||||
|
||||
If you want to skip tests you can use ``py.test.skip`` within
|
||||
test or setup functions. Example::
|
||||
|
||||
py.test.skip("message")
|
||||
|
||||
You can also use a helper to skip on a failing import::
|
||||
|
||||
docutils = py.test.importorskip("docutils")
|
||||
|
||||
or to skip if a library does not have the right version::
|
||||
|
||||
docutils = py.test.importorskip("docutils", minversion="0.3")
|
||||
|
||||
The version will be read from the module's ``__version__`` attribute.
|
||||
|
||||
|
||||
generative tests: yielding more tests
|
||||
-------------------------------------
|
||||
|
||||
*Generative tests* are test methods that are *generator functions* which
|
||||
``yield`` callables and their arguments. This is most useful for running a
|
||||
test function multiple times against different parameters. Example::
|
||||
|
||||
def test_generative():
|
||||
for x in (42,17,49):
|
||||
yield check, x
|
||||
|
||||
def check(arg):
|
||||
assert arg % 7 == 0 # second generated tests fails!
|
||||
|
||||
Note that ``test_generative()`` will cause three tests
|
||||
to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
|
||||
of which the middle one will obviously fail.
|
||||
|
||||
To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
|
||||
|
||||
def test_generative():
|
||||
for x in (42,17,49):
|
||||
yield "case %d" % x, check, x
|
||||
|
||||
|
||||
.. _`selection by keyword`:
|
||||
|
||||
selecting/unselecting tests by keyword
|
||||
---------------------------------------------
|
||||
|
||||
Pytest's keyword mechanism provides a powerful way to
|
||||
group and selectively run tests in your test code base.
|
||||
You can selectively run tests by specifiying a keyword
|
||||
on the command line. Examples:
|
||||
|
||||
py.test -k test_simple
|
||||
py.test -k "-test_simple"
|
||||
|
||||
will run all tests matching (or not matching) the
|
||||
"test_simple" keyword. Note that you need to quote
|
||||
the keyword if "-" is recognized as an indicator
|
||||
for a commandline option. Lastly, you may use
|
||||
|
||||
py.test. -k "test_simple:"
|
||||
|
||||
which will run all tests after the expression has *matched once*, i.e.
|
||||
all tests that are seen after a test that matches the "test_simple"
|
||||
keyword.
|
||||
|
||||
By default, all filename parts and
|
||||
class/function names of a test function are put into the set
|
||||
of keywords for a given test. You may specify additional
|
||||
kewords like this::
|
||||
|
||||
@py.test.mark(webtest=True)
|
||||
def test_send_http():
|
||||
...
|
||||
|
||||
testing with multiple python versions / executables
|
||||
---------------------------------------------------
|
||||
|
||||
With ``--tx EXECUTABLE`` you can specify a python
|
||||
executable (e.g. ``python2.2``) with which the tests
|
||||
will be executed.
|
||||
|
||||
|
||||
testing starts immediately
|
||||
--------------------------
|
||||
|
||||
Testing starts as soon as the first ``test item``
|
||||
is collected. The collection process is iterative
|
||||
and does not need to complete before your first
|
||||
test items are executed.
|
||||
|
||||
support for modules containing tests
|
||||
--------------------------------------
|
||||
|
||||
As ``py.test`` operates as a separate cmdline
|
||||
tool you can easily have a command line utility and
|
||||
some tests in the same file.
|
||||
|
||||
debug with the ``print`` statement
|
||||
----------------------------------
|
||||
|
||||
By default, ``py.test`` catches text written to stdout/stderr during
|
||||
the execution of each individual test. This output will only be
|
||||
displayed however if the test fails; you will not see it
|
||||
otherwise. This allows you to put debugging print statements in your
|
||||
code without being overwhelmed by all the output that might be
|
||||
generated by tests that do not fail.
|
||||
|
||||
Each failing test that produced output during the running of the test
|
||||
will have its output displayed in the ``recorded stdout`` section.
|
||||
|
||||
The catching of stdout/stderr output can be disabled using the
|
||||
``--nocapture`` option to the ``py.test`` tool. Any output will
|
||||
in this case be displayed as soon as it is generated.
|
||||
|
||||
test execution order
|
||||
--------------------------------
|
||||
|
||||
Tests usually run in the order in which they appear in the files.
|
||||
However, tests should not rely on running one after another, as
|
||||
this prevents more advanced usages: running tests
|
||||
distributedly or selectively, or in "looponfailing" mode,
|
||||
will cause them to run in random order.
|
||||
|
||||
useful tracebacks, recursion detection
|
||||
--------------------------------------
|
||||
|
||||
A lot of care is taken to present nice tracebacks in case of test
|
||||
failure. Try::
|
||||
|
||||
py.test py/doc/example/pytest/failure_demo.py
|
||||
|
||||
to see a variety of 17 tracebacks, each tailored to a different
|
||||
failure situation.
|
||||
|
||||
``py.test`` uses the same order for presenting tracebacks as Python
|
||||
itself: the oldest function call is shown first, and the most recent call is
|
||||
shown last. A ``py.test`` reported traceback starts with your
|
||||
failing test function. If the maximum recursion depth has been
|
||||
exceeded during the running of a test, for instance because of
|
||||
infinite recursion, ``py.test`` will indicate where in the
|
||||
code the recursion was taking place. You can inhibit
|
||||
traceback "cutting" magic by supplying ``--fulltrace``.
|
||||
|
||||
There is also the possibility of using ``--tb=short`` to get regular CPython
|
||||
tracebacks. Or you can use ``--tb=no`` to not show any tracebacks at all.
|
||||
|
||||
no inheritance requirement
|
||||
--------------------------
|
||||
|
||||
Test classes are recognized by their leading ``Test`` name. Unlike
|
||||
``unitest.py``, you don't need to inherit from some base class to make
|
||||
them be found by the test runner. Besides being easier, it also allows
|
||||
you to write test classes that subclass from application level
|
||||
classes.
|
||||
|
||||
disabling a test class
|
||||
----------------------
|
||||
|
||||
If you want to disable a complete test class you
|
||||
can set the class-level attribute ``disabled``.
|
||||
For example, in order to avoid running some tests on Win32::
|
||||
|
||||
class TestPosixOnly:
|
||||
disabled = sys.platform == 'win32'
|
||||
|
||||
def test_xxx(self):
|
||||
...
|
||||
|
||||
testing for deprecated APIs
|
||||
------------------------------
|
||||
|
||||
In your tests you can use ``py.test.deprecated_call(func, *args, **kwargs)``
|
||||
to test that a particular function call triggers a DeprecationWarning.
|
||||
This is useful for testing phasing out of old APIs in your projects.
|
||||
|
||||
doctest support
|
||||
-------------------
|
||||
|
||||
If you want to integrate doctests, ``py.test`` now by default
|
||||
picks up files matching the ``test_*.txt`` or ``*_test.txt``
|
||||
patterns and processes them as text files containing doctests.
|
||||
This is an experimental feature and likely to change
|
||||
its implementation.
|
||||
|
||||
|
||||
.. _`reStructured Text`: http://docutils.sourceforge.net
|
||||
.. _`Python debugger`: http://docs.python.org/lib/module-pdb.html
|
||||
|
||||
|
||||
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/
|
|
@ -1,67 +1,56 @@
|
|||
|
||||
pytest plugins
|
||||
==================
|
||||
Many of py.test's features are implemented as a plugin.
|
||||
|
||||
specifying plugins for directories or test modules
|
||||
---------------------------------------------------------
|
||||
|
||||
py.test loads and configures plugins at tool startup and whenever
|
||||
it encounters new confest or test modules which
|
||||
contain a ``pytest_plugins`` definition. At tool
|
||||
startup the ``PYTEST_PLUGINS`` environment variable
|
||||
is considered as well.
|
||||
|
||||
Example
|
||||
++++++++++
|
||||
|
||||
If you create a ``conftest.py`` file with the following content::
|
||||
|
||||
pytest_plugins = "pytest_plugin1", MyLocalPluginClass
|
||||
|
||||
then test execution within that directory can make use
|
||||
of the according instantiated plugins:
|
||||
|
||||
* the module ``pytest_plugin1`` will be imported and
|
||||
and its contained `Plugin1`` class instantiated.
|
||||
A plugin module can put its dependencies into
|
||||
a "pytest_plugins" attribute at module level as well.
|
||||
|
||||
* the ``MyLocalPluginClass`` will be instantiated
|
||||
and added to the pluginmanager.
|
||||
|
||||
|
||||
Plugin methods
|
||||
----------------------------------
|
||||
|
||||
A Plugin class may implement the following attributes and methods:
|
||||
|
||||
* pytest_cmdlineoptions: a list of optparse-style py.test.config.Option objects
|
||||
* pytest_configure(self, config): called after command line options have been parsed
|
||||
* pytest_unconfigure(self, config): called before the test process quits
|
||||
* pytest_event(self, event): called for each `pytest event`_
|
||||
|
||||
XXX reference APIcheck'ed full documentation
|
||||
|
||||
_`pytest event`:
|
||||
|
||||
Pytest Events
|
||||
-------------------
|
||||
|
||||
XXX Various reporting events.
|
||||
|
||||
Example plugins
|
||||
Available plugins
|
||||
-----------------------
|
||||
|
||||
XXX here are a few existing plugins:
|
||||
py.test has a number of default plugins. You can see which
|
||||
ones by specifying ``--trace=config``.
|
||||
|
||||
* adding reporting facilities, e.g.
|
||||
* adding reporting facilities, examples:
|
||||
pytest_terminal: default reporter for writing info to terminals
|
||||
pytest_resultlog: log test results in machine-readable form to a file
|
||||
pytest_eventlog: log all internal pytest events to a file
|
||||
|
||||
* marking and reporting test specially
|
||||
pytest_xfail: "expected to fail" test marker
|
||||
|
||||
* funcargs for advanced
|
||||
pytest_tmpdir: provide temporary directories to test functions
|
||||
pytest_plugintester: generic apichecks, support for functional plugin tests
|
||||
pytest_pytester: support for testing py.test runs
|
||||
|
||||
* extending test execution, e.g.
|
||||
pytest_apigen: tracing values of function/method calls when running tests
|
||||
|
||||
|
||||
Loading plugins and specifying dependencies
|
||||
---------------------------------------------------------
|
||||
|
||||
py.test loads and configures plugins at tool startup:
|
||||
|
||||
* by reading the ``PYTEST_PLUGINS`` environment variable
|
||||
and importing the comma-separated list of plugin names.
|
||||
|
||||
* by loading all plugins specified via one or more ``-p name``
|
||||
command line options.
|
||||
|
||||
* by loading all plugins specified via a ``pytest_plugins``
|
||||
variable in ``conftest.py`` files or test modules.
|
||||
|
||||
example: ensure a plugin is loaded
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
If you create a ``conftest.py`` file with the following content::
|
||||
|
||||
pytest_plugins = "pytest_myextension",
|
||||
|
||||
then all tests in that directory and below it will run with
|
||||
an instantiated "pytest_myextension". Here is how instantiation
|
||||
takes place:
|
||||
|
||||
* the module ``pytest_extension`` will be imported and
|
||||
and its contained `ExtensionPlugin`` class will
|
||||
be instantiated. A plugin module may specify its
|
||||
dependencies via another ``pytest_plugins`` definition.
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
.. _`setuptools installation`: http://pypi.python.org/pypi/setuptools
|
||||
|
||||
|
||||
Installing py.test
|
||||
-------------------------------
|
||||
|
||||
This document assumes basic python knowledge. If you have a
|
||||
`setuptools installation`_, install ``py.test`` by typing::
|
||||
|
||||
easy_install -U py
|
||||
|
||||
For alternative installation methods please see the download_ page.
|
||||
|
||||
You should now have a ``py.test`` command line tool and can
|
||||
look at its documented cmdline options via this command::
|
||||
|
||||
py.test -h
|
||||
|
||||
Writing and running a test
|
||||
---------------------------
|
||||
|
||||
``py.test`` is the command line tool to run tests.
|
||||
Let's write a first test module by putting the following
|
||||
test function into a ``test_sample.py`` file::
|
||||
|
||||
# content of test_sample.py
|
||||
def test_answer():
|
||||
assert 42 == 43
|
||||
|
||||
Now you can run the test by passing it as an argument::
|
||||
|
||||
py.test test_sample.py
|
||||
|
||||
What does happen here? ``py.test`` looks for functions and
|
||||
methods in the module that start with ``test_``. It then
|
||||
executes those tests. Assertions about test outcomes are
|
||||
done via the standard ``assert`` statement.
|
||||
|
||||
You can also use ``py.test`` to run all tests in a directory structure by
|
||||
invoking it without any arguments::
|
||||
|
||||
py.test
|
||||
|
||||
This will automatically collect and run any Python module whose filenames
|
||||
start with ``test_`` or ends with ``_test`` from the directory and any
|
||||
subdirectories, starting with the current directory, and run them. Each
|
||||
Python test module is inspected for test methods starting with ``test_``.
|
||||
|
||||
.. Organising your tests
|
||||
.. ---------------------------
|
||||
|
||||
Please refer to `features`_ for a walk through the basic features.
|
||||
|
||||
|
||||
.. _download: download.html
|
||||
.. _features: test-features.html
|
||||
|
||||
|
659
py/doc/test.txt
659
py/doc/test.txt
|
@ -1,651 +1,22 @@
|
|||
================================
|
||||
The ``py.test`` tool and library
|
||||
================================
|
||||
*py.test* is a tool for:
|
||||
|
||||
.. contents::
|
||||
.. sectnum::
|
||||
* rapidly writing unit- and functional tests in Python
|
||||
* writing tests for non-python code and data
|
||||
* receiving useful reports on test failures
|
||||
* distributing tests to multiple CPUs and remote environments
|
||||
|
||||
quickstart_: for getting started immediately.
|
||||
|
||||
This document is about the *usage* of the ``py.test`` testing tool. There is
|
||||
also document describing the `implementation and the extending of py.test`_.
|
||||
features_: a walk through basic features and usage.
|
||||
|
||||
.. _`implementation and the extending of py.test`: impl-test.html
|
||||
plugins_: using available plugins.
|
||||
|
||||
starting point: ``py.test`` command line tool
|
||||
=============================================
|
||||
extend_: writing plugins and advanced configuration.
|
||||
|
||||
We presume you have done an installation as per the
|
||||
download_ page after which you should be able to execute the
|
||||
'py.test' tool from a command line shell.
|
||||
`distributed testing`_ how to distribute test runs to other machines and platforms.
|
||||
|
||||
``py.test`` is the command line tool to run tests. You can supply it
|
||||
with a Python test file (or directory) by passing it as an argument::
|
||||
|
||||
py.test test_sample.py
|
||||
|
||||
``py.test`` looks for any functions and methods in the module that
|
||||
start with with ``test_`` and will then run those methods. Assertions
|
||||
about test outcomes are done via the standard ``assert`` statement.
|
||||
|
||||
This means you can write tests without any boilerplate::
|
||||
|
||||
# content of test_sample.py
|
||||
def test_answer():
|
||||
assert 42 == 43
|
||||
|
||||
You may have test functions and test methods, there is no
|
||||
need to subclass or to put tests into a class.
|
||||
You can also use ``py.test`` to run all tests in a directory structure by
|
||||
invoking it without any arguments::
|
||||
|
||||
py.test
|
||||
|
||||
This will automatically collect and run any Python module whose filenames
|
||||
start with ``test_`` or ends with ``_test`` from the directory and any
|
||||
subdirectories, starting with the current directory, and run them. Each
|
||||
Python test module is inspected for test methods starting with ``test_``.
|
||||
|
||||
.. _download: download.html
|
||||
.. _features:
|
||||
|
||||
Basic Features of ``py.test``
|
||||
=============================
|
||||
|
||||
assert with the ``assert`` statement
|
||||
------------------------------------
|
||||
|
||||
Writing assertions is very simple and this is one of py.test's
|
||||
most noticeable features, as you can use the ``assert``
|
||||
statement with arbitrary expressions. For example you can
|
||||
write the following in your tests::
|
||||
|
||||
assert hasattr(x, 'attribute')
|
||||
|
||||
to state that your object has a certain ``attribute``. In case this
|
||||
assertion fails the test ``reporter`` will provide you with a very
|
||||
helpful analysis and a clean traceback.
|
||||
|
||||
|
||||
how to write assertions about exceptions
|
||||
----------------------------------------
|
||||
|
||||
In order to write assertions about exceptions, you use
|
||||
one of two forms::
|
||||
|
||||
py.test.raises(Exception, func, *args, **kwargs)
|
||||
py.test.raises(Exception, "func(*args, **kwargs)")
|
||||
|
||||
both of which execute the given function with args and kwargs and
|
||||
asserts that the given ``Exception`` is raised. The reporter will
|
||||
provide you with helpful output in case of failures such as *no
|
||||
exception* or *wrong exception*.
|
||||
|
||||
Skipping tests
|
||||
----------------------------------------
|
||||
|
||||
If you want to skip tests you can use ``py.test.skip`` within
|
||||
test or setup functions. Example::
|
||||
|
||||
py.test.skip("message")
|
||||
|
||||
You can also use a helper to skip on a failing import::
|
||||
|
||||
docutils = py.test.importorskip("docutils")
|
||||
|
||||
or to skip if the library does not have the right version::
|
||||
|
||||
docutils = py.test.importorskip("docutils", minversion="0.3")
|
||||
|
||||
automatic collection of tests on all levels
|
||||
-------------------------------------------
|
||||
|
||||
The automated test collection process walks the current
|
||||
directory (or the directory given as a command line argument)
|
||||
and all its subdirectories and collects python modules with a
|
||||
leading ``test_`` or trailing ``_test`` filename. From each
|
||||
test module every function with a leading ``test_`` or class with
|
||||
a leading ``Test`` name is collected. The collecting process can
|
||||
be customized at directory, module or class level. (see
|
||||
`collection process`_ for some implementation details).
|
||||
|
||||
.. _`generative tests`:
|
||||
.. _`collection process`: impl-test.html#collection-process
|
||||
|
||||
generative tests: yielding more tests
|
||||
-------------------------------------
|
||||
|
||||
*Generative tests* are test methods that are *generator functions* which
|
||||
``yield`` callables and their arguments. This is most useful for running a
|
||||
test function multiple times against different parameters.
|
||||
Example::
|
||||
|
||||
def test_generative():
|
||||
for x in (42,17,49):
|
||||
yield check, x
|
||||
|
||||
def check(arg):
|
||||
assert arg % 7 == 0 # second generated tests fails!
|
||||
|
||||
Note that ``test_generative()`` will cause three tests
|
||||
to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
|
||||
of which the middle one will obviously fail.
|
||||
|
||||
To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
|
||||
|
||||
def test_generative():
|
||||
for x in (42,17,49):
|
||||
yield "case %d" % x, check, x
|
||||
|
||||
|
||||
.. _`selection by keyword`:
|
||||
|
||||
selecting/unselecting tests by keyword
|
||||
---------------------------------------------
|
||||
|
||||
Pytest's keyword mechanism provides a powerful way to
|
||||
group and selectively run tests in your test code base.
|
||||
You can selectively run tests by specifiying a keyword
|
||||
on the command line. Examples:
|
||||
|
||||
py.test -k test_simple
|
||||
py.test -k "-test_simple"
|
||||
|
||||
will run all tests matching (or not matching) the
|
||||
"test_simple" keyword. Note that you need to quote
|
||||
the keyword if "-" is recognized as an indicator
|
||||
for a commandline option. Lastly, you may use
|
||||
|
||||
py.test. -k "test_simple:"
|
||||
|
||||
which will run all tests after the expression has *matched once*, i.e.
|
||||
all tests that are seen after a test that matches the "test_simple"
|
||||
keyword.
|
||||
|
||||
By default, all filename parts and
|
||||
class/function names of a test function are put into the set
|
||||
of keywords for a given test. You may specify additional
|
||||
kewords like this::
|
||||
|
||||
@py.test.mark(webtest=True)
|
||||
def test_send_http():
|
||||
...
|
||||
|
||||
testing with multiple python versions / executables
|
||||
---------------------------------------------------
|
||||
|
||||
With ``--exec=EXECUTABLE`` you can specify a python
|
||||
executable (e.g. ``python2.2``) with which the tests
|
||||
will be executed.
|
||||
|
||||
|
||||
testing starts immediately
|
||||
--------------------------
|
||||
|
||||
Testing starts as soon as the first ``test item``
|
||||
is collected. The collection process is iterative
|
||||
and does not need to complete before your first
|
||||
test items are executed.
|
||||
|
||||
no interference with cmdline utilities
|
||||
--------------------------------------
|
||||
|
||||
As ``py.test`` mainly operates as a separate cmdline
|
||||
tool you can easily have a command line utility and
|
||||
some tests in the same file.
|
||||
|
||||
debug with the ``print`` statement
|
||||
----------------------------------
|
||||
|
||||
By default, ``py.test`` catches text written to stdout/stderr during
|
||||
the execution of each individual test. This output will only be
|
||||
displayed however if the test fails; you will not see it
|
||||
otherwise. This allows you to put debugging print statements in your
|
||||
code without being overwhelmed by all the output that might be
|
||||
generated by tests that do not fail.
|
||||
|
||||
Each failing test that produced output during the running of the test
|
||||
will have its output displayed in the ``recorded stdout`` section.
|
||||
|
||||
The catching of stdout/stderr output can be disabled using the
|
||||
``--nocapture`` option to the ``py.test`` tool. Any output will
|
||||
in this case be displayed as soon as it is generated.
|
||||
|
||||
test execution order
|
||||
--------------------------------
|
||||
|
||||
Tests usually run in the order in which they appear in the files.
|
||||
However, tests should not rely on running one after another, as
|
||||
this prevents more advanced usages: running tests
|
||||
distributedly or selectively, or in "looponfailing" mode,
|
||||
will cause them to run in random order.
|
||||
|
||||
useful tracebacks, recursion detection
|
||||
--------------------------------------
|
||||
|
||||
A lot of care is taken to present nice tracebacks in case of test
|
||||
failure. Try::
|
||||
|
||||
py.test py/documentation/example/pytest/failure_demo.py
|
||||
|
||||
to see a variety of 17 tracebacks, each tailored to a different
|
||||
failure situation.
|
||||
|
||||
``py.test`` uses the same order for presenting tracebacks as Python
|
||||
itself: the oldest function call is shown first, and the most recent call is
|
||||
shown last. A ``py.test`` reported traceback starts with your
|
||||
failing test function. If the maximum recursion depth has been
|
||||
exceeded during the running of a test, for instance because of
|
||||
infinite recursion, ``py.test`` will indicate where in the
|
||||
code the recursion was taking place. You can inhibit
|
||||
traceback "cutting" magic by supplying ``--fulltrace``.
|
||||
|
||||
There is also the possibility of using ``--tb=short`` to get regular CPython
|
||||
tracebacks. Or you can use ``--tb=no`` to not show any tracebacks at all.
|
||||
|
||||
no inheritance requirement
|
||||
--------------------------
|
||||
|
||||
Test classes are recognized by their leading ``Test`` name. Unlike
|
||||
``unitest.py``, you don't need to inherit from some base class to make
|
||||
them be found by the test runner. Besides being easier, it also allows
|
||||
you to write test classes that subclass from application level
|
||||
classes.
|
||||
|
||||
disabling a test class
|
||||
----------------------
|
||||
|
||||
If you want to disable a complete test class you
|
||||
can set the class-level attribute ``disabled``.
|
||||
For example, in order to avoid running some tests on Win32::
|
||||
|
||||
class TestEgSomePosixStuff:
|
||||
disabled = sys.platform == 'win32'
|
||||
|
||||
def test_xxx(self):
|
||||
...
|
||||
|
||||
testing for deprecated APIs
|
||||
------------------------------
|
||||
|
||||
In your tests you can use ``py.test.deprecated_call(func, *args, **kwargs)``
|
||||
to test that a particular function call triggers a DeprecationWarning.
|
||||
This is useful for testing phasing out of old APIs in your projects.
|
||||
|
||||
Managing test state across test modules, classes and methods
|
||||
------------------------------------------------------------
|
||||
|
||||
Often you want to create some files, database connections or other
|
||||
state in order to run tests in a certain environment. With
|
||||
``py.test`` there are three scopes for which you can provide hooks to
|
||||
manage such state. Again, ``py.test`` will detect these hooks in
|
||||
modules on a name basis. The following module-level hooks will
|
||||
automatically be called by the session::
|
||||
|
||||
def setup_module(module):
|
||||
""" setup up any state specific to the execution
|
||||
of the given module.
|
||||
"""
|
||||
|
||||
def teardown_module(module):
|
||||
""" teardown any state that was previously setup
|
||||
with a setup_module method.
|
||||
"""
|
||||
|
||||
The following hooks are available for test classes::
|
||||
|
||||
def setup_class(cls):
|
||||
""" setup up any state specific to the execution
|
||||
of the given class (which usually contains tests).
|
||||
"""
|
||||
|
||||
def teardown_class(cls):
|
||||
""" teardown any state that was previously setup
|
||||
with a call to setup_class.
|
||||
"""
|
||||
|
||||
def setup_method(self, method):
|
||||
""" setup up any state tied to the execution of the given
|
||||
method in a class. setup_method is invoked for every
|
||||
test method of a class.
|
||||
"""
|
||||
|
||||
def teardown_method(self, method):
|
||||
""" teardown any state that was previously setup
|
||||
with a setup_method call.
|
||||
"""
|
||||
|
||||
The last two hooks, ``setup_method`` and ``teardown_method``, are
|
||||
equivalent to ``setUp`` and ``tearDown`` in the Python standard
|
||||
library's ``unitest`` module.
|
||||
|
||||
All setup/teardown methods are optional. You could have a
|
||||
``setup_module`` but no ``teardown_module`` and the other way round.
|
||||
|
||||
Note that while the test session guarantees that for every ``setup`` a
|
||||
corresponding ``teardown`` will be invoked (if it exists) it does
|
||||
*not* guarantee that any ``setup`` is called only happens once. For
|
||||
example, the session might decide to call the ``setup_module`` /
|
||||
``teardown_module`` pair more than once during the execution of a test
|
||||
module.
|
||||
|
||||
Experimental doctest support
|
||||
------------------------------------------------------------
|
||||
|
||||
If you want to integrate doctests, ``py.test`` now by default
|
||||
picks up files matching the ``test_*.txt`` or ``*_test.txt``
|
||||
patterns and processes them as text files containing doctests.
|
||||
This is an experimental feature and likely to change
|
||||
its implementation.
|
||||
|
||||
Working Examples
|
||||
================
|
||||
|
||||
Example for managing state at module, class and method level
|
||||
------------------------------------------------------------
|
||||
|
||||
Here is a working example for what goes on when you setup modules,
|
||||
classes and methods::
|
||||
|
||||
# [[from py/documentation/example/pytest/test_setup_flow_example.py]]
|
||||
|
||||
def setup_module(module):
|
||||
module.TestStateFullThing.classcount = 0
|
||||
|
||||
class TestStateFullThing:
|
||||
def setup_class(cls):
|
||||
cls.classcount += 1
|
||||
|
||||
def teardown_class(cls):
|
||||
cls.classcount -= 1
|
||||
|
||||
def setup_method(self, method):
|
||||
self.id = eval(method.func_name[5:])
|
||||
|
||||
def test_42(self):
|
||||
assert self.classcount == 1
|
||||
assert self.id == 42
|
||||
|
||||
def test_23(self):
|
||||
assert self.classcount == 1
|
||||
assert self.id == 23
|
||||
|
||||
def teardown_module(module):
|
||||
assert module.TestStateFullThing.classcount == 0
|
||||
|
||||
For this example the control flow happens as follows::
|
||||
|
||||
import test_setup_flow_example
|
||||
setup_module(test_setup_flow_example)
|
||||
setup_class(TestStateFullThing)
|
||||
instance = TestStateFullThing()
|
||||
setup_method(instance, instance.test_42)
|
||||
instance.test_42()
|
||||
setup_method(instance, instance.test_23)
|
||||
instance.test_23()
|
||||
teardown_class(TestStateFullThing)
|
||||
teardown_module(test_setup_flow_example)
|
||||
|
||||
|
||||
Note that ``setup_class(TestStateFullThing)`` is called and not
|
||||
``TestStateFullThing.setup_class()`` which would require you
|
||||
to insert ``setup_class = classmethod(setup_class)`` to make
|
||||
your setup function callable. Did we mention that lazyness
|
||||
is a virtue?
|
||||
|
||||
Some ``py.test`` command-line options
|
||||
=====================================
|
||||
|
||||
Regular options
|
||||
---------------
|
||||
|
||||
``-v, --verbose``
|
||||
Increase verbosity. This shows a test per line while running and also
|
||||
shows the traceback after interrupting the test run with Ctrl-C.
|
||||
|
||||
|
||||
``-x, --exitfirst``
|
||||
exit instantly on the first error or the first failed test.
|
||||
|
||||
|
||||
``-s, --nocapture``
|
||||
disable catching of sys.stdout/stderr output.
|
||||
|
||||
|
||||
``-k KEYWORD``
|
||||
only run test items matching the given keyword expression. You can also add
|
||||
use ``-k -KEYWORD`` to exlude tests from being run. The keyword is matched
|
||||
against filename, test class name, method name.
|
||||
|
||||
|
||||
``-l, --showlocals``
|
||||
show locals in tracebacks: for every frame in the traceback, show the values
|
||||
of the local variables.
|
||||
|
||||
|
||||
``--pdb``
|
||||
drop into pdb (the `Python debugger`_) on exceptions. If the debugger is
|
||||
quitted, the next test is run. This implies ``-s``.
|
||||
|
||||
|
||||
``--tb=TBSTYLE``
|
||||
traceback verboseness: ``long`` is the default, ``short`` are the normal
|
||||
Python tracebacks, ``no`` omits tracebacks completely.
|
||||
|
||||
|
||||
``--fulltrace``
|
||||
Don't cut any tracebacks. The default is to leave out frames if an infinite
|
||||
recursion is detected.
|
||||
|
||||
|
||||
``--nomagic``
|
||||
Refrain from using magic as much as possible. This can be useful if you are
|
||||
suspicious that ``py.test`` somehow interferes with your program in
|
||||
unintended ways (if this is the case, please contact us!).
|
||||
|
||||
|
||||
``--collectonly``
|
||||
Only collect tests, don't execute them.
|
||||
|
||||
|
||||
``--traceconfig``
|
||||
trace considerations of conftest.py files. Useful when you have various
|
||||
conftest.py files around and are unsure about their interaction.
|
||||
|
||||
``-f, --looponfailing``
|
||||
Loop on failing test set. This is a feature you can use when you are trying
|
||||
to fix a number of failing tests: First all the tests are being run. If a
|
||||
number of tests are failing, these are run repeatedly afterwards. Every
|
||||
repetition is started once a file below the directory that you started
|
||||
testing for is changed. If one of the previously failing tests now passes,
|
||||
it is removed from the test set.
|
||||
|
||||
``--exec=EXECUTABLE``
|
||||
Python executable to run the tests with. Useful for testing on different
|
||||
versions of Python.
|
||||
|
||||
|
||||
|
||||
experimental options
|
||||
--------------------
|
||||
|
||||
**Note**: these options could change in the future.
|
||||
|
||||
|
||||
``-d, --dist``
|
||||
ad-hoc `distribute tests across machines`_ (requires conftest settings)
|
||||
|
||||
|
||||
``-w, --startserver``
|
||||
starts local web server for displaying test progress.
|
||||
|
||||
|
||||
``-r, --runbrowser``
|
||||
Run browser (implies --startserver).
|
||||
|
||||
|
||||
``--boxed``
|
||||
Use boxed tests: run each test in an external process. Very useful for testing
|
||||
things that occasionally segfault (since normally the segfault then would
|
||||
stop the whole test process).
|
||||
|
||||
``--rest``
|
||||
`reStructured Text`_ output reporting.
|
||||
|
||||
|
||||
.. _`reStructured Text`: http://docutils.sourceforge.net
|
||||
.. _`Python debugger`: http://docs.python.org/lib/module-pdb.html
|
||||
|
||||
|
||||
.. _`distribute tests across machines`:
|
||||
|
||||
|
||||
Automated Distributed Testing
|
||||
==================================
|
||||
|
||||
If you have a project with a large number of tests, and you have
|
||||
machines accessible through SSH, ``py.test`` can distribute
|
||||
tests across the machines. It does not require any particular
|
||||
installation on the remote machine sides as it uses `py.execnet`_
|
||||
mechanisms to distribute execution. Using distributed testing
|
||||
can speed up your development process considerably and it
|
||||
may also be useful where you need to use a remote server
|
||||
that has more resources (e.g. RAM/diskspace) than your
|
||||
local machine.
|
||||
|
||||
*WARNING*: support for distributed testing is experimental,
|
||||
its mechanics and configuration options may change without
|
||||
prior notice. Particularly, not all reporting features
|
||||
of the in-process py.test have been integrated into
|
||||
the distributed testing approach.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Local requirements:
|
||||
|
||||
* ssh client
|
||||
* python
|
||||
|
||||
requirements for remote machines:
|
||||
|
||||
* ssh daemon running
|
||||
* ssh keys setup to allow login without a password
|
||||
* python
|
||||
* unix like machine (reliance on ``os.fork``)
|
||||
|
||||
How to use it
|
||||
-----------------------
|
||||
|
||||
When you issue ``py.test -d`` then your computer becomes
|
||||
the distributor of tests ("master") and will start collecting
|
||||
and distributing tests to several machines. The machines
|
||||
need to be specified in a ``conftest.py`` file.
|
||||
|
||||
At start up, the master connects to each node using `py.execnet.SshGateway`_
|
||||
and *rsyncs* all specified python packages to all nodes.
|
||||
Then the master collects all of the tests and immediately sends test item
|
||||
descriptions to its connected nodes. Each node has a local queue of tests
|
||||
to run and begins to execute the tests, following the setup and teardown
|
||||
semantics. The test are distributed at function and method level.
|
||||
When a test run on a node is completed it reports back the result
|
||||
to the master.
|
||||
|
||||
The master can run one of three reporters to process the events
|
||||
from the testing nodes: command line, rest output and ajaxy web based.
|
||||
|
||||
.. _`py.execnet`: execnet.html
|
||||
.. _`py.execnet.SshGateway`: execnet.html
|
||||
|
||||
Differences from local tests
|
||||
----------------------------
|
||||
|
||||
* Test order is rather random (instead of in file order).
|
||||
* the test process may hang due to network problems
|
||||
* you may not reference files outside of rsynced directory structures
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
You must create a conftest.py in any parent directory above your tests.
|
||||
|
||||
The options that you need to specify in that conftest.py file are:
|
||||
|
||||
* `dist_hosts`: a required list of host specifications
|
||||
* `dist_rsync_roots` - a list of relative locations to copy to the remote machines.
|
||||
* `dist_rsync_ignore` - a list of relative locations to ignore for rsyncing
|
||||
* `dist_remotepython` - the remote python executable to run.
|
||||
* `dist_nicelevel` - process priority of remote nodes.
|
||||
* `dist_boxed` - will run each single test in a separate process
|
||||
(allowing to survive segfaults for example)
|
||||
* `dist_taskspernode` - Maximum number of tasks being queued to remote nodes
|
||||
|
||||
Sample configuration::
|
||||
|
||||
dist_hosts = ['localhost', 'user@someserver:/tmp/somedir']
|
||||
dist_rsync_roots = ['../pypy', '../py']
|
||||
dist_remotepython = 'python2.4'
|
||||
dist_nicelevel = 10
|
||||
dist_boxed = False
|
||||
dist_maxwait = 100
|
||||
dist_taskspernode = 10
|
||||
|
||||
To use the browser-based reporter (with a nice AJAX interface) you have to tell
|
||||
``py.test`` to run a small server locally using the ``-w`` or ``--startserver``
|
||||
command line options. Afterwards you can point your browser to localhost:8000
|
||||
to see the progress of the testing.
|
||||
|
||||
Development Notes
|
||||
-----------------
|
||||
|
||||
Changing the behavior of the web based reporter requires `pypy`_ since the
|
||||
javascript is actually generated fom rpython source.
|
||||
|
||||
.. _`pypy`: http://codespeak.net/pypy
|
||||
|
||||
Future/Planned Features of py.test
|
||||
==================================
|
||||
|
||||
integrating various test methods
|
||||
-------------------------------------------
|
||||
|
||||
There are various conftest.py's out there
|
||||
that do html-reports, ad-hoc distribute tests
|
||||
to windows machines or other fun stuff.
|
||||
These approaches should be offerred natively
|
||||
by py.test at some point (requires refactorings).
|
||||
In addition, performing special checks such
|
||||
as w3c-conformance tests or ReST checks
|
||||
should be offered from mainline py.test.
|
||||
|
||||
more distributed testing
|
||||
-----------------------------------------
|
||||
|
||||
We'd like to generalize and extend our ad-hoc
|
||||
distributed testing approach to allow for running
|
||||
on multiple platforms simultanously and selectively.
|
||||
The web reporter should learn to deal with driving
|
||||
complex multi-platform test runs and providing
|
||||
useful introspection and interactive debugging hooks.
|
||||
|
||||
|
||||
move to report event based architecture
|
||||
--------------------------------------------
|
||||
|
||||
To facilitate writing of custom reporters
|
||||
py.test is to learn to generate reporting events
|
||||
at all levels which a reporter can choose to
|
||||
interpret and present. The distributed testing
|
||||
approach already uses such an approach and
|
||||
we'd like to unify this with the default
|
||||
in-process py.test mode.
|
||||
|
||||
|
||||
see what other tools do currently (nose, etc.)
|
||||
----------------------------------------------------
|
||||
|
||||
There are various tools out there, among them
|
||||
the nose_ clone. It's about time to look again
|
||||
at these and other tools, integrate interesting
|
||||
features and maybe collaborate on some issues.
|
||||
|
||||
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/
|
||||
.. _quickstart: test-quickstart.html
|
||||
.. _features: test-features.html
|
||||
.. _plugins: test-plugins.html
|
||||
.. _extend: test-ext.html
|
||||
.. _`distributed testing`: test-dist.html
|
||||
|
|
Loading…
Reference in New Issue