Catego Tags: python, testing, pytest Status: draft
About pytest
From pytest.org:
- a mature full-featured Python testing tool
- provides easy no-boilerplate testing
- scales from simple unit to complex functional testing
- integrated with other testing methods and tools
- extensive plugin and customization system
Installing pytest
If you have already created your virtualenv
, download the latest pytest package and run pip install pytest-[version].tar.gz
.
Writing your tests
Basic example
This is the most basic example, adapted from the Python Guide:
# content of test_sample.py
def func(x):
return x + 1
def test_func():
assert func(3) == 5
You only need to prefix your test function with test_
so that Pytest can find it. A good practice is to use the name of the function you are testing after the prefix.
Mocking modules and environments
From Pytest:
Sometimes tests need to invoke functionality which depends on global settings or which invokes code which cannot be easily tested such as network access. The monkeypatch function argument helps you to safely set/delete an attribute, dictionary item or environment variable or to modify sys.path for importing.
Monkeypatch is a module that helps you set the return values for other functions that your function depends on.
If you want to pretend that os.expanduser returns a certain directory, you can use the monkeypatch.setattr() method to patch this function before calling into a function which uses it:
# content of test_module.py
import os.path
def getssh(): # pseudo application code
return os.path.join(os.path.expanduser("~admin"), '.ssh')
def test_mytest(monkeypatch):
def mockreturn(path):
return '/abc'
monkeypatch.setattr(os.path, 'expanduser', mockreturn)
x = getssh()
assert x == '/abc/.ssh'
Mock
Another useful module is Mock, which now comes with Unittest for Python 3.3 onward.
Let's mock a class, for example:
my_mock = Mock()
my_mock.some_attribute = 5
my_mock.some_method = Mock()
my_mock.some_method.return_value = 10
Now, my_mock.some_method()
will return 10. Similarly, my_mock.some_attribute
will return 3.
Running your tests
To run your tests, you only need run the command from your tests
directory.
py.test -v
Note: Remember to install the package you want to test beforehand with python setup.py install
.
Test discovery
Pytest has a 'discovery' feature to automatically find your tests within your code. This is how it works by default:
- collection starts from the 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 theirpackage name
.Test
prefixed test classes (without an__init__
method)test_
prefixed test functions or methods are test items
Note: If you run them from your package directory, and you have your virtualenv
directory in there, then pytest
will find the tests for the packages installed and run them.
Verifying test coverage
Pytest has a plugin called pytest-cov for coverage reporting of your tests. You can install this package using pip
.
For verifying centralized testing coverage in EC, we would run the following:
py.test --cov package-path/ tests-path/
Note: Pytest-cov depends on cov-core and on coverage.