×
Python Testing with unittest, nose, pytest cover page
Python Testing with unittest, nose, pytest

Suggested

$5.00
Buy Now

Python Testing with unittest, nose, pytest

Introduction

PythonTesting.net is a blog where I write about software testing.

The most popular posts so far are the tutorials on how to get started using the 3 most popular testing frameworks:

  • unittest
  • nose
  • pytest

I’ve organized a bunch of the most poplar posts into a sequence that I think makes sense, and pulled them into this book format.

I did this becuase I personally would have liked this stuff in an eBook format when I started learning about testing with Python. So, I hope it’s helpful for you.

How I got started writing about this stuff.

I’ve been a professional software developer since 1996.

I’ve been using Python for about the last 10 years. Mostly for testing.

One day I needed a test framework to run a bunch of pre-existing test scripts that weren’t set up to use any franework. Because of Pythons introspection facilities, it seemed like it would be pretty easy to implement.

I knew somewhat about unittest. But I really didn’t want to derive classes just to get test functions running.

The first incantation was pretty simple, and was implemented quickly.

However, the more we used it, the more new features we needed. So it grew.

Finally, one day, I looked on the web to see what test frameworks were available.

I found out more about unittest. And I found nose.
And then pytest.

But the documentation (for all of them) was confusing. At least to me.

I decided to find out for myself, and explore all three.

At first I thought I would discover that one was far superior to all the rest.
But I don’t think that’s the case.

I do think pytest is by far the coolest and most advanced.
However, unittest keeps improving, and is no slouch.
And although nose isn’t really in development as far as I can tell, lots of people still use it successfully.

Along the way I’ve learned lots about all three, and also some on doctest.

That’s where pythonTesting.net comes in. I am trying to share all that I know (and can clearly speak about) regarding these frameworks.

This book is a fund raiser

The proceeds from this book do a few things.

  1. Encourage me to keep writing content on pythontesting.net.
  2. Help offset the cost of putting this content and more into a professionally published book on the subject. See next section.
  3. Help pay off the laptop I just bought so I can write more.
  4. Let my family know that this is a good thing for me to be spending my time on.

unittest

unittest introduction

The unittest test framework is python’s xUnit style framework.
It is a standard module that you already have if you’ve got python version 2.1 or greater.
In this post, I’ll cover the basics of how to create and run a simple test using unittest.
Then I’ll show how I’m using it to test markdown.py.

Overview of unittest

The unittest module used to be called PyUnit, due to it’s legacy as a xUnit style framework.
It works much the same as the other styles of xUnit, and if you’re familiar with unit testing in other languages, this framework (or derived versions), may be the most comfortable for you.

The standard work flow is:

  1. You define your own class derived from unittest.TestCase.
  2. Then you fill it with functions that start with ‘test_’.
  3. You run the tests by placing unittest.main() in your file, usually at the bottom.

One of the many benefits of unittest, that you’ll use when your tests get bigger than the toy examples I’m showing on this blog, is the use of ‘setUp’ and ‘tearDown’ functions to get your system ready for the tests.

I’ll run through a simple example first, then show how I’m using unittest for testing markdown.py.

unittest example

Here is a simple module called unnecessary_math.py.

unnecessary_math.py:

1 def multiply(a, b):
2     return a * b

Here’s some example test code to test my ‘multiply’ function.

test_um_unittest.py:

 1 import unittest
 2 from unnecessary_math import multiply
 3 
 4 class TestUM(unittest.TestCase):
 5 
 6     def setUp(self):
 7         pass
 8 
 9     def test_numbers_3_4(self):
10         self.assertEqual( multiply(3,4), 12)
11 
12     def test_strings_a_3(self):
13         self.assertEqual( multiply('a',3), 'aaa')
14 
15 if __name__ == '__main__':
16     unittest.main()

In this example, I’ve used assertEqual(). The unittest framework has a whole bunch of assertBlah() style functions like assertEqual(). Once you have a reasonable reference for all of the assert functions bookmarked, working with unnittest is pretty powerful and easy.

Aside from the tests you write, most of what you need to do can be accomplished with the test fixture methods such as setUp, tearDown, setUpClass, tearDownClass, etc.

Running unittests

At the bottom of the test file, we have this code:

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

This allows us to run all of the test code just by running the file.

Running it with no options is the most terse, and running with a ‘-v’ is more verbose, showing which tests ran.

 1 > python test_um_unittest.py
 2 ..
 3 ------------------------------------------
 4 Ran 2 tests in 0.000s
 5 
 6 OK
 7 > python test_um_unittest.py -v
 8 test_numbers_3_4 (__main__.TestUM) ... ok
 9 test_strings_a_3 (__main__.TestUM) ... ok
10 
11 ------------------------------------------
12 Ran 2 tests in 0.000s
13 
14 OK

Test discovery

Let’s say that you’ve got a bunch of test files. It would be annoying to have to run each test file separately. That’s where test discovery comes in handy.

In our case, all of my test code (one file for now) is in ‘simple_example’.
To run all of the unittests in there, use python -m unittest discover simple_example, with or without the ‘-v’, like this:

 1 > python -m unittest discover simple_example
 2 ..
 3 --------------------------------------------------
 4 Ran 2 tests in 0.000s
 5 
 6 OK
 7 > python -m unittest discover -v simple_example
 8 test_numbers_3_4 (test_um_unittest.TestUM) ... ok
 9 test_strings_a_3 (test_um_unittest.TestUM) ... ok
10 
11 ---------------------------------------------------
12 Ran 2 tests in 0.000s
13 
14 OK

unittest example with markdown.py

Now, I’ll throw unittest at my markdown.py project.
This is going to be pretty straightforward, as the tests are quite similar to the doctest versions, just formatted with all of the unittest boilerplate stuff, especially since I don’t need to make use of startUp or tearDown fixtures.

test_markdown_unittest.py:

 1 import unittest
 2 from markdown_adapter import run_markdown
 3 
 4 class TestMarkdownPy(unittest.TestCase):
 5 
 6     def setUp(self):
 7         pass
 8 
 9     def test_non_marked_lines(self):
10         '''
11         Non-marked lines should only get 'p' tags around all input
12         '''
13         self.assertEqual(
14                 run_markdown('this line has no special handling'),
15                 '<p>this line has no special handling</p>')
16 
17     def test_em(self):
18         '''
19         Lines surrounded by asterisks should be wrapped in 'em' tags
20         '''
21         self.assertEqual(
22                 run_markdown('*this should be wrapped in em tags*'),
23                 '<p><em>this should be wrapped in em tags</em></p>')
24 
25     def test_strong(self):
26         '''
27         Lines surrounded by double asterisks should be wrapped in 'strong' tags
28         '''
29         self.assertEqual(
30                 run_markdown('**this should be wrapped in strong tags**'),
31                 '<p><strong>this should be wrapped in strong tags</strong></p>')
32 
33 if __name__ == '__main__':
34     unittest.main()

Testing markdown.py

And now we can see that everything is failing (as expected).

 1 > python test_markdown_unittest.py
 2 FFF
 3 ======================================================================
 4 FAIL: test_em (__main__.TestMarkdownPy)
 5 ----------------------------------------------------------------------
 6 Traceback (most recent call last):
 7   File "test_markdown_unittest.py", line 29, in test_em
 8     '<p><em>this should be wrapped in em tags</em></p>')
 9 AssertionError: '*this should be wrapped in em tags*' != '<p><em>this should be \
10 wrapped in em tags</em></p>'
11 
12 ======================================================================
13 FAIL: test_non_marked_lines (__main__.TestMarkdownPy)
14 ----------------------------------------------------------------------
15 Traceback (most recent call last):
16   File "test_markdown_unittest.py", line 21, in test_non_marked_lines
17     '<p>this line has no special handling</p>')
18 AssertionError: 'this line has no special handling' != '<p>this line has no spec\
19 ial handling</p>'
20 
21 ======================================================================
22 FAIL: test_strong (__main__.TestMarkdownPy)
23 ----------------------------------------------------------------------
24 Traceback (most recent call last):
25   File "test_markdown_unittest.py", line 37, in test_strong
26     '<p><strong>this should be wrapped in strong tags</strong></p>')
27 AssertionError: '**this should be wrapped in strong tags**' != '<p><strong>this \
28 should be wrapped in strong tags</strong></p>'
29 
30 ----------------------------------------------------------------------
31 Ran 3 tests in 0.142s
32 
33 FAILED (failures=3)

More unittest info

The python.org page on unittest is a great source for information on unittest.

Full Table Of Contents

You are reading a sample, which just has the introduction and an intrudoction to unittest.

If this is useful to you, please consider purchasing the full book.

The full book contains:

  • unittest
    • unittest introduction
      • Overview of unittest
      • Running unittests
      • Test discovery
      • unittest examples
    • unittest fixture syntax and flow reference
      • Software Test Fixtures
      • Common Case Example
      • Full Test Fixture Example
      • Full Test Fixture Flow
      • Adding Cleanup Calls
      • Skipping tests within setUp
      • Exceptions in Fixtures
  • nose
    • nose introduction
      • Nose example
      • Running nose
      • Nose fixtures
      • Nose assert_equals
      • Test discovery
      • Running unittests from nose
      • Running doctests from nose
    • nose support for unittest style fixtures
    • nose fixture reference
      • Method, Function, Package, Module, and Class fixtures
      • Full example
      • Control flow
      • Alternative names for fixtures
  • pytest
    • pytest introduction
      • pytest example
      • Running pytest
      • pytest fixtures
      • Test discovery
      • Running unittests from pytest
      • Running doctests from pytest
      • Running nose tests from pytest
    • pytest fixtures
      • pytest unittest style fixtures
      • pytest xUnit style fixtures
      • pytest fixtures easy example
      • pytest fixtures nuts and bolts
      • pytest session scoped fixtures