massive documentation refinements

This commit is contained in:
holger krekel 2010-11-02 00:53:53 +01:00
parent 7d495cc250
commit c18cca9d54
27 changed files with 622 additions and 508 deletions

View File

@ -46,7 +46,7 @@ except ImportError:
args = [quote(arg) for arg in args] args = [quote(arg) for arg in args]
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
DEFAULT_VERSION = "0.6.13" DEFAULT_VERSION = "0.6.14"
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
SETUPTOOLS_FAKED_VERSION = "0.6c11" SETUPTOOLS_FAKED_VERSION = "0.6c11"

View File

@ -14,6 +14,9 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
regen:
COLUMNS=76 regendoc --update *.txt */*.txt
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files" @echo " html to make standalone HTML files"

View File

@ -7,6 +7,7 @@ py.test reference documentation
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
customize.txt
assert.txt assert.txt
funcargs.txt funcargs.txt
xunit_setup.txt xunit_setup.txt
@ -16,6 +17,6 @@ py.test reference documentation
skipping.txt skipping.txt
mark.txt mark.txt
recwarn.txt recwarn.txt
doctest.txt
unittest.txt unittest.txt
doctest.txt

View File

@ -1,5 +1,5 @@
Writing easy assertions in tests Writing and reporting of assertions in tests
============================================ ============================================
assert with the ``assert`` statement assert with the ``assert`` statement
@ -21,7 +21,7 @@ assertion fails you will see the value of ``x``::
$ py.test test_assert1.py $ py.test test_assert1.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_assert1.py test path 1: test_assert1.py
test_assert1.py F test_assert1.py F
@ -101,7 +101,7 @@ if you run this module::
$ py.test test_assert2.py $ py.test test_assert2.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_assert2.py test path 1: test_assert2.py
test_assert2.py F test_assert2.py F

View File

@ -11,9 +11,7 @@ Getting help on version, option names, environment vars
py.test --version # shows where pytest was imported from py.test --version # shows where pytest was imported from
py.test --funcargs # show available builtin function arguments py.test --funcargs # show available builtin function arguments
py.test --help-config # show configuration values py.test -h | --help # show help on command line and config file options
py.test -h | --help # show help
Stopping after the first (or N) failures Stopping after the first (or N) failures

View File

@ -25,7 +25,8 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode'] extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo',
'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']

View File

@ -1,23 +1,25 @@
Contact and Communication points
.. _`contact channels`:
Contact channels
=================================== ===================================
- `py-dev developers list`_ announcements and discussions. - `new issue tracker`_ to report bugs or suggest features.
See also the `old issue tracker`_ but don't submit bugs there.
- `Testing In Python`_: a mailing list for Python testing tools and discussion.
- `py-dev developers list`_ pytest specific announcements and discussions.
- #pylib on irc.freenode.net IRC channel for random questions. - #pylib on irc.freenode.net IRC channel for random questions.
- `tetamap`_: Holger Krekel's blog, often about testing and py.test related news. - `tetamap`_: Holger Krekel's blog, often about testing and py.test related news.
- `commit mailing list`_
- `Testing In Python`_: a mailing list for testing tools and discussion.
- `commit mailing list`_ or `@pylibcommit`_ to follow development commits,
- `bitbucket issue tracker`_ use this bitbucket issue tracker to report
bugs or request features.
- `merlinux.eu`_ offers on-site teaching and consulting services. - `merlinux.eu`_ offers on-site teaching and consulting services.
.. _`bitbucket issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/ .. _`new issue tracker`: http://bitbucket.org/hpk42/pytest/issues/
.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
.. _`merlinux.eu`: http://merlinux.eu .. _`merlinux.eu`: http://merlinux.eu
@ -28,20 +30,8 @@ Contact and Communication points
.. _`@pylibcommit`: http://twitter.com/pylibcommit .. _`@pylibcommit`: http://twitter.com/pylibcommit
..
get an account on codespeak
---------------------------
codespeak_ is where the subversion repository is hosted. If you know
someone who is active on codespeak already or you are otherwise known in
the community (see also: FOAF_) you will get access. But even if
you are new to the python developer community please come to the IRC
or the mailing list and ask questions, get involved.
.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python .. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
.. _FOAF: http://en.wikipedia.org/wiki/FOAF .. _FOAF: http://en.wikipedia.org/wiki/FOAF
.. _us: http://codespeak.net/mailman/listinfo/py-dev
.. _codespeak: http://codespeak.net/
.. _`py-dev`: .. _`py-dev`:
.. _`development mailing list`: .. _`development mailing list`:
.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev .. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev

View File

@ -1,7 +1,3 @@
================================================
Customizing and Extending py.test
================================================
basic test configuration basic test configuration
=================================== ===================================
@ -58,309 +54,4 @@ builtin configuration file options
py.test --maxfail=2 -rf test_hello.py py.test --maxfail=2 -rf test_hello.py
.. _`function arguments`: funcargs.html .. _`function arguments`: funcargs.html
.. _`extensions`:
Plugin basics and project configuration
=============================================
.. _`local plugin`:
py.test implements all aspects of its functionality by calling `well specified
hooks`_. Hook functions are discovered in :file:`conftest.py` files or in
`named plugins`_. :file:`conftest.py` files are useful for keeping test
extensions and customizations close to test code.
local conftest.py plugins
--------------------------------------------------------------
local ``conftest.py`` plugins contain directory-specific hook implemenations. Its contained runtest- and collection- related hooks are called when collecting or running tests in files or directories next to or below the ``conftest.py``
file. Example: Assume the following layout and content of files::
a/conftest.py:
def pytest_runtest_setup(item):
print ("setting up", item)
a/test_in_subdir.py:
def test_sub():
pass
test_flat.py:
def test_flat():
pass
Here is how you might run it::
py.test test_flat.py # will not show "setting up"
py.test a/test_sub.py # will show "setting up"
``py.test`` loads all ``conftest.py`` files upwards from the command
line file arguments. It usually performs look up right-to-left, i.e.
the hooks in "closer" conftest files will be called earlier than further
away ones. This means you can even have a ``conftest.py`` file in your home
directory to customize test functionality globally for all of your projects.
.. Note::
If you have ``conftest.py`` files which do not reside in a
python package directory (i.e. one containing an ``__init__.py``) then
"import conftest" can be ambigous because there might be other
``conftest.py`` files as well on your PYTHONPATH or ``sys.path``.
It is good practise for projects to put ``conftest.py`` within a package
scope or to never import anything from the conftest.py file.
.. _`named plugins`: plugin/index.html
Plugin discovery at tool startup
--------------------------------------------
py.test loads plugin modules at tool startup in the following way:
* by loading all plugins registered through `setuptools entry points`_.
* by pre-scanning the command line for the ``-p name`` option
and loading the specified plugin before actual command line parsing.
* by loading all :file:`conftest.py` files as inferred by the command line
invocation (test files and all of its *parent* directories).
Note that ``conftest.py`` files from *sub* directories are by default
not loaded at tool startup.
* by recursively loading all plugins specified by the
``pytest_plugins`` variable in ``conftest.py`` files
Requiring/Loading plugins in a test module or conftest file
-------------------------------------------------------------
You can require plugins in a test module or a conftest file like this::
pytest_plugins = "name1", "name2",
When the test module or conftest plugin is loaded the specified plugins
will be loaded as well. You can also use dotted path like this::
pytest_plugins = "myapp.testsupport.myplugin"
which will import the specified module as a py.test plugin.
.. _`setuptools entry points`:
.. _registered:
Writing setuptools-registered plugins
------------------------------------------------------
.. _`Distribute`: http://pypi.python.org/pypi/distribute
.. _`setuptools`: http://pypi.python.org/pypi/setuptools
If you want to make your plugin publically available, you
can use `setuptools`_ or `Distribute`_ which both allow
to register an entry point. ``py.test`` will register
all objects with the ``pytest11`` entry point.
To make your plugin available you may insert the following
lines in your setuptools/distribute-based setup-invocation:
.. sourcecode:: python
# sample ./setup.py file
from setuptools import setup
setup(
name="myproject",
packages = ['myproject']
# the following makes a plugin available to py.test
entry_points = {
'pytest11': [
'name_of_plugin = myproject.pluginmodule',
]
},
)
If a package is installed with this setup, py.test will load
``myproject.pluginmodule`` under the ``name_of_plugin`` name
and use it as a plugin.
Accessing another plugin by name
--------------------------------------------
If a plugin wants to collaborate with code from
another plugin it can obtain a reference through
the plugin manager like this:
.. sourcecode:: python
plugin = config.pluginmanager.getplugin("name_of_plugin")
If you want to look at the names of existing plugins, use
the ``--traceconfig`` option.
.. _`well specified hooks`:
py.test hook reference
====================================
hook specification and validation
-----------------------------------------
py.test calls hook functions to implement initialization, running,
test execution and reporting. When py.test loads a plugin it validates
that all hook functions conform to their respective hook specification.
Each hook function name and its argument names need to match a hook
specification exactly but it is allowed for a hook function to accept
*less* parameters than specified. If you mistype argument names or the
hook name itself you get useful errors.
initialisation, command line and configuration hooks
--------------------------------------------------------------------
.. currentmodule:: pytest.hookspec
.. autofunction:: pytest_cmdline_parse
.. autofunction:: pytest_namespace
.. autofunction:: pytest_addoption
.. autofunction:: pytest_cmdline_main
.. autofunction:: pytest_configure
.. autofunction:: pytest_unconfigure
generic "runtest" hooks
------------------------------
All all runtest related hooks receive a :py:class:`pytest.collect.Item` object.
.. autofunction:: pytest_runtest_protocol
.. autofunction:: pytest_runtest_setup
.. autofunction:: pytest_runtest_call
.. autofunction:: pytest_runtest_teardown
.. autofunction:: pytest_runtest_makereport
For deeper understanding you may look at the default implementation of
these hooks in :py:mod:`pytest.plugin.runner` and maybe also
in :py:mod:`pytest.plugin.pdb` which intercepts creation
of reports in order to drop to interactive debugging.
The :py:mod:`pytest.plugin.terminal` reported specifically uses
the reporting hook to print information about a test run.
collection hooks
------------------------------
py.test calls the following hooks for collecting files and directories:
.. autofunction:: pytest_ignore_collect
.. autofunction:: pytest_collect_directory
.. autofunction:: pytest_collect_file
For influencing the collection of objects in Python modules
you can use the following hook:
.. autofunction:: pytest_pycollect_makeitem
reporting hooks
------------------------------
Collection related reporting hooks:
.. autofunction: pytest_collectstart
.. autofunction: pytest_itemcollected
.. autofunction: pytest_collectreport
.. autofunction: pytest_deselected
And here is the central hook for reporting about
test execution:
.. autofunction: pytest_runtest_logreport
The test collection tree
======================================================
Default filesystem test discovery
-----------------------------------------------
Test collection starts from specified paths or from the current
directory. All tests are collected ahead of running the first test.
(This used to be different in earlier versions of ``py.test`` where
collection and running was interweaved which made test randomization
and distributed testing harder).
Collection nodes which have children are called "Collectors" and otherwise
they are called "Items" or "test items". Here is an example of such a
tree::
example $ py.test --collectonly test_collectonly.py
<Directory 'example'>
<Module 'test_collectonly.py'>
<Function 'test_function'>
<Class 'TestClass'>
<Instance '()'>
<Function 'test_method'>
<Function 'test_anothermethod'>
By default all directories not starting with a dot are traversed,
looking for ``test_*.py`` and ``*_test.py`` files. Those Python
files are imported under their `package name`_.
The Module collector looks for test functions
and test classes and methods. Test functions and methods
are prefixed ``test`` by default. Test classes must
start with a capitalized ``Test`` prefix.
Customizing error messages
-------------------------------------------------
On test and collection nodes ``py.test`` will invoke
the ``node.repr_failure(excinfo)`` function which
you may override and make it return an error
representation string of your choice. It
will be reported as a (red) string.
.. _`package name`:
constructing the package name for test modules
-------------------------------------------------
Test modules are imported under their fully qualified
name. Given a filesystem ``fspath`` it is constructed as follows:
* walk the directories up to the last one that contains
an ``__init__.py`` file.
* perform ``sys.path.insert(0, basedir)``.
* import the root package as ``root``
Reference of important objects involved in hooks
===========================================================
.. autoclass:: pytest.plugin.config.Config
:members:
.. autoclass:: pytest.plugin.config.Parser
:members:
.. autoclass:: pytest.plugin.session.Node(name, parent)
:members:
..
.. autoclass:: pytest.plugin.session.File(fspath, parent)
:members:
.. autoclass:: pytest.plugin.session.Item(name, parent)
:members:
.. autoclass:: pytest.plugin.python.Module(name, parent)
:members:
.. autoclass:: pytest.plugin.python.Class(name, parent)
:members:
.. autoclass:: pytest.plugin.python.Function(name, parent)
:members:
.. autoclass:: pytest.plugin.runner.CallInfo
:members:
.. autoclass:: pytest.plugin.runner.TestReport
:members:

45
doc/discovery.txt Normal file
View File

@ -0,0 +1,45 @@
Test collection and discovery
======================================================
.. _`discovered`:
Default filesystem test discovery
-----------------------------------------------
Test collection starts from paths specified at the command line or from
the current directory. Tests are collected ahead of running the first test.
(This used to be different in earlier versions of ``py.test`` where
collection and running was interweaved which made test randomization
and distributed testing harder).
Collection nodes which have children are called "Collectors" and otherwise
they are called "Items" or "test items". Here is an example of such a
tree::
example $ py.test --collectonly test_collectonly.py
<Directory 'example'>
<Module 'test_collectonly.py'>
<Function 'test_function'>
<Class 'TestClass'>
<Instance '()'>
<Function 'test_method'>
<Function 'test_anothermethod'>
By default all directories not starting with a dot are traversed,
looking for ``test_*.py`` and ``*_test.py`` files. Those Python
files are imported under their `package name`_.
The Module collector looks for test functions
and test classes and methods. Test functions and methods
are prefixed ``test`` by default. Test classes must
start with a capitalized ``Test`` prefix.
Customizing error messages
-------------------------------------------------
On test and collection nodes ``py.test`` will invoke
the ``node.repr_failure(excinfo)`` function which
you may override and make it return an error
representation string of your choice. It
will be reported as a (red) string.

View File

@ -44,11 +44,7 @@ then you can just invoke ``py.test`` without command line options::
$ py.test $ py.test
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: /tmp/doc-exec-288 test path 1: /tmp/doc-exec-197
conftest.py . ============================= in 0.00 seconds =============================
example.rst .
mymodule.py .
========================= 3 passed in 0.01 seconds =========================

View File

@ -36,12 +36,12 @@ and when running it will see a skipped "slow" test::
$ py.test test_module.py -rs # "-rs" means report on the little 's' $ py.test test_module.py -rs # "-rs" means report on the little 's'
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_module.py test path 1: test_module.py
test_module.py .s test_module.py .s
========================= short test summary info ========================== ========================= short test summary info ==========================
SKIP [1] /tmp/doc-exec-12/conftest.py:9: 'need --runslow option to run' SKIP [1] /tmp/doc-exec-195/conftest.py:9: 'need --runslow option to run'
=================== 1 passed, 1 skipped in 0.02 seconds ==================== =================== 1 passed, 1 skipped in 0.02 seconds ====================
@ -49,7 +49,7 @@ Or run it including the ``slow`` marked test::
$ py.test test_module.py --runslow $ py.test test_module.py --runslow
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_module.py test path 1: test_module.py
test_module.py .. test_module.py ..

View File

@ -49,7 +49,7 @@ You can now run the test::
$ py.test test_sample.py $ py.test test_sample.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_sample.py test path 1: test_sample.py
test_sample.py F test_sample.py F
@ -57,7 +57,7 @@ You can now run the test::
================================= FAILURES ================================= ================================= FAILURES =================================
_______________________________ test_answer ________________________________ _______________________________ test_answer ________________________________
mysetup = <conftest.MySetup instance at 0x1a09f38> mysetup = <conftest.MySetup instance at 0x2809a70>
def test_answer(mysetup): def test_answer(mysetup):
app = mysetup.myapp() app = mysetup.myapp()
@ -122,12 +122,12 @@ Running it yields::
$ py.test test_ssh.py -rs $ py.test test_ssh.py -rs
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_ssh.py test path 1: test_ssh.py
test_ssh.py s test_ssh.py s
========================= short test summary info ========================== ========================= short test summary info ==========================
SKIP [1] /tmp/doc-exec-9/conftest.py:22: 'specify ssh host with --ssh' SKIP [1] /tmp/doc-exec-198/conftest.py:22: 'specify ssh host with --ssh'
======================== 1 skipped in 0.02 seconds ========================= ======================== 1 skipped in 0.02 seconds =========================

View File

@ -25,8 +25,8 @@ now execute the test specification::
nonpython $ py.test test_simple.yml nonpython $ py.test test_simple.yml
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev10 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: /home/hpk/p/pytest/doc/example/nonpython test path 1: test_simple.yml
test_simple.yml .F test_simple.yml .F
@ -35,7 +35,7 @@ now execute the test specification::
usecase execution failed usecase execution failed
spec failed: 'some': 'other' spec failed: 'some': 'other'
no further details known at this point. no further details known at this point.
==================== 1 failed, 1 passed in 0.06 seconds ==================== ==================== 1 failed, 1 passed in 0.37 seconds ====================
You get one dot for the passing ``sub1: sub1`` check and one failure. You get one dot for the passing ``sub1: sub1`` check and one failure.
Obviously in the above ``conftest.py`` you'll want to implement a more Obviously in the above ``conftest.py`` you'll want to implement a more
@ -45,7 +45,7 @@ reporting in ``verbose`` mode::
nonpython $ py.test -v nonpython $ py.test -v
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev10 -- /home/hpk/venv/0/bin/python platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 -- /home/hpk/venv/0/bin/python
test path 1: /home/hpk/p/pytest/doc/example/nonpython test path 1: /home/hpk/p/pytest/doc/example/nonpython
test_simple.yml:1: usecase: ok PASSED test_simple.yml:1: usecase: ok PASSED
@ -56,7 +56,7 @@ reporting in ``verbose`` mode::
usecase execution failed usecase execution failed
spec failed: 'some': 'other' spec failed: 'some': 'other'
no further details known at this point. no further details known at this point.
==================== 1 failed, 1 passed in 0.06 seconds ==================== ==================== 1 failed, 1 passed in 0.07 seconds ====================
While developing your custom test collection and execution it's also While developing your custom test collection and execution it's also
interesting to just look at the collection tree:: interesting to just look at the collection tree::

View File

@ -1,82 +1,51 @@
Frequent Issues and Questions Some Issues and Questions
================================== ==================================
.. _`installation issues`: .. note::
Installation issues If you don't find an answer here, checkout the :ref:`contact channels`
------------------------------ to get help.
easy_install or pip not found?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Consult distribute_ to install the ``easy_install`` tool on your machine.
You may also use the original but somewhat older `setuptools`_ project
although we generally recommend to use ``distribute`` because it contains
more bug fixes and also works for Python3.
For Python2 you can also consult pip_ for the popular ``pip`` tool.
However, If you want to install on Python3 you need to use Distribute_ which
provides the ``easy_install`` utility.
py.test not found on Windows despite installation?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.. _`Python for Windows`: http://www.imladris.com/Scripts/PythonForWindows.html
- **Windows**: If "easy_install" or "py.test" are not found
please see here for preparing your environment for running
command line tools: `Python for Windows`_. You may alternatively
use an `ActivePython install`_ which makes command line tools
automatically available under Windows.
.. _`ActivePython install`: http://www.activestate.com/activepython/downloads
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
so ``py.test`` will not work correctly. You may install py.test on
CPython and type ``py.test --genscript=mytest`` and then use
``jython mytest`` to run py.test for your tests to run in Jython.
On naming, nosetests, licensing and magic XXX On naming, nosetests, licensing and magic XXX
------------------------------------------------ ------------------------------------------------
Why the ``py.test`` naming, why not ``pytest``? Why a ``py.test`` instead of a ``pytest`` command?
++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++
XXX Some historic, some practical reasons: ``py.test`` used to be part of
the ``py`` package which provided several developer utitilities,
because of TAB-completion under Bash/Shells. If you hit all starting with ``py.<TAB>``, providing nice TAB-completion. If
``py.<TAB>`` you'll get a list of available development you install ``pip install pycmd`` you get these tools from a separate
tools that all share the ``py.`` prefix. Another motivation package. These days the command line tool could be ``pytest``
was to unify the package ("py.test") and tool filename. but then many people have gotten used to the old name and there
also is another tool with this same which would lead to some clashes.
What's py.test's relation to ``nosetests``? What's py.test's relation to ``nosetests``?
+++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++
py.test and nose_ share basic philosophy when it comes py.test and nose_ share basic philosophy when it comes
to running Python tests. In fact, to running Python tests. In fact, you can run many tests
with py.test-1.1.0 it is ever easier to run many test suites written for unittest or nose with py.test. nose_ was originally created
that currently work with ``nosetests``. nose_ was created
as a clone of ``py.test`` when py.test was in the ``0.8`` release as a clone of ``py.test`` when py.test was in the ``0.8`` release
cycle so some of the newer features_ introduced with py.test-1.0 cycle.
and py.test-1.1 have no counterpart in nose_.
.. _features: test/features.html .. _features: test/features.html
.. _apipkg: http://pypi.python.org/pypi/apipkg
What's this "magic" with py.test? What's this "magic" with py.test?
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++
Around 2007 it was claimed that py.test was magic implementation Around 2007 (version ``0.8``) some several people claimed that py.test
wise XXX. It has been refactored. was using too much "magic". It has been refactored a lot. It is today
probably one of the smallest, most universally runnable and most
customizable testing frameworks for Python. It remains true
that ``py.test`` uses metaprogramming techniques, i.e. it views
test code similar to how compilers view programs, using a
somewhat abstract internal model.
* when an ``assert`` statement fails, py.test re-interprets the expression It's also true that the no-boilerplate testing is implemented by making
use of the Python assert statement through "re-interpretation":
When an ``assert`` statement fails, py.test re-interprets the expression
to show intermediate values if a test fails. If your expression to show intermediate values if a test fails. If your expression
has side effects the intermediate values may not be the same, obfuscating has side effects the intermediate values may not be the same, obfuscating
the initial error (this is also explained at the command line if it happens). the initial error (this is also explained at the command line if it happens).
@ -92,10 +61,9 @@ function arguments, parametrized tests and setup
.. _funcargs: test/funcargs.html .. _funcargs: test/funcargs.html
Is using funcarg- versus xUnit-based setup a style question? Is using funcarg- versus xUnit setup a style question?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
XXX
For simple applications and for people experienced with nose_ or For simple applications and for people experienced with nose_ or
unittest-style test setup using `xUnit style setup`_ unittest-style test setup using `xUnit style setup`_
feels natural. For larger test suites, parametrized testing feels natural. For larger test suites, parametrized testing

View File

@ -4,9 +4,11 @@ py.test Features
no-boilerplate testing with Python no-boilerplate testing with Python
---------------------------------- ----------------------------------
- automatic customizable Python test discovery - automatic, fully customizable Python test discovery
- :pep:`8` consistent testing style
- allows simple test functions
- ``assert`` statement for your assertions
- powerful parametrization of test functions - powerful parametrization of test functions
- use the ``assert`` statement for your assertions
- rely on powerful traceback and assertion reporting - rely on powerful traceback and assertion reporting
- use ``print`` or ``pdb`` debugging on failures - use ``print`` or ``pdb`` debugging on failures

View File

@ -32,7 +32,7 @@ Running the test looks like this::
$ py.test test_simplefactory.py $ py.test test_simplefactory.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_simplefactory.py test path 1: test_simplefactory.py
test_simplefactory.py F test_simplefactory.py F
@ -133,7 +133,7 @@ Running this::
$ py.test test_example.py $ py.test test_example.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_example.py test path 1: test_example.py
test_example.py .........F test_example.py .........F
@ -154,7 +154,7 @@ Note that the ``pytest_generate_tests(metafunc)`` hook is called during
the test collection phase. You can have a look at it with this:: the test collection phase. You can have a look at it with this::
$ py.test --collectonly test_example.py $ py.test --collectonly test_example.py
<Directory 'doc-exec-341'> <Directory 'doc-exec-167'>
<Module 'test_example.py'> <Module 'test_example.py'>
<Function 'test_func[0]'> <Function 'test_func[0]'>
<Function 'test_func[1]'> <Function 'test_func[1]'>
@ -171,14 +171,31 @@ If you want to select only the run with the value ``7`` you could do::
$ py.test -v -k 7 test_example.py # or -k test_func[7] $ py.test -v -k 7 test_example.py # or -k test_func[7]
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 -- /home/hpk/venv/0/bin/python platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 -- /home/hpk/venv/0/bin/python
test path 1: test_example.py test path 1: test_example.py
test_example.py:6: test_func[0] PASSED
test_example.py:6: test_func[1] PASSED
test_example.py:6: test_func[2] PASSED
test_example.py:6: test_func[3] PASSED
test_example.py:6: test_func[4] PASSED
test_example.py:6: test_func[5] PASSED
test_example.py:6: test_func[6] PASSED
test_example.py:6: test_func[7] PASSED test_example.py:6: test_func[7] PASSED
test_example.py:6: test_func[8] PASSED
test_example.py:6: test_func[9] FAILED
======================== 9 tests deselected by '7' ========================= ================================= FAILURES =================================
================== 1 passed, 9 deselected in 0.01 seconds ================== _______________________________ test_func[9] _______________________________
numiter = 9
def test_func(numiter):
> assert numiter < 9
E assert 9 < 9
test_example.py:7: AssertionError
==================== 1 failed, 9 passed in 0.04 seconds ====================
.. _`metafunc object`: .. _`metafunc object`:

View File

@ -1,4 +1,4 @@
Getting Started Installation and Getting Started
=================================== ===================================
.. _`easy_install`: .. _`easy_install`:
@ -20,7 +20,7 @@ To check your installation has installed the correct version::
If you get an error, checkout :ref:`installation issues`. If you get an error, checkout :ref:`installation issues`.
Writing a simple test function with an assertion Our first test run
---------------------------------------------------------- ----------------------------------------------------------
Let's create a small file with a test function testing a function Let's create a small file with a test function testing a function
@ -32,17 +32,17 @@ computes a certain value::
def test_answer(): def test_answer():
assert func(3) == 5 assert func(3) == 5
Now you can execute the test function:: You can execute the test function::
$ py.test test_sample.py $ py.test test_sample.py
========================= test session starts ========================== =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev4 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_sample.py test path 1: test_sample.py
test_sample.py F test_sample.py F
=============================== FAILURES =============================== ================================= FAILURES =================================
_____________________________ test_answer ______________________________ _______________________________ test_answer ________________________________
def test_answer(): def test_answer():
> assert func(3) == 5 > assert func(3) == 5
@ -50,23 +50,27 @@ Now you can execute the test function::
E + where 4 = func(3) E + where 4 = func(3)
test_sample.py:4: AssertionError test_sample.py:4: AssertionError
======================= 1 failed in 0.02 seconds ======================= ========================= 1 failed in 0.02 seconds =========================
We got a failure because our little ``func(3)`` call did not return ``5``. We told py.test to run the ``test_sample.py`` file and it :ref:`discovered` the
A few notes on this little test invocation: ``test_answer`` function because of the ``test_`` prefix. We got a
failure because our little ``func(3)`` call did not return ``5``.
* ``test_answer`` was identified as a test function because of the .. note::
``test_`` prefix,
* we conveniently used the standard `assert statement`_ and the failure You can simply use the `assert statement`_ for coding expectations because
report shows us the intermediate values. intermediate values will be presented to you. Or to put it bluntly,
there is no need to learn all `the JUnit legacy methods`_ for expressing
assertions.
.. _`the JUnit legacy methods`: http://docs.python.org/library/unittest.html#test-cases
.. _`assert statement`: http://docs.python.org/reference/simple_stmts.html#the-assert-statement .. _`assert statement`: http://docs.python.org/reference/simple_stmts.html#the-assert-statement
Asserting that a certain exception is raised Asserting a certain exception is raised
-------------------------------------------------------------- --------------------------------------------------------------
If you want to assert a test raises a certain exception you can If you want to assert some code raises an exception you can
use the ``raises`` helper:: use the ``raises`` helper::
# content of test_sysexit.py # content of test_sysexit.py
@ -78,18 +82,49 @@ use the ``raises`` helper::
with py.test.raises(SystemExit): with py.test.raises(SystemExit):
f() f()
Running it with:: Running it with, this time in "quiet" reporting mode::
$ py.test test_sysexit.py $ py.test -q test_sysexit.py
========================= test session starts ========================== .
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev4 1 passed in 0.01 seconds
test path 1: test_sysexit.py
test_sysexit.py . .. todo:: For further ways to assert exceptions see the :pyfunc:`raises`
======================= 1 passed in 0.01 seconds ======================= Grouping multiple tests in a class
--------------------------------------------------------------
.. For further ways to assert exceptions see the :pyfunc:`raises` If you start to have more than a few tests it often makes sense
to group tests logically, in classes and modules. Let's put two
tests in a class like this::
# content of test_class.py
class TestClass:
def test_one(self):
x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')
The two tests will be discovered because of the default `automatic test
discovery`_. There is no need to subclass anything. If we now run
the module we'll see one passed and one failed test::
$ py.test -q test_class.py
.F
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass instance at 0x1732368>
def test_two(self):
x = "hello"
> assert hasattr(x, 'check')
E assert hasattr('hello', 'check')
test_class.py:8: AssertionError
1 failed, 1 passed in 0.02 seconds
where to go from here where to go from here
------------------------------------- -------------------------------------
@ -99,6 +134,47 @@ Here are a few suggestions where to go next:
* :ref:`cmdline` for command line invocation examples * :ref:`cmdline` for command line invocation examples
* :ref:`good practises` for virtualenv, test layout, genscript support * :ref:`good practises` for virtualenv, test layout, genscript support
* :ref:`apiref` for documentation and examples on writing Python tests * :ref:`apiref` for documentation and examples on writing Python tests
* :ref:`examples` for more complex examples
.. _`installation issues`:
Installation issues
------------------------------
easy_install or pip not found?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Consult distribute_ to install the ``easy_install`` tool on your machine.
You may also use the original but somewhat older `setuptools`_ project
although we generally recommend to use ``distribute`` because it contains
more bug fixes and also works for Python3.
For Python2 you can also consult pip_ for the popular ``pip`` tool.
However, If you want to install on Python3 you need to use Distribute_ which
provides the ``easy_install`` utility.
py.test not found on Windows despite installation?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.. _`Python for Windows`: http://www.imladris.com/Scripts/PythonForWindows.html
- **Windows**: If "easy_install" or "py.test" are not found
please see here for preparing your environment for running
command line tools: `Python for Windows`_. You may alternatively
use an `ActivePython install`_ which makes command line tools
automatically available under Windows.
.. _`ActivePython install`: http://www.activestate.com/activepython/downloads
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
so ``py.test`` will not work correctly. You may install py.test on
CPython and type ``py.test --genscript=mytest`` and then use
``jython mytest`` to run py.test for your tests to run in Jython.
:ref:`examples` for more complex examples
.. include:: links.inc .. include:: links.inc

View File

@ -2,51 +2,91 @@
.. highlightlang:: python .. highlightlang:: python
.. _`good practises`: .. _`good practises`:
Good Practises Good Integration Practises
================================================= =================================================
Recommendation: install tool and dependencies virtually work with virtual environments
----------------------------------------------------------- -----------------------------------------------------------
We recommend to work with virtual environments We recommend to work with virtualenv_ environments and use easy_install_
(e.g. virtualenv_ or buildout_ based) and use easy_install_ (or pip_) for installing your application dependencies as well as
(or pip_) for installing py.test/pylib and any dependencies the ``pytest`` package itself. This way you get a much more reproducible
you need to run your tests. Local virtual Python environments environment. A good tool to help you automate test runs against multiple
(as opposed to system-wide "global" environments) make for a more dependency configurations or Python interpreters is `tox`_,
reproducible and reliable test environment. independently created by the main py.test author. The latter
is also useful for integration with the continous integration
server Hudson_.
.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv .. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
.. _`buildout`: http://www.buildout.org/ .. _`buildout`: http://www.buildout.org/
.. _pip: http://pypi.python.org/pypi/pip .. _pip: http://pypi.python.org/pypi/pip
Choosing a test layout / import rules
------------------------------------------
py.test supports common test layouts:
* inlining test directories into your application package, useful if you want to
keep (unit) tests and actually tested code close together::
mypkg/
__init__.py
appmodule.py
...
test/
test_app.py
...
* putting tests into an extra directory outside your actual application
code, useful if you have many functional tests or want to keep
tests separate from actual application code::
mypkg/
__init__.py
appmodule.py
tests/
test_app.py
...
You can always run your tests by pointing to it::
py.test tests/test_app.py # for external test dirs
py.test mypkg/test/test_app.py # for inlined test dirs
py.test mypkg # run tests in all below test directories
py.test # run all tests below current dir
...
.. note::
Test modules are imported under their fully qualified name as follows:
* ``basedir`` = first upward directory not containing an ``__init__.py``
* perform ``sys.path.insert(0, basedir)``.
* ``import path.to.test_module``
.. _standalone: .. _standalone:
Choosing a test layout
----------------------------
py.test supports common test layouts.
XXX
.. _`genscript method`: .. _`genscript method`:
Generating a py.test standalone Script Generating a py.test standalone Script
------------------------------------------- -------------------------------------------
If you are a maintainer or application developer and want users If you are a maintainer or application developer and want others
to run tests you can use a facility to generate a standalone to easily run tests you can generate a completely standalone "py.test"
"py.test" script that you can tell users to run:: script::
py.test --genscript=runtests.py py.test --genscript=runtests.py
will generate a ``mytest`` script that is, in fact, a ``py.test`` under generates a ``runtests.py`` script which is a fully functional basic
disguise. You can tell people to download and then e.g. run it like this:: ``py.test`` script, running unchanged under Python2 and Python3.
You can tell people to download and then e.g. run it like this to
produce a Paste URL::
python runtests.py --pastebin=all python runtests.py --pastebin=all
and ask them to send you the resulting URL. The resulting script has and ask them to send you the resulting URL.
all core features and runs unchanged under Python2 and Python3 interpreters.
.. _`Distribute for installation`: http://pypi.python.org/pypi/distribute#installation-instructions .. _`Distribute for installation`: http://pypi.python.org/pypi/distribute#installation-instructions
.. _`distribute installation`: http://pypi.python.org/pypi/distribute .. _`distribute installation`: http://pypi.python.org/pypi/distribute

View File

@ -1,6 +1,9 @@
py.test: no-boilerplate testing with Python py.test: no-boilerplate testing with Python
============================================== ==============================================
.. todolist::
Welcome to ``py.test`` documentation: Welcome to ``py.test`` documentation:
.. toctree:: .. toctree::
@ -8,7 +11,7 @@ Welcome to ``py.test`` documentation:
overview overview
apiref apiref
customize plugins
examples examples
talks talks
develop develop

View File

@ -16,3 +16,4 @@
.. _`pip`: http://pypi.python.org/pypi/pip .. _`pip`: http://pypi.python.org/pypi/pip
.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv .. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
.. _hudson: http://hudson-ci.org/ .. _hudson: http://hudson-ci.org/
.. _tox: http://codespeak.net/tox

View File

@ -88,8 +88,8 @@ You can use the ``-k`` command line option to select tests::
$ py.test -k webtest # running with the above defined examples yields $ py.test -k webtest # running with the above defined examples yields
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: /tmp/doc-exec-11 test path 1: /tmp/doc-exec-171
test_mark.py .. test_mark.py ..
test_mark_classlevel.py .. test_mark_classlevel.py ..
@ -100,8 +100,8 @@ And you can also run all tests except the ones that match the keyword::
$ py.test -k-webtest $ py.test -k-webtest
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: /tmp/doc-exec-11 test path 1: /tmp/doc-exec-171
===================== 4 tests deselected by '-webtest' ===================== ===================== 4 tests deselected by '-webtest' =====================
======================= 4 deselected in 0.01 seconds ======================= ======================= 4 deselected in 0.01 seconds =======================
@ -110,8 +110,8 @@ Or to only select the class::
$ py.test -kTestClass $ py.test -kTestClass
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: /tmp/doc-exec-11 test path 1: /tmp/doc-exec-171
test_mark_classlevel.py .. test_mark_classlevel.py ..

View File

@ -39,8 +39,8 @@ will be undone.
.. background check: .. background check:
$ py.test $ py.test
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: /tmp/doc-exec-296 test path 1: /tmp/doc-exec-172
============================= in 0.00 seconds ============================= ============================= in 0.00 seconds =============================

282
doc/plugins.txt Normal file
View File

@ -0,0 +1,282 @@
Writing, managing and understanding plugins
=============================================
.. _`local plugin`:
py.test implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic locations types::
* builtin plugins: loaded from py.test's own `pytest/plugin`_ directory.
* `external plugins`_: modules discovered through `setuptools entry points`_
* `conftest.py plugins`_: modules auto-discovered in test directories
.. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/
.. _`conftest.py plugins`:
conftest.py: local per-directory plugins
--------------------------------------------------------------
local ``conftest.py`` plugins contain directory-specific hook
implementations. Collection and test running activities will
invoke all hooks defined in "higher up" ``conftest.py`` files.
Example: Assume the following layout and content of files::
a/conftest.py:
def pytest_runtest_setup(item):
# called for running each test in 'a' directory
print ("setting up", item)
a/test_in_subdir.py:
def test_sub():
pass
test_flat.py:
def test_flat():
pass
Here is how you might run it::
py.test test_flat.py # will not show "setting up"
py.test a/test_sub.py # will show "setting up"
A note on ordering: ``py.test`` loads all ``conftest.py`` files upwards
from the command line file arguments. It usually performs look up
right-to-left, i.e. the hooks in "closer" conftest files will be called
earlier than further away ones.
.. Note::
If you have ``conftest.py`` files which do not reside in a
python package directory (i.e. one containing an ``__init__.py``) then
"import conftest" can be ambigous because there might be other
``conftest.py`` files as well on your PYTHONPATH or ``sys.path``.
It is thus good practise for projects to either put ``conftest.py``
under a package scope or to never import anything from a
conftest.py file.
.. _`installing plugins`:
.. _`external plugins`:
Installing External Plugins
------------------------------------------------------
Installing a plugin happens through any usual Python installation
tool, for example::
pip install pytest-NAME
pip uninstall pytest-NAME
If a plugin is installed, py.test automatically finds and integrates it,
there is no need to activate it. If you don't need a plugin anymore simply
de-install it. You can find a list of valid plugins through a
`pytest- pypi.python.org search`_.
.. _`available installable plugins`:
.. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
.. _`setuptools entry points`:
Writing an installable plugin
------------------------------------------------------
.. _`Distribute`: http://pypi.python.org/pypi/distribute
.. _`setuptools`: http://pypi.python.org/pypi/setuptools
If you want to write a plugin, there are many real-life examples
you can copy from:
* around 20 `builtin plugins`_ which comprise py.test's own functionality
* around 10 `external plugins`_ providing additional features
If you want to make your plugin externally available, you
may define a so called entry point for your distribution so
that ``py.test`` finds your plugin module. Entry points are
a feature that is provided by `setuptools`_ or `Distribute`_.
The concrete entry point is ``pytest11``. To make your plugin
available you can insert the following lines in your
setuptools/distribute-based setup-invocation:
.. sourcecode:: python
# sample ./setup.py file
from setuptools import setup
setup(
name="myproject",
packages = ['myproject']
# the following makes a plugin available to py.test
entry_points = {
'pytest11': [
'name_of_plugin = myproject.pluginmodule',
]
},
)
If a package is installed this way, py.test will load
``myproject.pluginmodule`` and accordingly call functions
if they match the `well specified hooks`_.
Plugin discovery order at tool startup
--------------------------------------------
py.test loads plugin modules at tool startup in the following way:
* by loading all builtin plugins
* by loading all plugins registered through `setuptools entry points`_.
* by pre-scanning the command line for the ``-p name`` option
and loading the specified plugin before actual command line parsing.
* by loading all :file:`conftest.py` files as inferred by the command line
invocation (test files and all of its *parent* directories).
Note that ``conftest.py`` files from *sub* directories are by default
not loaded at tool startup.
* by recursively loading all plugins specified by the
``pytest_plugins`` variable in ``conftest.py`` files
Requiring/Loading plugins in a test module or conftest file
-------------------------------------------------------------
You can require plugins in a test module or a conftest file like this::
pytest_plugins = "name1", "name2",
When the test module or conftest plugin is loaded the specified plugins
will be loaded as well. You can also use dotted path like this::
pytest_plugins = "myapp.testsupport.myplugin"
which will import the specified module as a py.test plugin.
.. _`setuptools entry points`:
.. _registered:
Accessing another plugin by name
--------------------------------------------
If a plugin wants to collaborate with code from
another plugin it can obtain a reference through
the plugin manager like this:
.. sourcecode:: python
plugin = config.pluginmanager.getplugin("name_of_plugin")
If you want to look at the names of existing plugins, use
the ``--traceconfig`` option.
.. _`well specified hooks`:
py.test hook reference
====================================
hook specification and validation
-----------------------------------------
py.test calls hook functions to implement initialization, running,
test execution and reporting. When py.test loads a plugin it validates
that all hook functions conform to their respective hook specification.
Each hook function name and its argument names need to match a hook
specification exactly but it is allowed for a hook function to accept
*less* parameters than specified. If you mistype argument names or the
hook name itself you get useful errors.
initialisation, command line and configuration hooks
--------------------------------------------------------------------
.. currentmodule:: pytest.hookspec
.. autofunction:: pytest_cmdline_parse
.. autofunction:: pytest_namespace
.. autofunction:: pytest_addoption
.. autofunction:: pytest_cmdline_main
.. autofunction:: pytest_configure
.. autofunction:: pytest_unconfigure
generic "runtest" hooks
------------------------------
All all runtest related hooks receive a :py:class:`pytest.collect.Item` object.
.. autofunction:: pytest_runtest_protocol
.. autofunction:: pytest_runtest_setup
.. autofunction:: pytest_runtest_call
.. autofunction:: pytest_runtest_teardown
.. autofunction:: pytest_runtest_makereport
For deeper understanding you may look at the default implementation of
these hooks in :py:mod:`pytest.plugin.runner` and maybe also
in :py:mod:`pytest.plugin.pdb` which intercepts creation
of reports in order to drop to interactive debugging.
The :py:mod:`pytest.plugin.terminal` reported specifically uses
the reporting hook to print information about a test run.
collection hooks
------------------------------
py.test calls the following hooks for collecting files and directories:
.. autofunction:: pytest_ignore_collect
.. autofunction:: pytest_collect_directory
.. autofunction:: pytest_collect_file
For influencing the collection of objects in Python modules
you can use the following hook:
.. autofunction:: pytest_pycollect_makeitem
reporting hooks
------------------------------
Collection related reporting hooks:
.. autofunction: pytest_collectstart
.. autofunction: pytest_itemcollected
.. autofunction: pytest_collectreport
.. autofunction: pytest_deselected
And here is the central hook for reporting about
test execution:
.. autofunction: pytest_runtest_logreport
Reference of important objects involved in hooks
===========================================================
.. autoclass:: pytest.plugin.config.Config
:members:
.. autoclass:: pytest.plugin.config.Parser
:members:
.. autoclass:: pytest.plugin.session.Node(name, parent)
:members:
..
.. autoclass:: pytest.plugin.session.File(fspath, parent)
:members:
.. autoclass:: pytest.plugin.session.Item(name, parent)
:members:
.. autoclass:: pytest.plugin.python.Module(name, parent)
:members:
.. autoclass:: pytest.plugin.python.Class(name, parent)
:members:
.. autoclass:: pytest.plugin.python.Function(name, parent)
:members:
.. autoclass:: pytest.plugin.runner.CallInfo
:members:
.. autoclass:: pytest.plugin.runner.TestReport
:members:

View File

@ -26,7 +26,7 @@ Running this would result in a passed test except for the last
$ py.test test_tmpdir.py $ py.test test_tmpdir.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_tmpdir.py test path 1: test_tmpdir.py
test_tmpdir.py F test_tmpdir.py F
@ -34,7 +34,7 @@ Running this would result in a passed test except for the last
================================= FAILURES ================================= ================================= FAILURES =================================
_____________________________ test_create_file _____________________________ _____________________________ test_create_file _____________________________
tmpdir = local('/tmp/pytest-427/test_create_file0') tmpdir = local('/tmp/pytest-1248/test_create_file0')
def test_create_file(tmpdir): def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt") p = tmpdir.mkdir("sub").join("hello.txt")
@ -45,7 +45,7 @@ Running this would result in a passed test except for the last
E assert 0 E assert 0
test_tmpdir.py:7: AssertionError test_tmpdir.py:7: AssertionError
========================= 1 failed in 0.03 seconds ========================= ========================= 1 failed in 0.04 seconds =========================
.. _`base temporary directory`: .. _`base temporary directory`:

View File

@ -1,11 +1,11 @@
unittest.py style testing integration unittest.TestCase support
===================================================================== =====================================================================
py.test has limited support for running Python `unittest.py style`_ tests. py.test has limited support for running Python `unittest.py style`_ tests.
It will automatically collect ``unittest.TestCase`` subclasses It will automatically collect ``unittest.TestCase`` subclasses
and their ``test`` methods in test files. It will invoke and their ``test`` methods in test files. It will invoke
``setUp/tearDown`` methods but also perform py.test's standard ways ``setUp/tearDown`` methods but also perform py.test's standard ways
of treating tests like IO capturing:: of treating tests like e.g. IO capturing::
# content of test_unittest.py # content of test_unittest.py
@ -21,7 +21,7 @@ Running it yields::
$ py.test test_unittest.py $ py.test test_unittest.py
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_unittest.py test path 1: test_unittest.py
test_unittest.py F test_unittest.py F
@ -55,7 +55,5 @@ Running it yields::
hello hello
========================= 1 failed in 0.02 seconds ========================= ========================= 1 failed in 0.02 seconds =========================
This plugin is enabled by default.
.. _`unittest.py style`: http://docs.python.org/library/unittest.html .. _`unittest.py style`: http://docs.python.org/library/unittest.html

View File

@ -74,6 +74,7 @@ you can also use the following functions to implement fixtures::
def teardown_method(function): def teardown_method(function):
""" teardown any state that was previously setup """ teardown any state that was previously setup
with a setup_function call. with a setup_function call.
"""
Note that it possible that setup/teardown pairs are invoked multiple Note that it possible that setup/teardown pairs are invoked multiple
times per testing process. times per testing process.

View File

@ -247,7 +247,8 @@ class Config(object):
basetemp = None basetemp = None
def __init__(self, pluginmanager=None): def __init__(self, pluginmanager=None):
#: command line option values #: command line option values, usually added via parser.addoption(...)
#: or parser.getgroup(...).addoption(...) calls
self.option = CmdOptions() self.option = CmdOptions()
self._parser = Parser( self._parser = Parser(
usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]", usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]",
@ -404,7 +405,7 @@ class Config(object):
return self._getconftest(name, path, check=False) return self._getconftest(name, path, check=False)
def getvalueorskip(self, name, path=None): def getvalueorskip(self, name, path=None):
""" return getvalue(name) or call py.test.skip if no value exists. """ """ (deprecated) return getvalue(name) or call py.test.skip if no value exists. """
try: try:
val = self.getvalue(name, path) val = self.getvalue(name, path)
if val is None: if val is None: