Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
pytest Quick Start Guide

You're reading from   pytest Quick Start Guide Write better Python code with simple and maintainable tests

Arrow left icon
Product type Paperback
Published in Aug 2018
Publisher Packt
ISBN-13 9781789347562
Length 160 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Bruno Oliveira Bruno Oliveira
Author Profile Icon Bruno Oliveira
Bruno Oliveira
Arrow right icon
View More author details
Toc

A quick look at the unittest module

Python comes with the built-in unittest module, which is a framework to write automated tests based on JUnit, a unit testing framework for Java. You create tests by subclassing from unittest.TestCase and defining methods that begin with test. Here's an example of a typical minimal test case using unittest:

    import unittest
from fibo import fibonacci

class Test(unittest.TestCase):

def test_fibo(self):
result = fibonacci(4)
self.assertEqual(result, 3)

if __name__ == '__main__':
unittest.main()

The focus of this example is on showcasing the test itself, not the code being tested, so we will be using a simple fibonacci function. The Fibonacci sequence is an infinite sequence of positive integers where the next number in the sequence is found by summing up the two previous numbers. Here are the first 11 numbers:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Our fibonacci function receives an index of the fibonacci sequence, computes the value on the fly, and returns it.

To ensure the function is working as expected, we call it with a value that we know the correct answer for (the fourth element of the Fibonacci series is 3), then the self.assertEqual(a, b) method is called to check that a and b are equal. If the function has a bug and does not return the expected result, the framework will tell us when we execute it:

    λ python3 -m venv .env
source .env/bin/activate

F
======================================================================
FAIL: test_fibo (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_fibo.py", line 8, in test_fibo
self.assertEqual(result, 3)
AssertionError: 5 != 3

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

It seems there's a bug in our fibonacci function and whoever wrote it forgot that for n=0 it should return 0. Fixing the function and running the test again shows that the function is now correct:


λ python test_fibo.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

This is great and is certainly a step in the right direction. But notice that, in order to code this very simple check, we had to do a number of things not really related to the check itself:

  1. Import unittest
  2. Create a class subclassing from unittest.TestCase

  1. Use self.assertEqual() to do the checking; there are a lot of self.assert* methods that should be used for all situations like self.assertGreaterEqual (for ≥ comparisons), self.assertLess (for < comparisons), self.assertAlmostEqual (for floating point comparisons), self.assertMultiLineEqual() (for multi-line string comparisons), and so on

The above feels like unnecessary boilerplate, and while it is certainly not the end of the world, some people feel that the code is non-Pythonic; code is written just to placate the framework into doing what you need it to.

Also, the unittest framework doesn't provide much in terms of batteries included to help you write your tests for the real world. Need a temporary directory? You need to create it yourself and clean up afterwards. Need to connect to a PostgreSQL database to test a Flask application? You will need to write the supporting code to connect to the database, create the required tables, and clean up when the tests end. Need to share utility test functions and resources between tests? You will need to create base classes and reuse them through subclassing, which in large code bases might evolve into multiple inheritance. Some frameworks provide their own unittest support code (for example, Django, https://www.djangoproject.com/), but those frameworks are rare.

You have been reading a chapter from
pytest Quick Start Guide
Published in: Aug 2018
Publisher: Packt
ISBN-13: 9781789347562
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime