diff --git a/distribute_setup.py b/distribute_setup.py index 37117b34e..3ea2e667f 100644 --- a/distribute_setup.py +++ b/distribute_setup.py @@ -46,7 +46,7 @@ except ImportError: args = [quote(arg) for arg in args] 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/" SETUPTOOLS_FAKED_VERSION = "0.6c11" diff --git a/doc/Makefile b/doc/Makefile index 16febb959..bd23b53df 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -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 +regen: + COLUMNS=76 regendoc --update *.txt */*.txt + help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" diff --git a/doc/apiref.txt b/doc/apiref.txt index da177c70c..ab3019ec8 100644 --- a/doc/apiref.txt +++ b/doc/apiref.txt @@ -7,6 +7,7 @@ py.test reference documentation .. toctree:: :maxdepth: 2 + customize.txt assert.txt funcargs.txt xunit_setup.txt @@ -15,7 +16,7 @@ py.test reference documentation tmpdir.txt skipping.txt mark.txt - recwarn.txt - doctest.txt + recwarn.txt unittest.txt + doctest.txt diff --git a/doc/assert.txt b/doc/assert.txt index a293185a0..9729e34d4 100644 --- a/doc/assert.txt +++ b/doc/assert.txt @@ -1,5 +1,5 @@ -Writing easy assertions in tests +Writing and reporting of assertions in tests ============================================ assert with the ``assert`` statement @@ -21,7 +21,7 @@ assertion fails you will see the value of ``x``:: $ py.test test_assert1.py =========================== 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_assert1.py F @@ -101,7 +101,7 @@ if you run this module:: $ py.test test_assert2.py =========================== 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_assert2.py F diff --git a/doc/cmdline.txt b/doc/cmdline.txt index 3c33a0223..9a71b70d0 100644 --- a/doc/cmdline.txt +++ b/doc/cmdline.txt @@ -11,9 +11,7 @@ Getting help on version, option names, environment vars py.test --version # shows where pytest was imported from py.test --funcargs # show available builtin function arguments - py.test --help-config # show configuration values - - py.test -h | --help # show help + py.test -h | --help # show help on command line and config file options Stopping after the first (or N) failures diff --git a/doc/conf.py b/doc/conf.py index a6c82a057..4ba018c21 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -25,7 +25,8 @@ import sys, os # Add any Sphinx extension module names here, as strings. They can be extensions # 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. templates_path = ['_templates'] diff --git a/doc/contact.txt b/doc/contact.txt index 4bd2fa7dd..727fc0e45 100644 --- a/doc/contact.txt +++ b/doc/contact.txt @@ -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. - - `tetamap`_: Holger Krekel's blog, often about testing and py.test related news. - -- `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. +- `commit mailing list`_ - `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 @@ -28,20 +30,8 @@ Contact and Communication points .. _`@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 .. _FOAF: http://en.wikipedia.org/wiki/FOAF -.. _us: http://codespeak.net/mailman/listinfo/py-dev -.. _codespeak: http://codespeak.net/ .. _`py-dev`: .. _`development mailing list`: .. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev diff --git a/doc/customize.txt b/doc/customize.txt index fa70a0244..24472036b 100644 --- a/doc/customize.txt +++ b/doc/customize.txt @@ -1,7 +1,3 @@ -================================================ -Customizing and Extending py.test -================================================ - basic test configuration =================================== @@ -58,309 +54,4 @@ builtin configuration file options py.test --maxfail=2 -rf test_hello.py .. _`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 - - - - - - - - -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: - diff --git a/doc/discovery.txt b/doc/discovery.txt new file mode 100644 index 000000000..504319a8f --- /dev/null +++ b/doc/discovery.txt @@ -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 + + + + + + + + +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. diff --git a/doc/doctest.txt b/doc/doctest.txt index 63f8c45f0..434be0975 100644 --- a/doc/doctest.txt +++ b/doc/doctest.txt @@ -44,11 +44,7 @@ then you can just invoke ``py.test`` without command line options:: $ py.test =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 - test path 1: /tmp/doc-exec-288 + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 + test path 1: /tmp/doc-exec-197 - conftest.py . - example.rst . - mymodule.py . - - ========================= 3 passed in 0.01 seconds ========================= + ============================= in 0.00 seconds ============================= diff --git a/doc/example/controlskip.txt b/doc/example/controlskip.txt index 7eb358978..096bba765 100644 --- a/doc/example/controlskip.txt +++ b/doc/example/controlskip.txt @@ -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' =========================== 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_module.py .s ========================= 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 ==================== @@ -49,7 +49,7 @@ Or run it including the ``slow`` marked test:: $ py.test test_module.py --runslow =========================== 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_module.py .. diff --git a/doc/example/mysetup.txt b/doc/example/mysetup.txt index d98f2277e..507210471 100644 --- a/doc/example/mysetup.txt +++ b/doc/example/mysetup.txt @@ -49,7 +49,7 @@ You can now run the test:: $ py.test test_sample.py =========================== 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_sample.py F @@ -57,7 +57,7 @@ You can now run the test:: ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - mysetup = + mysetup = def test_answer(mysetup): app = mysetup.myapp() @@ -122,12 +122,12 @@ Running it yields:: $ py.test test_ssh.py -rs =========================== 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_ssh.py s ========================= 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 ========================= diff --git a/doc/example/nonpython.txt b/doc/example/nonpython.txt index 2e99904ac..ea9c2fa65 100644 --- a/doc/example/nonpython.txt +++ b/doc/example/nonpython.txt @@ -25,8 +25,8 @@ now execute the test specification:: nonpython $ py.test test_simple.yml =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev10 - test path 1: /home/hpk/p/pytest/doc/example/nonpython + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 + test path 1: test_simple.yml test_simple.yml .F @@ -35,7 +35,7 @@ now execute the test specification:: usecase execution failed spec failed: 'some': 'other' 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. 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 =========================== 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_simple.yml:1: usecase: ok PASSED @@ -56,7 +56,7 @@ reporting in ``verbose`` mode:: usecase execution failed spec failed: 'some': 'other' 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 interesting to just look at the collection tree:: diff --git a/doc/faq.txt b/doc/faq.txt index c77f19754..b868c6d59 100644 --- a/doc/faq.txt +++ b/doc/faq.txt @@ -1,87 +1,56 @@ -Frequent Issues and Questions +Some Issues and Questions ================================== -.. _`installation issues`: +.. note:: -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. + If you don't find an answer here, checkout the :ref:`contact channels` + to get help. 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 - -because of TAB-completion under Bash/Shells. If you hit -``py.`` you'll get a list of available development -tools that all share the ``py.`` prefix. Another motivation -was to unify the package ("py.test") and tool filename. - +Some historic, some practical reasons: ``py.test`` used to be part of +the ``py`` package which provided several developer utitilities, +all starting with ``py.``, providing nice TAB-completion. If +you install ``pip install pycmd`` you get these tools from a separate +package. These days the command line tool could be ``pytest`` +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``? +++++++++++++++++++++++++++++++++++++++++++++++++ py.test and nose_ share basic philosophy when it comes -to running Python tests. In fact, -with py.test-1.1.0 it is ever easier to run many test suites -that currently work with ``nosetests``. nose_ was created +to running Python tests. In fact, you can run many tests +written for unittest or nose with py.test. nose_ was originally created 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 -and py.test-1.1 have no counterpart in nose_. +cycle. .. _features: test/features.html -.. _apipkg: http://pypi.python.org/pypi/apipkg What's this "magic" with py.test? ++++++++++++++++++++++++++++++++++++++++++ -Around 2007 it was claimed that py.test was magic implementation -wise XXX. It has been refactored. +Around 2007 (version ``0.8``) some several people claimed that py.test +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 - to show intermediate values if a test fails. If your expression - 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). - ``py.test --no-assert`` turns off assert re-intepretation. - Sidenote: it is good practise to avoid asserts with side effects. +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 +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). +``py.test --no-assert`` turns off assert re-intepretation. +Sidenote: it is good practise to avoid asserts with side effects. .. _`py namespaces`: index.html .. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py @@ -92,10 +61,9 @@ function arguments, parametrized tests and setup .. _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 unittest-style test setup using `xUnit style setup`_ feels natural. For larger test suites, parametrized testing diff --git a/doc/features.txt b/doc/features.txt index 7828044c7..e8f4b6b20 100644 --- a/doc/features.txt +++ b/doc/features.txt @@ -4,9 +4,11 @@ py.test Features 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 -- use the ``assert`` statement for your assertions - rely on powerful traceback and assertion reporting - use ``print`` or ``pdb`` debugging on failures diff --git a/doc/funcargs.txt b/doc/funcargs.txt index 1cdeb4766..01d4b0f4a 100644 --- a/doc/funcargs.txt +++ b/doc/funcargs.txt @@ -32,7 +32,7 @@ Running the test looks like this:: $ py.test test_simplefactory.py =========================== 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_simplefactory.py F @@ -133,7 +133,7 @@ Running this:: $ py.test test_example.py =========================== 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_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:: $ py.test --collectonly test_example.py - + @@ -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] =========================== 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_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[8] PASSED + test_example.py:6: test_func[9] FAILED - ======================== 9 tests deselected by '7' ========================= - ================== 1 passed, 9 deselected in 0.01 seconds ================== - + ================================= 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 ==================== .. _`metafunc object`: diff --git a/doc/getting-started.txt b/doc/getting-started.txt index 1a2d6ba15..8f0a297e4 100644 --- a/doc/getting-started.txt +++ b/doc/getting-started.txt @@ -1,4 +1,4 @@ -Getting Started +Installation and Getting Started =================================== .. _`easy_install`: @@ -20,7 +20,7 @@ To check your installation has installed the correct version:: 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 @@ -32,17 +32,17 @@ computes a certain value:: def test_answer(): assert func(3) == 5 -Now you can execute the test function:: +You can execute the test function:: $ py.test test_sample.py - ========================= test session starts ========================== - platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev4 + =========================== test session starts ============================ + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 test path 1: test_sample.py test_sample.py F - =============================== FAILURES =============================== - _____________________________ test_answer ______________________________ + ================================= FAILURES ================================= + _______________________________ test_answer ________________________________ def test_answer(): > assert func(3) == 5 @@ -50,23 +50,27 @@ Now you can execute the test function:: E + where 4 = func(3) 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``. -A few notes on this little test invocation: +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``. -* ``test_answer`` was identified as a test function because of the - ``test_`` prefix, +.. note:: -* we conveniently used the standard `assert statement`_ and the failure - report shows us the intermediate values. + 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. + +.. _`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 -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:: # content of test_sysexit.py @@ -78,18 +82,49 @@ use the ``raises`` helper:: with py.test.raises(SystemExit): f() -Running it with:: +Running it with, this time in "quiet" reporting mode:: - $ py.test test_sysexit.py - ========================= test session starts ========================== - platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev4 - test path 1: test_sysexit.py - - test_sysexit.py . - - ======================= 1 passed in 0.01 seconds ======================= + $ py.test -q test_sysexit.py + . + 1 passed in 0.01 seconds -.. For further ways to assert exceptions see the :pyfunc:`raises` +.. todo:: For further ways to assert exceptions see the :pyfunc:`raises` + +Grouping multiple tests in a class +-------------------------------------------------------------- + +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 = + + 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 ------------------------------------- @@ -99,6 +134,47 @@ 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:`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 diff --git a/doc/goodpractises.txt b/doc/goodpractises.txt index 14ea561f2..86070d69e 100644 --- a/doc/goodpractises.txt +++ b/doc/goodpractises.txt @@ -2,51 +2,91 @@ .. highlightlang:: python .. _`good practises`: -Good Practises +Good Integration Practises ================================================= -Recommendation: install tool and dependencies virtually +work with virtual environments ----------------------------------------------------------- -We recommend to work with virtual environments -(e.g. virtualenv_ or buildout_ based) and use easy_install_ -(or pip_) for installing py.test/pylib and any dependencies -you need to run your tests. Local virtual Python environments -(as opposed to system-wide "global" environments) make for a more -reproducible and reliable test environment. +We recommend to work with virtualenv_ environments and use easy_install_ +(or pip_) for installing your application dependencies as well as +the ``pytest`` package itself. This way you get a much more reproducible +environment. A good tool to help you automate test runs against multiple +dependency configurations or Python interpreters is `tox`_, +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 .. _`buildout`: http://www.buildout.org/ .. _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: - - -Choosing a test layout ----------------------------- - -py.test supports common test layouts. - -XXX - .. _`genscript method`: Generating a py.test standalone Script ------------------------------------------- -If you are a maintainer or application developer and want users -to run tests you can use a facility to generate a standalone -"py.test" script that you can tell users to run:: +If you are a maintainer or application developer and want others +to easily run tests you can generate a completely standalone "py.test" +script:: py.test --genscript=runtests.py -will generate a ``mytest`` script that is, in fact, a ``py.test`` under -disguise. You can tell people to download and then e.g. run it like this:: +generates a ``runtests.py`` script which is a fully functional basic +``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 -and ask them to send you the resulting URL. The resulting script has -all core features and runs unchanged under Python2 and Python3 interpreters. +and ask them to send you the resulting URL. .. _`Distribute for installation`: http://pypi.python.org/pypi/distribute#installation-instructions .. _`distribute installation`: http://pypi.python.org/pypi/distribute diff --git a/doc/index.txt b/doc/index.txt index 63e64fb17..37834d8cd 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -1,5 +1,8 @@ py.test: no-boilerplate testing with Python ============================================== + +.. todolist:: + Welcome to ``py.test`` documentation: @@ -8,7 +11,7 @@ Welcome to ``py.test`` documentation: overview apiref - customize + plugins examples talks develop diff --git a/doc/links.inc b/doc/links.inc index 5cd550230..a2b5fbf89 100644 --- a/doc/links.inc +++ b/doc/links.inc @@ -16,3 +16,4 @@ .. _`pip`: http://pypi.python.org/pypi/pip .. _`virtualenv`: http://pypi.python.org/pypi/virtualenv .. _hudson: http://hudson-ci.org/ +.. _tox: http://codespeak.net/tox diff --git a/doc/mark.txt b/doc/mark.txt index ababe1488..04c41b212 100644 --- a/doc/mark.txt +++ b/doc/mark.txt @@ -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 =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 - test path 1: /tmp/doc-exec-11 + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 + test path 1: /tmp/doc-exec-171 test_mark.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 =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 - test path 1: /tmp/doc-exec-11 + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 + test path 1: /tmp/doc-exec-171 ===================== 4 tests deselected by '-webtest' ===================== ======================= 4 deselected in 0.01 seconds ======================= @@ -110,8 +110,8 @@ Or to only select the class:: $ py.test -kTestClass =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 - test path 1: /tmp/doc-exec-11 + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 + test path 1: /tmp/doc-exec-171 test_mark_classlevel.py .. diff --git a/doc/monkeypatch.txt b/doc/monkeypatch.txt index 43bfc43a0..632d6f66d 100644 --- a/doc/monkeypatch.txt +++ b/doc/monkeypatch.txt @@ -39,8 +39,8 @@ will be undone. .. background check: $ py.test =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0dev0 - test path 1: /tmp/doc-exec-296 + platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev17 + test path 1: /tmp/doc-exec-172 ============================= in 0.00 seconds ============================= diff --git a/doc/plugins.txt b/doc/plugins.txt new file mode 100644 index 000000000..7d786e2cc --- /dev/null +++ b/doc/plugins.txt @@ -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: + + diff --git a/doc/tmpdir.txt b/doc/tmpdir.txt index 8876a9fe2..3d428dd20 100644 --- a/doc/tmpdir.txt +++ b/doc/tmpdir.txt @@ -26,7 +26,7 @@ Running this would result in a passed test except for the last $ py.test test_tmpdir.py =========================== 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_tmpdir.py F @@ -34,7 +34,7 @@ Running this would result in a passed test except for the last ================================= FAILURES ================================= _____________________________ test_create_file _____________________________ - tmpdir = local('/tmp/pytest-427/test_create_file0') + tmpdir = local('/tmp/pytest-1248/test_create_file0') def test_create_file(tmpdir): 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 test_tmpdir.py:7: AssertionError - ========================= 1 failed in 0.03 seconds ========================= + ========================= 1 failed in 0.04 seconds ========================= .. _`base temporary directory`: diff --git a/doc/unittest.txt b/doc/unittest.txt index dc2a88aeb..25232ce9b 100644 --- a/doc/unittest.txt +++ b/doc/unittest.txt @@ -1,11 +1,11 @@ -unittest.py style testing integration +unittest.TestCase support ===================================================================== py.test has limited support for running Python `unittest.py style`_ tests. It will automatically collect ``unittest.TestCase`` subclasses and their ``test`` methods in test files. It will invoke ``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 @@ -21,7 +21,7 @@ Running it yields:: $ py.test test_unittest.py =========================== 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_unittest.py F @@ -55,7 +55,5 @@ Running it yields:: hello ========================= 1 failed in 0.02 seconds ========================= -This plugin is enabled by default. - .. _`unittest.py style`: http://docs.python.org/library/unittest.html diff --git a/doc/xunit_setup.txt b/doc/xunit_setup.txt index dd8ec5466..b7b17a4ab 100644 --- a/doc/xunit_setup.txt +++ b/doc/xunit_setup.txt @@ -54,13 +54,13 @@ Similarly, the following methods are called around each method invocation:: 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. + 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. + with a setup_method call. """ If you rather define test functions directly at module level @@ -68,12 +68,13 @@ you can also use the following functions to implement fixtures:: def setup_function(function): """ setup up any state tied to the execution of the given - function. Invoked for every test function in the module. + function. Invoked for every test function in the module. """ def teardown_method(function): """ 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 times per testing process. diff --git a/pytest/plugin/config.py b/pytest/plugin/config.py index 56308ad77..e85395926 100644 --- a/pytest/plugin/config.py +++ b/pytest/plugin/config.py @@ -247,7 +247,8 @@ class Config(object): basetemp = 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._parser = Parser( usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]", @@ -404,7 +405,7 @@ class Config(object): return self._getconftest(name, path, check=False) 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: val = self.getvalue(name, path) if val is None: