Table Of Contents

Previous topic

Usage and Invocations

Next topic

Some Issues and Questions

This Page

Good Integration Practises

Work with virtual environments

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.

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 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 Changing standard (Python) test discovery.

py.test additionally discovers tests using the standard unittest.TestCase subclassing technique.

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:

  • find basedir – this is the first “upward” directory not containing an __init__.py
  • perform sys.path.insert(0, basedir) to make the fully qualified test module path importable.
  • import path.to.test_module where the path is determined by converting path separators into ”.” files. This means you must follow the convention of having directory and file names map to the import names.

Generating a py.test standalone Script

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

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.

Integrating with distutils / python setup.py test

You can easily integrate test runs into your distutils or setuptools based project. Use the genscript method to generate a standalone py.test script:

py.test --genscript=runtests.py

and make this script part of your distribution and then add this to your setup.py file:

from distutils.core import setup, Command
# you can also import from setuptools

class PyTest(Command):
    user_options = []
    def initialize_options(self):
        pass
    def finalize_options(self):
        pass
    def run(self):
        import sys,subprocess
        errno = subprocess.call([sys.executable, 'runtest.py'])
        raise SystemExit(errno)
setup(
    #...,
    cmdclass = {'test': PyTest},
    #...,
)

If you now type:

python setup.py test

this will execute your tests using runtest.py. As this is a standalone version of py.test no prior installation whatsoever is required for calling the test command. You can also pass additional arguments to the subprocess-calls like your test directory or other options.