4 Lessor-Known Yet Awesome Tips for Pytest | by Khuyen Tran | Nov, 2020


Master Unit Testing in Python with These 4 Tips

Photo by Gayatri Malhotra on Unsplash

As a data scientist, it is important to make sure your functions work as expected. A good practice is to write a small function then test your function with unit testing.

Rather than trying to debug a big chunk of code, it is better to break your code down into smaller pieces and make sure the smaller pieces work.

Pytest is the ideal framework that makes it easy to write small tests in Python. I covered the benefits of unit testing and how to get started with pytest here. In the last article, I have shown how to:

  • Test one function with multiple tests
  • Combine multiple tests into one test function
  • Test one function at a time
  • Test different functions using the same data
  • Structure your projects

In this article, I will show you how to:

  • Filter warnings
  • Print the output of the function being tested
  • Benchmark your code
  • Repeat a single test for a specific number of times

Let’s get started!

It is common to see deprecation warnings when running pytest. The warnings might not be necessary and appear annoying when we just want to debug our code. Luckily, we can filter pytest warnings.

I will borrow the examples from my previous pytest article. In this example, I want to test whether TextBlob accurately predicts the sentiment of a text. If you don’t know about TextBlob, you can learn more about the tool here.

When we test this script using

pytest test_example.py

we will see warnings.

In order to filter the warnings, create a file called pytest.ini in the same directory that we run our script

├── pytest.ini
└── test_example.py

Then insert the content below inside the pytest.ini

[pytest]addopts = -p no:warnings

That’s it! Now rerun our test. We will have a clean output without the warnings!

Sometimes we might want to see the intermediate output before writing assert statement. Why not print the output to know the intermediate output?

This will also help us develop a function that produces the output we want.

For example, we can print text.sentiment to know what exactly text.sentiment does

When running pytest test_example.py, we will see no output. In order to see the output of theprint function, we need to include -s at the end of our command

>>> pytest test_example.py -s====================== test session starts ======================
test_examply.py Sentiment(polarity=0.8, subjectivity=0.75)
======================= 1 passed in 0.49s =======================

Awesome! Now we know we can use text.sentiment.polarityto get the polarity of the sentiment.

Sometimes we might want to run one test 100 times to make sure the function always works as expected.

For example, we discovered the method to combine 2 Python lists

>>> l1 = [1,2,3]
>>> l2 = [4,5,6]
>>> l1.extend(l2)
>>> l1

From the output, it seems like the values in the list l2 are inserted after the values in the list l1. But is the order always that way with every pair of lists?

To make sure the order of insertion is preserved when using the functionextend, we can create two random lists then test it 100 times. If all tests pass, we are certain that the function will always work as we expected

To repeat a single test, install pytest-repeat

pip install pytest-repeat

Now use pytest.mark.repeat(100) as the decorator of the test function we want to repeat

>>> pytest test_repeat.py 
====================== test session starts ========================
test_repeat.py ........... [100%]======================= 101 passed in 0.09s =======================

Awesome. Now we are certain that the order of insertion will always be preserved when using extend() since 101 tests passed.

If you want to be more certain, increase the number to 1000 and see what you get. You can find more about pytest-repeat here.

We might not only want to assert the outputs are what we expected, but we also want to compare the speed of different functions.

A benchmark is a test that we can use to measure how fast our code is.

Luckily, there is a library called pytest-benchmark that allows us to benchmark our code while testing our function with pytest!

Install pytest-benchmark with

pip install pytest-benchmark

I will borrow the examples from my article on timing for efficient Python code to show how we can use pytest-benchmark.

Here we test how long it takes to create a list using concat method

The mean time of running concat is 792.1252 microseconds. We can see other measurements such as the min time and max time!

We can also insert parameters for the test function and repeat the tests 100 times to get a more accurate estimation of how fast the code is executed.

We get a different mean of 730 microseconds.

Now let’s use pytest-benchmark to compare multiple methods to create a list ranging from 0 to 999.


Source link

Write a comment