Skip to content

Installing/Running pytest

pytest is a framework for testing Python programs. This page explains how to install and run pytest, and how to write test modules.

Installing pytest

Complete the following steps in Thonny:

  1. Type the following command in the shell:
    !pip install pytest-cov
    
  2. Go to Tools > Options…
    • Make sure you have FORCE_COLOR=1 under environment variables (see instructions).
    • If needed, close and restart Thonny for the changes to take effect.

Example code

As a reminder, you should create a new folder for each assignment. Tools like ruff and pytest analyze every file under the current folder. If you don't organize your files into folders, the tools are harder to use.

Create a new folder named geometry under your CS149 folder. Download the following files into your geometry folder. (Right click each link, and "Save link as…")

Running pytest

In Thonny, open triangles.py and test_triangles.py (in the geometry folder you created). Run the triangles.py program. You should see the following output:

valid((3, 4, 5)): True
area((3, 4, 5)): 6.0
classify((3, 4, 5)): Scalene

Note

Running a program puts Thonny's shell in the same folder as the program. You need to be in the correct folder for pytest (and ruff) to find your program.

To run pytest, type the following command in Thonny's shell:

!pytest

This command runs every module in the current folder beginning with the word test_. Within each module, every function beginning with the word test_ is called. If any assertions fail, a detailed error message is displayed.

Exercise 1

The example code currently passes all tests. To see what failing a test looks like, introduce a bug in triangles.py. For example, edit line 46 to say 0.0 * (a + b + c) instead of 0.5. Then run the pytest command again in the shell.

approx() function

Because floating-point arithmetic is imprecise, comparison with == can be unreliable. For example, 0.1 + 0.2 == 0.3 is False, because 0.1 + 0.2 is 0.30000000000000004.

Pytest includes a function named approx() that checks if the expected value is within a small difference of the other value. So, 0.1 + 0.2 == approx(0.3) is True.

Notice that test_area() uses approx(), because the area() function returns a float.

Exercise 2

Run the following lines, one at a time, in the shell:

0.1 + 0.2
0.1 + 0.2 == 0.3
from pytest import approx
approx(0.3)
0.1 + 0.2 == approx(0.3)

Keyboard shortcuts

In Thonny, use the keyboard shortcut Alt+S to switch to the shell. And use the keyboard shortcut Alt+E to switch back to the editor. Then you won't have to reach for the mouse every time you want to run pytest.

Also, press the Up and Down buttons in the shell to recall previous commands. Then you won't have to retype the same command over and over while testing.

Note for Mac users (click to expand)

The keyboard shortcuts are different on macOS. Press Cmd+Option+S for the shell and Cmd+Option+E for the editor.

These shortcuts might not work in the current version of macOS. However, you can define your own shortcuts by following these steps:

  1. From the Thonny "Tools" menu, select "Open Thonny data folder…"
  2. Close Thonny (otherwise your changes will be overwritten when Thonny is closed).
  3. Open (double click) the configuration.ini file in the data folder.
  4. Add the following lines to the end of the file:
    [shortcuts]
    focus_shell = <Control-s>
    focus_editor = <Control-e>
    
  5. Save configuration.ini, and reopen Thonny.
  6. Use Ctrl+S for the shell and Ctrl+E for the editor.

For more information, see Custom shortcuts on Thonny's Wiki.

Exercise 3

Practice using each of the keyboard shortcuts described above.

Optional arguments

pytest works the same way as ruff. If you run pytest without any arguments, all test modules will be run. Alternatively, you can run a specific test module as follows:

!pytest test_triangles.py

In addition, you can run a specific test function using the -k option.

!pytest -k test_area

Finally, the -q (quiet) option can be used to make the output less verbose.

!pytest -q

Multiple options can be combined.

!pytest -q -k test_area

Exercise 4

Run each command listed above and see how the output changes. And if you haven't already, fix the bug you added on line 46 of triangles.py (change the 0.0 back to 0.5).

Unit Testing

Test functions use Python's assert statement.

  • Ex: assert a % 2 == 0, "value was odd, should be even"
  • The error message after the comma is optional, but helpful.

Follow this pattern when testing your own programs:

  • For every module m, create a module named test_m.
  • For every function f, write a function named test_f.
  • Write enough assert statements to test every branch.

Exercise 5

The provided test functions are incomplete. There are many possible errors that these tests wouldn't catch. Add more assert statements to each function in test_trianges.py. Each assert should have different triangle values and expected results. Try to test every possible branch (return value) of each function. Submit your test_trianges.py to Gradescope.

Going further

See pytest's documentation and API Reference for additional details.