pytest is my tool of choice. There is also a standard library solution, which has too much API overhead for my taste and is by for not as convenient as pytest is. pytest does some very clever things to let you use the assertion statement directly and you get much better failure reports. It also has fixtures which makes it very easy to make test code very modular. This makes for much cleaner test code.
The sources of the test modules are here: tests/
The ability to write simple functions to test your code cannot be developed early enough, so why not start this right away as well? The examples are dead simple and not covering much yet, but show that it's not rocket science to write automatic tests for your code. Pytest makes it possible to use the inbuilt
assert for writing tests.
pytest (command line)¶
pytest looks for modules with the pattern
test_*.py downwards from your cwd. In those modules it looks for
def test_* and
class Test*. After collecting everything fitting those patterns it execute all test functions and reports back.
$ cd </path/to/your/clone> $ pytest
Example for a successful run:
========================== test session starts ========================== platform linux -- Python 3.4.3, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 rootdir: </path/to/your/clone>, inifile: tox.ini collected 13 items tests/test_pile.py ..... tests/test_player.py ... tests/test_sim.py ..... ======================= 13 passed in 0.03 seconds =======================
Example for a not so successful run:
======================= test session starts ============================= platform linux -- Python 3.4.4, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 rootdir: </path/to/your/clone>, inifile: tox.ini collected 35 items tests/test_concepts.py ................... tests/test_objects.py ..F.. tests/test_player.py ... tests/test_rules.py ... tests/test_sim.py ..... ======================== short test summary info ======================== FAIL tests/test_objects.py::test_non_empty_stock =============================== FAILURES ================================ _________________________ test_non_empty_stock __________________________ def test_non_empty_stock(): > assert not Stock() E assert not Stock() E + where Stock() = Stock() tests/test_objects.py:17: AssertionError ==================== 1 failed, 34 passed in 0.21 seconds ================
This test failed not because the code is broken, but because I made a wrong assertion about the behaviour of the
Stock class. If you pass a list when you create the class (like
Stock([Card('Queen', '♠'), Card('10', '♠')])), you should not expect it to be empty afterwards.
Automatically run tests on changes:¶
If you want to take this one step further and have the tests being run automatically every time the code changes, you can:
$ pip install pytest-watch $ cd </path/to/your/clone> $ ptw --onfail 'notify-send --urgency=critical "FAIL"' --onpass 'notify-send "PASSED"'
The default testrunner in PyCharm is Unittest. You have to switch to pytest like so:
Find Action: default testrunner: set to pytest
accept offer to install it in your project virtualenv or do it yourself with
pip install pytest
Depending on where you are, you can run all tests or a part of them. The magic action is
run context configuration. It runs what is sensible in the context. If your focus is in a normal script it runs the script and if the focus is in a module defining tests it will run the configured testrunner with the tests. Running the context configuration with ...
- Focus in the editor, inside a specific test
- Focus in the editor on the line defining a class containing tests
- Focus in the Project Tool Window, choose the
... all yields different results as which tests are run (and they are what you would intuitively expect).
For an example in the code see concepts.py