All Projects → cgoldberg → Python Unittest Tutorial

cgoldberg / Python Unittest Tutorial

Python3 tutorial - unittest module - PyMOTW

Programming Languages

python
139335 projects - #7 most used programming language
python3
1442 projects

Projects that are alternatives of or similar to Python Unittest Tutorial

Slic Starter
A complete, serverless starter project
Stars: ✭ 184 (-3.16%)
Mutual labels:  tutorial
React Survey
A Survey System Created With React
Stars: ✭ 186 (-2.11%)
Mutual labels:  tutorial
Arcadecarphysics
Arcade Car Physics - Vehicle Simulation for Unity3D
Stars: ✭ 189 (-0.53%)
Mutual labels:  tutorial
Docker For Java
Docker for Java Developers
Stars: ✭ 183 (-3.68%)
Mutual labels:  tutorial
React Workshop
The course material for our React Hooks workshop
Stars: ✭ 184 (-3.16%)
Mutual labels:  tutorial
Django Mock Queries
A library for mocking django queryset functions in memory for testing
Stars: ✭ 187 (-1.58%)
Mutual labels:  unittest
Gans From Theory To Production
Material for the tutorial: "Deep Diving into GANs: from theory to production"
Stars: ✭ 182 (-4.21%)
Mutual labels:  tutorial
Smarthome Tutorial
🎓 Tutorial: smart-home dashboard UI concept.
Stars: ✭ 190 (+0%)
Mutual labels:  tutorial
Wasm game of life
A Rust and WebAssembly tutorial implementing the Game of Life
Stars: ✭ 184 (-3.16%)
Mutual labels:  tutorial
Tutorial Git
📘 어떻게 깃을 사용하는지 빠르게 알아봅시다. (Quick learn How to use Git.)
Stars: ✭ 188 (-1.05%)
Mutual labels:  tutorial
Training Material
A collection of Galaxy-related training material
Stars: ✭ 184 (-3.16%)
Mutual labels:  tutorial
Zero To Preact
A Step-by-step Guide to Preact + Webpack 2, without boilerplate!
Stars: ✭ 185 (-2.63%)
Mutual labels:  tutorial
Startwordpress
Learn how to develop a WordPress theme from scratch with this basic skeleton and accompanying tutorial.
Stars: ✭ 187 (-1.58%)
Mutual labels:  tutorial
Keycloak Nodejs Example
A simply step by step Keycloak, MySQL and Node.js integration tutorial. There are some docker examples as well.
Stars: ✭ 183 (-3.68%)
Mutual labels:  tutorial
Library App
Detailed Ember.js Octane v3.21 tutorial for absolute beginners. https://yoember.com
Stars: ✭ 189 (-0.53%)
Mutual labels:  tutorial
K8s Intro Tutorials
Kubernetes Intro Tutorials
Stars: ✭ 183 (-3.68%)
Mutual labels:  tutorial
React Gh Pages
Deploying a React App (created using create-react-app) to GitHub Pages
Stars: ✭ 2,801 (+1374.21%)
Mutual labels:  tutorial
Androidtvapptutorial
Hands on tutorial for coding Android TV app from scratch
Stars: ✭ 190 (+0%)
Mutual labels:  tutorial
Tutorials
📖 Community driven web development tutorials
Stars: ✭ 189 (-0.53%)
Mutual labels:  tutorial
Lambda The Cli Way
AWS Lambda using CLI, an introductory cookbook
Stars: ✭ 188 (-1.05%)
Mutual labels:  tutorial

Python Unit Testing Tutorial

This is an update to Doug Hellman's excellent PyMOTW article found here:

The code and examples here have been updated by Corey Goldberg to reflect Python 3.3.

further reading:


unittest - Automated testing framework

Python's unittest module, sometimes referred to as 'PyUnit', is based on the XUnit framework design by Kent Beck and Erich Gamma. The same pattern is repeated in many other languages, including C, Perl, Java, and Smalltalk. The framework implemented by unittest supports fixtures, test suites, and a test runner to enable automated testing for your code.

Basic Test Structure

Tests, as defined by unittest, have two parts: code to manage test "fixtures", and the test itself. Individual tests are created by subclassing TestCase and overriding or adding appropriate methods. For example,

import unittest

class SimplisticTest(unittest.TestCase):

    def test(self):
        self.assertTrue(True)

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

In this case, the SimplisticTest has a single test() method, which would fail if True is ever False.

Running Tests

The easiest way to run unittest tests is to include:

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

at the bottom of each test file, then simply run the script directly from the command line:

$ python3 test_simple.py

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

OK

This abbreviated output includes the amount of time the tests took, along with a status indicator for each test (the "." on the first line of output means that a test passed). For more detailed test results, include the -v option:

$ python3 test_simple.py -v

test (__main__.SimplisticTest) ... ok

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

OK

Test Outcomes

Tests have 3 possible outcomes:

ok

The test passes.

FAIL

The test does not pass, and raises an AssertionError exception.

ERROR

The test raises an exception other than AssertionError.

There is no explicit way to cause a test to "pass", so a test's status depends on the presence (or absence) of an exception.

import unittest

class OutcomesTest(unittest.TestCase):

    def test_pass(self):
        self.assertTrue(True)

    def test_fail(self):
        self.assertTrue(False)

    def test_error(self):
        raise RuntimeError('Test error!')

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

When a test fails or generates an error, the traceback is included in the output.

$ python3 test_outcomes.py


EF.
======================================================================
ERROR: test_error (__main__.OutcomesTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_outcomes.py", line 13, in test_error
    raise RuntimeError('Test error!')
RuntimeError: Test error!

======================================================================
FAIL: test_fail (__main__.OutcomesTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_outcomes.py", line 9, in test_fail
    self.assertTrue(False)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 3 tests in 0.000s

FAILED (failures=1, errors=1)

In the example above, test_fail() fails and the traceback shows the line with the failure code. It is up to the person reading the test output to look at the code to figure out the semantic meaning of the failed test, though. To make it easier to understand the nature of a test failure, the assert*() methods all accept an argument msg, which can be used to produce a more detailed error message.

import unittest

class FailureMessageTest(unittest.TestCase):

    def test_fail(self):
        self.assertTrue(False, 'failure message goes here')

if __name__ == '__main__':
    unittest.main()
$ python3 test_failwithmessage.py -v

test_fail (__main__.FailureMessageTest) ... FAIL

======================================================================
FAIL: test_fail (__main__.FailureMessageTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_failwithmessage.py", line 6, in test_fail
    self.assertTrue(False, 'failure message goes here')
AssertionError: failure message goes here

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

FAILED (failures=1)

Asserting Truth

Most tests assert the truth of some condition. There are a few different ways to write truth-checking tests, depending on the perspective of the test author and the desired outcome of the code being tested. If the code produces a value which can be evaluated as true, the method assertTrue() should be used. If the code produces a false value, the method assertFalse() makes more sense.

import unittest

class TruthTest(unittest.TestCase):

    def test_assert_true(self):
        self.assertTrue(True)

    def test_assert_false(self):
        self.assertFalse(False)

if __name__ == '__main__':
    unittest.main()
$ python3 test_truth.py -v

test_assert_false (__main__.TruthTest) ... ok
test_assert_true (__main__.TruthTest) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

Assertion Methods

The TestCase class provides a number of methods to check for and report failures:

Common Assertions

Method
assertTrue(x, msg=None)
assertFalse(x, msg=None)
assertIsNone(x, msg=None)
assertIsNotNone(x, msg=None)
assertEqual(a, b, msg=None)
assertNotEqual(a, b, msg=None)
assertIs(a, b, msg=None)
assertIsNot(a, b, msg=None)
assertIn(a, b, msg=None)
assertNotIn(a, b, msg=None)
assertIsInstance(a, b, msg=None)
assertNotIsInstance(a, b, msg=None)

Other Assertions

Method
assertAlmostEqual(a, b, places=7, msg=None, delta=None)
assertNotAlmostEqual(a, b, places=7, msg=None, delta=None)
assertGreater(a, b, msg=None)
assertGreaterEqual(a, b, msg=None)
assertLess(a, b, msg=None)
assertLessEqual(a, b, msg=None)
assertRegex(text, regexp, msg=None)
assertNotRegex(text, regexp, msg=None)
assertCountEqual(a, b, msg=None)
assertMultiLineEqual(a, b, msg=None)
assertSequenceEqual(a, b, msg=None)
assertListEqual(a, b, msg=None)
assertTupleEqual(a, b, msg=None)
assertSetEqual(a, b, msg=None)
assertDictEqual(a, b, msg=None)

Failure Messages

These assertions are handy, since the values being compared appear in the failure message when a test fails.

import unittest

class InequalityTest(unittest.TestCase):

    def testEqual(self):
        self.assertNotEqual(1, 3-2)

    def testNotEqual(self):
        self.assertEqual(2, 3-2)

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

And when these tests are run:

$ python3 test_notequal.py -v

testEqual (__main__.InequalityTest) ... FAIL
testNotEqual (__main__.InequalityTest) ... FAIL

======================================================================
FAIL: test_equal (__main__.InequalityTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_notequal.py", line 7, in test_equal
    self.assertNotEqual(1, 3-2)
AssertionError: 1 == 1

======================================================================
FAIL: test_not_equal (__main__.InequalityTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_notequal.py", line 10, in test_not_equal
    self.assertEqual(2, 3-2)
AssertionError: 2 != 1

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (failures=2)

All the assert methods above accept a msg argument that, if specified, is used as the error message on failure.

Testing for Exceptions (and Warnings)

The TestCase class provides methods to check for expected exceptions:

Method
assertRaises(exception)
assertRaisesRegex(exception, regexp)
assertWarns(warn, fun, *args, **kwds)
assertWarnsRegex(warn, fun, *args, **kwds)

As previously mentioned, if a test raises an exception other than AssertionError it is treated as an error. This is very useful for uncovering mistakes while you are modifying code which has existing test coverage. There are circumstances, however, in which you want the test to verify that some code does produce an exception. For example, if an invalid value is given to an attribute of an object. In such cases, assertRaises() makes the code more clear than trapping the exception yourself. Compare these two tests:

import unittest

def raises_error(*args, **kwds):
    raise ValueError('Invalid value: %s%s' % (args, kwds))

class ExceptionTest(unittest.TestCase):

    def test_trap_locally(self):
        try:
            raises_error('a', b='c')
        except ValueError:
            pass
        else:
            self.fail('Did not see ValueError')

    def test_assert_raises(self):
        self.assertRaises(ValueError, raises_error, 'a', b='c')

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

The results for both are the same, but the second test using assertRaises() is more succinct.

$ python3 test_exception.py -v

test_assert_raises (__main__.ExceptionTest) ... ok
test_trap_locally (__main__.ExceptionTest) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

Test Fixtures

Fixtures are resources needed by a test. For example, if you are writing several tests for the same class, those tests all need an instance of that class to use for testing. Other test fixtures include database connections and temporary files (many people would argue that using external resources makes such tests not "unit" tests, but they are still tests and still useful). TestCase includes a special hook to configure and clean up any fixtures needed by your tests. To configure the fixtures, override setUp(). To clean up, override tearDown().

import unittest

class FixturesTest(unittest.TestCase):

    def setUp(self):
        print('In setUp()')
        self.fixture = range(1, 10)

    def tearDown(self):
        print('In tearDown()')
        del self.fixture

    def test(self):
        print('in test()')
        self.assertEqual(self.fixture, range(1, 10))

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

When this sample test is run, you can see the order of execution of the fixture and test methods:

$ python3 test_fixtures.py

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

OK
In setUp()
in test()
In tearDown()

Test Suites

The standard library documentation describes how to organize test suites manually. I generally do not use test suites directly, because I prefer to build the suites automatically (these are automated tests, after all). Automating the construction of test suites is especially useful for large code bases, in which related tests are not all in the same place. Tools such as nose make it easier to manage tests when they are spread over multiple files and directories.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].