Table Of Contents

Previous topic

py.test Features

Next topic

Usage and Invocations

This Page

Installation and Getting Started

Compatibility: Python 2.4-3.2, Jython, PyPy on Unix/Posix and Windows

Installation

Installation options:

easy_install -U pytest  # or
pip install -U pytest

To check your installation has installed the correct version:

$ py.test --version
This is py.test version 2.0.0.dev30, imported from /home/hpk/p/pytest/pytest.py

If you get an error checkout Known Installation issues.

Our first test run

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

That’s it. You can execute the test function now:

$ py.test
=========================== test session starts ============================
platform linux2 -- Python 2.6.5 -- pytest-2.0.0.dev30
test path 1: /tmp/doc-exec-70

test_sample.py F

================================= FAILURES =================================
_______________________________ test_answer ________________________________

    def test_answer():
>       assert func(3) == 5
E       assert 4 == 5
E        +  where 4 = func(3)

test_sample.py:5: AssertionError
========================= 1 failed in 0.02 seconds =========================

py.test found the test_answer function by following standard test discovery rules, 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 standard traceback reporting.

Note

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

Asserting a certain exception is raised

If you want to assert some code raises an exception you can use the raises helper:

# content of test_sysexit.py
import pytest
def f():
    raise SystemExit(1)

def test_mytest():
    with pytest.raises(SystemExit):
        f()

Running it with, this time in “quiet” reporting mode:

$ py.test -q test_sysexit.py
.
1 passed in 0.00 seconds

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 are found because of the standard Conventions for Python 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 0x288fc20>

    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

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 Test function arguments and factories 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-122/test_needsfiles0')

    def test_needsfiles(tmpdir):
        print tmpdir
>       assert 0
E       assert 0

test_tmpdir.py:3: AssertionError
----------------------------- Captured stdout ------------------------------
/tmp/pytest-122/test_needsfiles0
1 failed in 0.05 seconds

Before the test runs, a unique-per-test-invocation temporary directory was created. More info at temporary directories and files.

You can find out what kind of builtin Test function arguments and factories 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:

Known Installation issues

easy_install or pip not found?

Consult distribute docs to install the easy_install tool on your machine. You may also use the older setuptools project but it lacks bug fixes and does not work on Python3. If you use Python2 you may also install pip.

py.test not found on Windows despite installation?

  • Windows: If “easy_install” or “py.test” are not found you need to add the Python script path to your PATH, see here: Python for Windows. You may alternatively use an ActivePython install which does this for you automatically.
  • 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.
Usages and Examples for more complex examples