• 10 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 8/30/22

Go Further With Pytest

Debug Pytest

If you can’t work out why a test is failing, you’re going to need to debug the test. In this chapter, we’ll be looking at some tips to help you do this.

Let’s look at the subtraction method from the  Operators  class in the Calculator project: 

def subtraction(self, operation):
    self.operation = operation
    self.sign = "-"
    if self._is_operation_valid():
       self._calculate_subtraction()
       return self.result

And let’s check the scenario below:

def test_subtraction_operation():
    sut = Operators()
    operation = "5.5 + 10 - 10"
    expected_value = 5.6
    assert sut.subtraction(operation) == expected_value

After running the command to run the tests, I’ve noticed that the test has failed. If we want to get more details on the test, we can add some  print()  instructions. So, I’m going to remove the assertion and insert some  print()  instructions to get some more details on what the test is doing.

def test_subtraction_operation():
   sut = Operators()
   operation = "5.5 + 10 - 10"
   expected_value = 5.6
   sut.subtraction(operation)
   print(f"operation : {sut.operation}")
   print(f"sign : {sut.signe}")
   print(f"result : {sut.result}")
   print(f"expected value : {expected_value}")

But if you run the test again with the  pytest  command, nothing is displayed. You need to add a  -s  at the end so that the  print()  instructions will display on your terminal, like so:  pytest -s .

Use the pytest command with the -s option to see the print results.
Display the print results on the terminal

You can also run the following command to simply run the scenario  test_subtraction_operation :

pytest -s tests/test_operators.py::test_subtraction_operation

If you have a number of tests in your file or project, this method can be really useful when debugging.

The test_substraction_operation test can be run by running the pytest -s tests/test_operators.py::test_substraction_operation command.
Run one test at a time

Using the  print()  instructions that we added to the test, I now realize that I’m testing a subtraction operation, but the operation contains an addition operator.

So, we can now write:

def test_subtraction_operation():
    sut = Operators()
    operation = "5.5 - 10 - 10"
    expected_value = -14.5
    assert sut.subtraction(operation) == expected_value

This time, the test was successful!

Test Exceptions

Sometimes, you’ll need to check if an exception is raised correctly by the code. Fortunately, there’s a method that does just that! 

Let’s consider a function that divides two numbers that are passed in as arguments:

def division(numerator, denominator):
    return numerator / denominator

This code could raise an exception if it is being asked to divide by zero. This is why we’re not going to test that the code is supposed to fail, but that it will raise an exception in this specific case.

How do we do this?

By running a test with unexpected values and taking note of the exception raised. Pytest provides the raises(SomeException) method to specify that we expect the program to flag an error. 

If we want to use it, we first need to import the  pytest  module.

Add this to the top of your test file:

import pytest

Then we can write the following test:

def test_division():
    numerator = 2
    denominator = 0
    with pytest.raises(ZeroDivisionError):
        division(numerator, denominator)

Has the exception been correctly raised for you? Join me in the screencast below to find out more about testing exceptions.

Create Parametrized Tests

If you want to run a test with different datasets to check how the code behaves, look no further! You just need to use parametrized testing. Parametrized tests enable you to run the same scenario against multiple sets of sample data. This method means that you don’t need to duplicate your test to run it with different parameters.

Pytest provides a decorator that enables us to set up parametrized tests:  @pytest.mark.parametrize .

How do we use it?

  • Import the  pytest  module at the top of the test file.

  • Define the parameter names in a character string with comma separators and place this string as the first argument of the decorator.

  • Provide the various parameters in a list of tuples and use this as the second argument of the decorator.

  • Define your test by placing each parameter name as an argument of the function.

Now we can write our first parametrized test:

import pytest

@pytest.mark.parametrize("number, square", [(2, 4), (10, 100), (16, 256)])
def test_should_return_square(number, square):
    assert number ** 2 == square

Here’s a screencast showing a step-by-step guide to setting up this parametrized test:

Over to You!

Go back to the Calculator project and set up your first parametrized tests.

Find a suggested solution on the super-calculator project.

Let’s Recap!

  • Use the  -s  option when running the  pytest  command to display  print  instructions for your testing on the terminal: as follows  pytest -s .

  • To test an exception raised in the code, use the  raises()  function, provided by the  pytest  module. If the section of code within the  with  statement doesn’t raise an exception, the test will fail.

  • Parametrized tests enable you to run the same scenario using sample data. You can define your data sample using the  @pytest.mark.parametrize  decorator.

And that’s the end of part two, so now it’s time for the quiz! Your challenge is to get at least seven correct answers.

Example of certificate of achievement
Example of certificate of achievement