[py-svn] pytest commit 567a0d7b8fa2: some more refinements to docs
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Sat Nov 6 09:57:00 CET 2010
# HG changeset patch -- Bitbucket.org
# Project pytest
# URL http://bitbucket.org/hpk42/pytest/overview
# User holger krekel <holger at merlinux.eu>
# Date 1288996645 -3600
# Node ID 567a0d7b8fa2be3820a64b6a4d5ecb326b383f7a
# Parent 9ff5086b4e67207b3caf98c5554269e1f126557d
some more refinements to docs
--- a/doc/examples.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-.. _examples:
-
-Usages and Examples
-===========================================
-
-.. toctree::
- :maxdepth: 2
-
- example/controlskip.txt
- example/mysetup.txt
- example/detectpytest.txt
- example/nonpython.txt
--- a/doc/example/test_collectonly.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-# run this with $ py.test --collectonly test_collectonly.py
-#
-def test_function():
- pass
-
-class TestClass:
- def test_method(self):
- pass
- def test_anothermethod(self):
- pass
--- /dev/null
+++ b/doc/example/simple.txt
@@ -0,0 +1,137 @@
+
+.. highlightlang:: python
+
+simple patterns using hooks
+==========================================================
+
+pass different values to a test function, depending on command line options
+----------------------------------------------------------------------------
+
+Suppose we want to write a test that depends on a command line option.
+Here is a basic pattern how to achieve this::
+
+ # content of test_sample.py
+ def test_answer(cmdopt):
+ if cmdopt == "type1":
+ print ("first")
+ elif cmdopt == "type2":
+ print ("second")
+ assert 0 # to see what was printed
+
+
+For this to work we need to add a command line option and
+provide the ``cmdopt`` through a function argument factory::
+
+ # content of conftest.py
+ def pytest_addoption(parser):
+ parser.addoption("--cmdopt", action="store", default="type1",
+ help="my option: type1 or type2")
+
+ def pytest_funcarg__cmdopt(request):
+ return request.config.option.cmdopt
+
+Let's run this without supplying our new command line option::
+
+ $ py.test -q
+ F
+ ================================= FAILURES =================================
+ _______________________________ test_answer ________________________________
+
+ cmdopt = 'type1'
+
+ def test_answer(cmdopt):
+ if cmdopt == "type1":
+ print ("first")
+ elif cmdopt == "type2":
+ print ("second")
+ > assert 0 # to see what was printed
+ E assert 0
+
+ test_sample.py:6: AssertionError
+ ----------------------------- Captured stdout ------------------------------
+ first
+ 1 failed in 0.02 seconds
+
+And now with supplying a command line option::
+
+ $ py.test -q --cmdopt=type2
+ F
+ ================================= FAILURES =================================
+ _______________________________ test_answer ________________________________
+
+ cmdopt = 'type2'
+
+ def test_answer(cmdopt):
+ if cmdopt == "type1":
+ print ("first")
+ elif cmdopt == "type2":
+ print ("second")
+ > assert 0 # to see what was printed
+ E assert 0
+
+ test_sample.py:6: AssertionError
+ ----------------------------- Captured stdout ------------------------------
+ second
+ 1 failed in 0.02 seconds
+
+Ok, this completes the basic pattern. However, one often rather
+wants to process command line options outside of the test and
+rather pass in different or more complex objects. See the
+next example or refer to :ref:`mysetup` for more information
+on real-life examples.
+
+generating parameters combinations, depending on command line
+----------------------------------------------------------------------------
+
+Let's say we want to execute a test with different parameters
+and the parameter range shall be determined by a command
+line argument. Let's first write a simple computation test::
+
+ # content of test_compute.py
+
+ def test_compute(param1):
+ assert param1 < 4
+
+Now we add a test configuration like this::
+
+ # content of conftest.py
+
+ def pytest_addoption(parser):
+ parser.addoption("--all", action="store_true",
+ help="run all combinations")
+
+ def pytest_generate_tests(metafunc):
+ if 'param1' in metafunc.funcargnames:
+ if metafunc.config.option.all:
+ end = 5
+ else:
+ end = 2
+ for i in range(end):
+ metafunc.addcall(funcargs={'param1': i})
+
+This means that we only run 2 tests if we do not pass ``--all``::
+
+ $ py.test -q test_compute.py
+ ..
+ 2 passed in 0.01 seconds
+
+We run only two computations, so we see two dots.
+let's run the full monty::
+
+ $ py.test -q --all test_compute.py
+ ....F
+ ================================= FAILURES =================================
+ _____________________________ test_compute[4] ______________________________
+
+ param1 = 4
+
+ def test_compute(param1):
+ > assert param1 < 4
+ E assert 4 < 4
+
+ test_compute.py:3: AssertionError
+ 1 failed, 4 passed in 0.03 seconds
+
+
+As expected when running the full range of ``param1`` values
+we'll get an error on the last one.
--- /dev/null
+++ b/doc/example/index.txt
@@ -0,0 +1,15 @@
+
+.. _examples:
+
+Usages and Examples
+===========================================
+
+.. toctree::
+ :maxdepth: 2
+
+ pythoncollection.txt
+ controlskip.txt
+ mysetup.txt
+ detectpytest.txt
+ nonpython.txt
+ simple.txt
--- /dev/null
+++ b/doc/example/pythoncollection.txt
@@ -0,0 +1,29 @@
+Changing standard (Python) test discovery
+===============================================
+
+changing directory recursion
+-----------------------------------------------------
+
+You can set the :confval:`norecursedirs` option in an ini-file, for example your ``setup.cfg`` in the project root directory::
+
+ # content of setup.cfg
+ [pytest]
+ norecursedirs = .svn _build tmp*
+
+This would tell py.test to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
+
+
+finding out what is collected
+-----------------------------------------------
+
+You can always peek at the collection tree without running tests like this::
+
+ $ py.test --collectonly collectonly.py
+ <Directory 'example'>
+ <Module 'test_collectonly.py'>
+ <Function 'test_function'>
+ <Class 'TestClass'>
+ <Instance '()'>
+ <Function 'test_method'>
+ <Function 'test_anothermethod'>
+
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -258,7 +258,7 @@ epub_copyright = u'2010, holger krekel e
# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'http://docs.python.org/': None}
+intersphinx_mapping = {} # 'http://docs.python.org/': None}
def setup(app):
#from sphinx.ext.autodoc import cut_lines
#app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
--- a/doc/funcargs.txt
+++ b/doc/funcargs.txt
@@ -4,6 +4,8 @@ creating and managing test function argu
.. currentmodule:: pytest.plugin.python
+
+.. _`funcargs`:
.. _`funcarg mechanism`:
Test function arguments and factories
@@ -34,18 +36,18 @@ Running the test looks like this::
=========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_simplefactory.py
-
+
test_simplefactory.py F
-
+
================================= FAILURES =================================
______________________________ test_function _______________________________
-
+
myfuncarg = 42
-
+
def test_function(myfuncarg):
> assert myfuncarg == 17
E assert 42 == 17
-
+
test_simplefactory.py:5: AssertionError
========================= 1 failed in 0.02 seconds =========================
@@ -118,7 +120,8 @@ example:
Basic generated test example
----------------------------
-Let's consider this test module::
+Let's consider a test module which uses the ``pytest_generate_tests``
+hook to generate several calls to the same test function::
# content of test_example.py
def pytest_generate_tests(metafunc):
@@ -135,23 +138,24 @@ Running this::
=========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
test path 1: test_example.py
-
+
test_example.py .........F
-
+
================================= FAILURES =================================
_______________________________ 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.03 seconds ====================
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 which is separate from the actual test running.
+Let's just look at what is collected::
$ py.test --collectonly test_example.py
<Directory 'doc-exec-167'>
@@ -173,7 +177,7 @@ If you want to select only the run with
=========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 -- /home/hpk/venv/0/bin/python
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
@@ -184,16 +188,16 @@ If you want to select only the run with
test_example.py:6: test_func[7] PASSED
test_example.py:6: test_func[8] PASSED
test_example.py:6: test_func[9] FAILED
-
+
================================= FAILURES =================================
_______________________________ 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 ====================
--- a/doc/customize.txt
+++ b/doc/customize.txt
@@ -35,13 +35,13 @@ If no path was provided at all the curre
builtin configuration file options
----------------------------------------------
-.. confval:: minversion = VERSTRING
+.. confval:: minversion
- specifies the minimal pytest version that is needed for this test suite.
+ specifies a minimal pytest version needed for running tests.
minversion = 2.1 # will fail if we run with pytest-2.0
-.. confval:: addopts = OPTS
+.. confval:: addopts
add the specified ``OPTS`` to the set of command line arguments as if they
had been specified by the user. Example: if you have this ini file content::
@@ -53,5 +53,28 @@ builtin configuration file options
py.test --maxfail=2 -rf test_hello.py
-.. _`function arguments`: funcargs.html
+ Default is to add no options.
+.. confval:: norecursedirs
+
+ Set the directory basename patterns to avoid when recursing
+ for test discovery. The individual (fnmatch-style) patterns are
+ applied to the basename of a directory to decide if to recurse into it.
+ Pattern matching characters::
+
+ * matches everything
+ ? matches any single character
+ [seq] matches any character in seq
+ [!seq] matches any char not in seq
+
+ Default patterns are ``.* _* CVS {args}``. Setting a ``norecurse``
+ replaces the default. Here is a customizing example for avoiding
+ a different set of directories::
+
+ # content of setup.cfg
+ [pytest]
+ norecursedirs = .svn _build tmp*
+
+ This would tell py.test to not recurse into typical subversion or
+ sphinx-build directories or into any ``tmp`` prefixed directory.
+
--- a/doc/getting-started.txt
+++ b/doc/getting-started.txt
@@ -1,8 +1,6 @@
Installation and Getting Started
===================================
-.. _`easy_install`:
-
**Compatibility**: Python 2.4-3.2, Jython, PyPy on Unix/Posix and Windows
Installation
@@ -17,27 +15,26 @@ To check your installation has installed
$ py.test --version
-If you get an error, checkout :ref:`installation issues`.
-
+If you get an error checkout :ref:`installation issues`.
Our first test run
----------------------------------------------------------
-Let's create a small file with a test function testing a function
-computes a certain value::
+Let's create a first test file with a simple test function::
# content of test_sample.py
def func(x):
return x + 1
+
def test_answer():
assert func(3) == 5
-You can execute the test function::
+That's it. You can execute the test function now::
- $ py.test test_sample.py
+ $ py.test
=========================== test session starts ============================
- platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17
- test path 1: test_sample.py
+ platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev18
+ test path 1: /tmp/doc-exec-211
test_sample.py F
@@ -49,19 +46,26 @@ You can execute the test function::
E assert 4 == 5
E + where 4 = func(3)
- test_sample.py:4: AssertionError
+ test_sample.py:5: AssertionError
========================= 1 failed in 0.02 seconds =========================
-We told py.test to run the ``test_sample.py`` file and it :ref:`discovered` the
-``test_answer`` function because of the ``test_`` prefix. We got a
-failure because our little ``func(3)`` call did not return ``5``.
+py.test found the ``test_answer`` function by following :ref:`standard test discovery rules <test discovery>`, basically detecting the ``test_`` prefixes. We got a failure report because our little ``func(3)`` call did not return ``5``. The report is formatted using the :ref:`standard traceback reporting`.
.. note::
- You can simply use the `assert statement`_ for coding expectations because
- 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.
+ You can simply use the ``assert`` statement for coding expectations because
+ intermediate values will be presented to you. This is much easier than
+ learning all the `the JUnit legacy methods`_ which are even inconsistent
+ with Python's own coding guidelines (but consistent with
+ Java-style naming).
+
+ There is only one seldomly hit caveat to using asserts: if your
+ assertion expression fails and has side effects then re-evaluating
+ it for presenting intermediate values can go wrong. It's easy to fix:
+ compute the value ahead of the assert and then do the
+ assertion or use the assert "message" syntax::
+
+ assert expr, "message" # show "message" if expr is not True
.. _`the JUnit legacy methods`: http://docs.python.org/library/unittest.html#test-cases
@@ -88,7 +92,7 @@ Running it with, this time in "quiet" re
.
1 passed in 0.01 seconds
-.. todo:: For further ways to assert exceptions see the :pyfunc:`raises`
+.. todo:: For further ways to assert exceptions see the `raises`
Grouping multiple tests in a class
--------------------------------------------------------------
@@ -107,16 +111,16 @@ tests in a class like this::
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::
+The two tests are found because of the standard :ref:`test discovery`.
+There is no need to subclass anything. We can simply
+run the module by passing its filename::
$ py.test -q test_class.py
.F
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
- self = <test_class.TestClass instance at 0x1732368>
+ self = <test_class.TestClass instance at 0x19c6638>
def test_two(self):
x = "hello"
@@ -126,27 +130,74 @@ the module we'll see one passed and one
test_class.py:8: AssertionError
1 failed, 1 passed in 0.02 seconds
-where to go from here
+The first test passed, the second failed. Again we can easily see
+the intermediate values used in the assertion, helping us to
+understand the reason for the failure.
+
+Going functional: requesting a unique temporary directory
+--------------------------------------------------------------
+
+For functional tests one often needs to create some files
+and pass them to application objects. py.test provides
+the versatile :ref:`funcarg mechanism` which allows to request
+arbitrary resources, for example a unique temporary directory::
+
+ # content of test_tmpdir.py
+ def test_needsfiles(tmpdir):
+ print tmpdir
+ assert 0
+
+We list the name ``tmpdir`` in the test function signature and
+py.test will lookup and call a factory to create the resource
+before performing the test function call. Let's just run it::
+
+ $ py.test -q test_tmpdir.py
+ F
+ ================================= FAILURES =================================
+ _____________________________ test_needsfiles ______________________________
+
+ tmpdir = local('/tmp/pytest-1306/test_needsfiles0')
+
+ def test_needsfiles(tmpdir):
+ print tmpdir
+ > assert 0
+ E assert 0
+
+ test_tmpdir.py:3: AssertionError
+ ----------------------------- Captured stdout ------------------------------
+ /tmp/pytest-1306/test_needsfiles0
+ 1 failed in 0.04 seconds
+
+Before the test runs, a unique-per-test-invocation temporary directory
+was created. More info at :ref:`tmpdir handling`.
+
+You can find out what kind of builtin :ref:`funcargs` exist by typing::
+
+ py.test --funcargs # shows builtin and custom function arguments
+
+where to go next
-------------------------------------
Here are a few suggestions where to go next:
* :ref:`cmdline` for command line invocation examples
* :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 using py.test
+* :ref:`plugins` managing and writing plugins
.. _`installation issues`:
-Installation issues
+Known 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.
+Consult `distribute docs <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.
--- a/doc/tmpdir.txt
+++ b/doc/tmpdir.txt
@@ -1,3 +1,5 @@
+
+.. _`tmpdir handling`:
temporary directories and files
================================================
@@ -18,7 +20,7 @@ and more. Here is an example test usage
p = tmpdir.mkdir("sub").join("hello.txt")
p.write("content")
assert p.read() == "content"
- assert len(os.listdir(str(tmpdir))) == 1
+ assert tmpdir.listdir() == 1
assert 0
Running this would result in a passed test except for the last
@@ -41,8 +43,6 @@ Running this would result in a passed te
p.write("content")
assert p.read() == "content"
assert len(os.listdir(str(tmpdir))) == 1
- > assert 0
- E assert 0
test_tmpdir.py:7: AssertionError
========================= 1 failed in 0.04 seconds =========================
--- a/doc/unittest.txt
+++ b/doc/unittest.txt
@@ -1,3 +1,6 @@
+
+.. _`unittest.TestCase`:
+
unittest.TestCase support
=====================================================================
--- /dev/null
+++ b/doc/extracol
@@ -0,0 +1,32 @@
+changing Python test discovery patterns
+--------------------------------------------------
+
+You can influence python test file, function and class prefixes through
+the :confval:`python_patterns` configuration valueto determine which
+files are checked and which test functions are found. Example for using
+a scheme that builds on ``check`` rather than on ``test`` prefixes::
+
+
+ # content of setup.cfg
+ [pytest]
+ python_patterns =
+ files: check_*.py
+ functions: check_
+ classes: Check
+
+See
+ :confval:`python_funcprefixes` and :confval:`python_classprefixes`
+
+
+ changing test file discovery
+ -----------------------------------------------------
+
+ You can specify patterns where python tests are found::
+
+ python_testfilepatterns =
+ testing/**/{purebasename}.py
+ testing/*.py
+
+ .. note::
+
+ conftest.py files are never considered for test discovery
--- a/doc/example/nonpython/conftest.py
+++ b/doc/example/nonpython/conftest.py
@@ -11,22 +11,22 @@ class YamlFile(py.test.collect.File):
import yaml # we need a yaml parser, e.g. PyYAML
raw = yaml.load(self.fspath.open())
for name, spec in raw.items():
- yield UsecaseItem(name, self, spec)
+ yield YamlItem(name, self, spec)
-class UsecaseItem(py.test.collect.Item):
+class YamlItem(py.test.collect.Item):
def __init__(self, name, parent, spec):
- super(UsecaseItem, self).__init__(name, parent)
+ super(YamlItem, self).__init__(name, parent)
self.spec = spec
def runtest(self):
for name, value in self.spec.items():
# some custom test execution (dumb example follows)
if name != value:
- raise UsecaseException(self, name, value)
+ raise YamlException(self, name, value)
def repr_failure(self, excinfo):
""" called when self.runtest() raises an exception. """
- if excinfo.errisinstance(UsecaseException):
+ if isinstance(excinfo.value, YamlException):
return "\n".join([
"usecase execution failed",
" spec failed: %r: %r" % excinfo.value.args[1:3],
@@ -36,5 +36,5 @@ class UsecaseItem(py.test.collect.Item):
def reportinfo(self):
return self.fspath, 0, "usecase: %s" % self.name
-class UsecaseException(Exception):
+class YamlException(Exception):
""" custom exception for error reporting. """
--- a/doc/goodpractises.txt
+++ b/doc/goodpractises.txt
@@ -5,7 +5,7 @@
Good Integration Practises
=================================================
-work with virtual environments
+Work with virtual environments
-----------------------------------------------------------
We recommend to work with virtualenv_ environments and use easy_install_
@@ -21,6 +21,24 @@ server Hudson_.
.. _`buildout`: http://www.buildout.org/
.. _pip: http://pypi.python.org/pypi/pip
+.. _`test discovery`:
+
+Conventions for Python test discovery
+-------------------------------------------------
+
+``py.test`` implements the following standard test discovery:
+
+* collection starts from initial command line arguments
+ which may be directories, filenames or test ids.
+* recurse into directories, unless they match :confval:`norecursedirs`
+* ``test_*.py`` or ``*_test.py`` files, imported by their `package name`_.
+* ``Test`` prefixed test classes (without an ``__init__`` method)
+* ``test_`` prefixed test functions or methods are test items
+
+For changing and customization example, see :doc:`example/pythoncollection`.
+
+py.test additionally discovers tests using the standard
+:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
Choosing a test layout / import rules
------------------------------------------
@@ -57,6 +75,8 @@ You can always run your tests by pointin
py.test # run all tests below current dir
...
+.. _`package name`:
+
.. note::
Test modules are imported under their fully qualified name as follows:
--- a/doc/example/nonpython.txt
+++ b/doc/example/nonpython.txt
@@ -4,6 +4,8 @@
Working with non-python tests
====================================================
+.. _`yaml plugin`:
+
a basic example for specifying tests in Yaml files
--------------------------------------------------------------
@@ -39,7 +41,17 @@ now execute the test specification::
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
-interesting interpretation of the yaml-values. Note that ``reportinfo()``
+interesting interpretation of the yaml-values. You can easily write
+your own domain specific testing language this way.
+
+.. note::
+
+ ``repr_failure(excinfo)`` is called for representing test failures.
+ If you create custom collection nodes you can return an error
+ representation string of your choice. It
+ will be reported as a (red) string.
+
+ ``reportinfo()``
is used for representing the test location and is also consulted for
reporting in ``verbose`` mode::
--- a/doc/index.txt
+++ b/doc/index.txt
@@ -12,7 +12,7 @@ Welcome to ``py.test`` documentation:
overview
apiref
plugins
- examples
+ example/index
talks
develop
--- a/doc/plugins.txt
+++ b/doc/plugins.txt
@@ -3,7 +3,7 @@ Writing, managing and understanding plug
.. _`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::
+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`_
@@ -55,7 +55,7 @@ earlier than further away ones.
.. _`installing plugins`:
.. _`external plugins`:
-Installing External Plugins
+Installing External Plugins / Searching
------------------------------------------------------
Installing a plugin happens through any usual Python installation
@@ -72,9 +72,7 @@ de-install it. You can find a list of v
.. _`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
+Writing a plugin by looking at examples
------------------------------------------------------
.. _`Distribute`: http://pypi.python.org/pypi/distribute
@@ -83,9 +81,18 @@ Writing an installable plugin
If you want to write a plugin, there are many real-life examples
you can copy from:
+* a custom collection example plugin: :ref:`yaml plugin`
* around 20 `builtin plugins`_ which comprise py.test's own functionality
* around 10 `external plugins`_ providing additional features
+All of these plugins are using the documented `well specified hooks`_
+to implement their wide-ranging functionality.
+
+.. _`setuptools entry points`:
+
+Making your plugin installable by others
+-----------------------------------------------
+
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
@@ -149,9 +156,6 @@ will be loaded as well. You can also us
which will import the specified module as a py.test plugin.
-.. _`setuptools entry points`:
-.. _registered:
-
Accessing another plugin by name
--------------------------------------------
--- /dev/null
+++ b/doc/example/collectonly.py
@@ -0,0 +1,11 @@
+
+# run this with $ py.test --collectonly test_collectonly.py
+#
+def test_function():
+ pass
+
+class TestClass:
+ def test_method(self):
+ pass
+ def test_anothermethod(self):
+ pass
--- a/doc/discovery.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-
-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.
More information about the pytest-commit
mailing list