Testing Tools Comparison

A comparison of different testing tools in Python.
Covered yet: unittest and nosetest
Not covered yet: pytest

unittest

Installation

Unittest is built in to Python and part of the standard library since version 2.1. and thereby one of the ready to use ‘Battery included’ modules of Python.

Using

Inside the project-folder run:

python -m unittest

unittest will start in the test discovery mode and automaticaly detect all files which start with test_. Example:

test_ex47.property
test_some_name.py

But you can run any file which has tests. Just specify the path:

python -m unittest tests/something_to_test.py

Style

Import

import unittest

Testcases

unittest provides a base class, TestCase, which may be used to create new test cases. In this case, write a class that inherits from unittest.TestCase:

import unittest
from ex47.game import Room

class MyTest(unittest.TestCase):
    def test_room(self):
        gold = Room("GoldRoom",
                    """This room has gold in it you can grab. There's a
                    door to the north.""")
        self.assertEqual(gold.name, "GoldRoom")
        self.assertEqual(gold.paths, {})

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

Start every test function with test_. This naming convention informs the test runner about which methods represent tests.

The final block if __name__ == '__main__': shows a simple way to run the tests. unittest.main() provides a command-line interface to the test script. So you have to include the main function on the end of your script to run the tests from the command line.

Specialty

The test cases inherit from the base class unittest.TestCase. So you have to subclass all of your testclasses from it. For example: class MyTest(unittest.TestCase).
To let unittest automaticaly detect and call your tests you need to set the main function on the end of your tests:

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

Example

test_ex47.py

import unittest
from ex47.game import Room

class MyTest(unittest.TestCase):
    def test_room(self):
        gold = Room("GoldRoom",
                    """This room has gold in it you can grab. There's a
                    door to the north.""")
        self.assertEqual(gold.name, "GoldRoom")
        self.assertEqual(gold.paths, {})

    def test_room_paths(self):
        center = Room("Center", "Test room in the center.")
        north = Room("North", "Test room in the north.")
        south = Room("South", "Test room in the south.")

        center.add_paths({'north': north, 'south': south})
        self.assertEqual(center.go('north'), north)
        self.assertEqual(center.go('south'), south)

    def test_map(self):
        start = Room("Start", "You can go west and down a hole.")
        west = Room("Trees", "There are trees here, you can go east.")
        down = Room("Dungeon", "It's dark down here, you can go up.")

        start.add_paths({'west': west, 'down': down})
        west.add_paths({'east': start})
        down.add_paths({'up': start})

        self.assertEqual(start.go('west'), west)
        self.assertEqual(start.go('west').go('east'), start)
        self.assertEqual(start.go('down').go('up'), start)


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

Docs

https://docs.python.org/3.6/library/unittest.html


nose

Installation

You have to install nose to use it.

pip install nose

Using

Inside the project-folder run:

# python 2
nosetests
# python 3
nosetests3

nose will automaticaly detect all files with the following regex-Pattern, and run it.

(?:^|[\\b_\\.-])[Tt]est

Style

Import

from nose.tools.import *

Testcases

Write your tests directly. They will be automaticaly inherit from the unittest.TestCase class. So, don’t wrapp it in a class.
It should look something like this:

def test_room():
    gold = Room("GoldRoom", "Test sentence")
    assert_equal(gold.name, "GoldRoom")
    assert_equal(gold.paths, {})

Specialty

Differently to unittest you need no main function.
You can use all assertX methods found in unittest.TestCase but spell it in PEP 8#function-names fashion, so assert_equal rather than assertEqual.

Example

ex47_tests.py

from nose.tools import *
from ex47.game import Room

def test_room():
    gold = Room("GoldRoom",
                """This room has gold in it you can grab. There's a
                door to the north.""")
    assert_equal(gold.name, "GoldRoom")
    assert_equal(gold.paths, {})

def test_room_paths():
    center = Room("Center", "Test room in the center.")
    north = Room("North", "Test room in the north.")
    south = Room("South", "Test room in the south.")

    center.add_paths({'north': north, 'south': south})
    assert_equal(center.go('north'), north)
    assert_equal(center.go('south'), south)

def test_map():
    start = Room("Start", "You can go west and down a hole.")
    west = Room("Trees", "There are trees here, you can go east.")
    down = Room("Dungeon", "It's dark down here, you can go up.")

    start.add_paths({'west': west, 'down': down})
    west.add_paths({'east': start})
    down.add_paths({'up': start})

    assert_equal(start.go('west'), west)
    assert_equal(start.go('west').go('east'), start)
    assert_equal(start.go('down').go('up'), start)

Docs

http://nose.readthedocs.io/en/latest/index.html


pytest

TODO

2 Likes

Hi @DidierCH.

I can recomend pythontesting.net for reading about Pytest.
I bought Brians book about Pytest and think it is the best ”manual” for testing python. For me anyway.
The gap between easy examples and advanced examples are not too wide.
This was a problem for me with the nose and unittest.

3 Likes

Thank you @ulfen69. I bought the book! Testing is my weakness, so I have to improve on it :slight_smile: