Pythons: Python 2.4-3.2, Jython, PyPy
Platforms: Unix/Posix and Windows
PyPI package name: pytest
documentation as PDF: download latest
Installation options:
pip install -U pytest # or
easy_install -U pytest
To check your installation has installed the correct version:
$ py.test --version
This is py.test version 2.1.3, imported from /Users/hpk/p/pytest/pytest.pyc
setuptools registered plugins:
pytest-cov-1.4 at /Users/hpk/venv/0/lib/python2.7/site-packages/pytest_cov.pyc
pytest-xdist-1.6 at /Users/hpk/venv/0/lib/python2.7/site-packages/xdist/plugin.pyc
If you get an error checkout Known Installation issues.
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 darwin -- Python 2.7.1 -- pytest-2.1.3
collecting ... collected 1 items
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.
Note
You can simply use the assert statement for asserting test expectations. pytest’s Advanced assertion introspection will intelligently report intermediate values of the assert expression freeing you from the need to learn the many names of JUnit legacy methods.
If you want to assert that 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
collecting ... collected 1 items
.
1 passed in 0.01 seconds
Once you start to have more than a few tests it often makes sense to group tests logically, in classes and modules. Let’s write a class containing two tests:
# 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
collecting ... collected 2 items
.F
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass instance at 0x1013167a0>
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.03 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.
For functional tests one often needs to create some files and pass them to application objects. py.test provides the versatile Dependency injection through function arguments 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
collecting ... collected 1 items
F
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmpdir = local('/Users/hpk/tmp/pytest-93/test_needsfiles0')
def test_needsfiles(tmpdir):
print tmpdir
> assert 0
E assert 0
test_tmpdir.py:3: AssertionError
----------------------------- Captured stdout ------------------------------
/Users/hpk/tmp/pytest-93/test_needsfiles0
1 failed in 0.04 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 Dependency injection through function arguments exist by typing:
py.test --funcargs # shows builtin and custom function arguments
Here are a few suggestions where to go next:
Install pip for a state of the art python package installer.
Or 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.
Usages and Examples for more complex examples