Writing Python tests

Guidelines on how to write tests for our Python code
Warning

🚧 This section is still in active development and is subject to changes 🚧

What to write tests for

Write tests for:

  • Every function, class, and method.
  • Every possible input and output.
  • Every possible error within the function.

How to write tests

Test location

We use pytest for testing our Python code and keep the tests outside the application code in a tests directory, like so:

sprout/
β”œβ”€β”€ core/
β”‚   β”œβ”€β”€ my_function.py
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_my_function.py

Test files

Make one test file per Python script and only test the functions within that script. This makes it easier to do a cycle of writing and testing, since you only need to run the one test file and not all the tests.

Always name the test file the same as the Python script, but with test_ as a prefix. E.g., my_function.py –> test_my_function.py.

Test names

Use the following general pattern for naming tests:

  • test_<action>_<condition>. E.g., test_returns_relative_path_with_multi_digits or test_rejects_unsupported_format.
  • If there are multiple functions in the same script, you can include the function name in the test name: test_<function>_<action>_<condition>.

Test structure

Use the following general structure for tests:

  1. Given: Set up the test data and any other necessary conditions.
  2. When: Call the function or method being tested.
  3. Then: Check the output of the function or method.

This is sometimes called β€œArrange, act, assert”.

If tests are short and very simple, you don’t have to use these sections explicitly. But as tests get longer and more complex, it can be helpful - for reviewers and your future self - to include them.

Keep the tests as simple as possible and only test one thing at a time. If you need to test multiple things, write multiple tests.

To avoid repeating yourself, use parameterized tests to test multiple inputs and outputs with the same test function.