{"id":13937723,"url":"https://github.com/cgoldberg/python-unittest-tutorial","last_synced_at":"2025-05-08T21:45:43.386Z","repository":{"id":6342184,"uuid":"7578293","full_name":"cgoldberg/python-unittest-tutorial","owner":"cgoldberg","description":"Python3 tutorial - unittest module - PyMOTW","archived":false,"fork":false,"pushed_at":"2017-08-07T08:29:57.000Z","size":179,"stargazers_count":226,"open_issues_count":1,"forks_count":102,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-01-26T04:05:44.510Z","etag":null,"topics":["python","python3","tutorial","unittest"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cgoldberg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-12T17:34:57.000Z","updated_at":"2024-11-23T05:49:30.000Z","dependencies_parsed_at":"2022-08-02T14:00:28.529Z","dependency_job_id":null,"html_url":"https://github.com/cgoldberg/python-unittest-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgoldberg%2Fpython-unittest-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgoldberg%2Fpython-unittest-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgoldberg%2Fpython-unittest-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgoldberg%2Fpython-unittest-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cgoldberg","download_url":"https://codeload.github.com/cgoldberg/python-unittest-tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238044095,"owners_count":19407128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","python3","tutorial","unittest"],"created_at":"2024-08-07T23:03:48.631Z","updated_at":"2025-02-10T02:12:24.789Z","avatar_url":"https://github.com/cgoldberg.png","language":"Python","readme":"# Python Unit Testing Tutorial\n\nThis is an update to Doug Hellman's excellent PyMOTW article found here:\n\n* [PyMOTW - unittest (2007)](http://www.doughellmann.com/PyMOTW/unittest/index.html)\n\nThe code and examples here have been updated by [Corey Goldberg](https://github.com/cgoldberg) to reflect Python 3.3.\n\nfurther reading:\n\n* [unittest - Python Standard Library 3.3 Documentation](http://docs.python.org/3.3/library/unittest.html)\n  \n----\n\n## unittest - Automated testing framework\n\nPython'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.\n\n## Basic Test Structure\n\nTests, 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,\n\n```python\nimport unittest\n\nclass SimplisticTest(unittest.TestCase):\n\n    def test(self):\n        self.assertTrue(True)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nIn this case, the `SimplisticTest` has a single `test()` method, which would fail if True is ever False.\n\n## Running Tests\n\nThe easiest way to run unittest tests is to include:\n\n```python\nif __name__ == '__main__':\n    unittest.main()\n```\n\nat the bottom of each test file, then simply run the script directly from the command line:\n\n```\n$ python3 test_simple.py\n\n.\n----------------------------------------------------------------------\nRan 1 test in 0.000s\n\nOK\n```\n\nThis 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:\n\n```\n$ python3 test_simple.py -v\n\ntest (__main__.SimplisticTest) ... ok\n\n----------------------------------------------------------------------\nRan 1 test in 0.000s\n\nOK\n```\n\n## Test Outcomes\n\nTests have 3 possible outcomes:\n\n```\nok\n```\n\nThe test passes.\n\n```\nFAIL\n```\n\nThe test does not pass, and raises an `AssertionError` exception.\n\n```\nERROR\n```\n\nThe test raises an exception other than `AssertionError`.\n\nThere is no explicit way to cause a test to \"pass\", so a test's status depends on the presence (or absence) of an exception.\n\n```python\nimport unittest\n\nclass OutcomesTest(unittest.TestCase):\n\n    def test_pass(self):\n        self.assertTrue(True)\n\n    def test_fail(self):\n        self.assertTrue(False)\n\n    def test_error(self):\n        raise RuntimeError('Test error!')\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nWhen a test fails or generates an error, the traceback is included in the output.\n\n```\n$ python3 test_outcomes.py\n\n\nEF.\n======================================================================\nERROR: test_error (__main__.OutcomesTest)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"test_outcomes.py\", line 13, in test_error\n    raise RuntimeError('Test error!')\nRuntimeError: Test error!\n\n======================================================================\nFAIL: test_fail (__main__.OutcomesTest)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"test_outcomes.py\", line 9, in test_fail\n    self.assertTrue(False)\nAssertionError: False is not true\n\n----------------------------------------------------------------------\nRan 3 tests in 0.000s\n\nFAILED (failures=1, errors=1)\n```\n\nIn 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.\n\n```python\nimport unittest\n\nclass FailureMessageTest(unittest.TestCase):\n\n    def test_fail(self):\n        self.assertTrue(False, 'failure message goes here')\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\n```\n$ python3 test_failwithmessage.py -v\n\ntest_fail (__main__.FailureMessageTest) ... FAIL\n\n======================================================================\nFAIL: test_fail (__main__.FailureMessageTest)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"test_failwithmessage.py\", line 6, in test_fail\n    self.assertTrue(False, 'failure message goes here')\nAssertionError: failure message goes here\n\n----------------------------------------------------------------------\nRan 1 test in 0.000s\n\nFAILED (failures=1)\n```\n\n## Asserting Truth\n\nMost 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.\n\n```python\nimport unittest\n\nclass TruthTest(unittest.TestCase):\n\n    def test_assert_true(self):\n        self.assertTrue(True)\n\n    def test_assert_false(self):\n        self.assertFalse(False)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\n```\n$ python3 test_truth.py -v\n\ntest_assert_false (__main__.TruthTest) ... ok\ntest_assert_true (__main__.TruthTest) ... ok\n\n----------------------------------------------------------------------\nRan 2 tests in 0.000s\n\nOK\n```\n\n## Assertion Methods\n\nThe `TestCase` class provides a number of methods to check for and report failures:\n\n* [`TestCase` class](http://docs.python.org/3.3/library/unittest.html#unittest.TestCase)\n* [`assert*` methods](http://docs.python.org/3.3/library/unittest.html#assert-methods)\n\n### Common Assertions\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth\u003eMethod\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertTrue(x, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertFalse(x, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertIsNone(x, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertIsNotNone(x, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertNotEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertIs(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertIsNot(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertIn(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertNotIn(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertIsInstance(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertNotIsInstance(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n### Other Assertions\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth\u003eMethod\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertAlmostEqual(a, b, places=7, msg=None, delta=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertNotAlmostEqual(a, b, places=7, msg=None, delta=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertGreater(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertGreaterEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertLess(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertLessEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertRegex(text, regexp, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertNotRegex(text, regexp, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertCountEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertMultiLineEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertSequenceEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertListEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertTupleEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertSetEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertDictEqual(a, b, msg=None)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n### Failure Messages\n\nThese assertions are handy, since the values being compared appear in the failure message when a test fails.\n\n```python\nimport unittest\n\nclass InequalityTest(unittest.TestCase):\n\n    def testEqual(self):\n        self.assertNotEqual(1, 3-2)\n\n    def testNotEqual(self):\n        self.assertEqual(2, 3-2)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nAnd when these tests are run:\n\n```\n$ python3 test_notequal.py -v\n\ntestEqual (__main__.InequalityTest) ... FAIL\ntestNotEqual (__main__.InequalityTest) ... FAIL\n\n======================================================================\nFAIL: test_equal (__main__.InequalityTest)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"test_notequal.py\", line 7, in test_equal\n    self.assertNotEqual(1, 3-2)\nAssertionError: 1 == 1\n\n======================================================================\nFAIL: test_not_equal (__main__.InequalityTest)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"test_notequal.py\", line 10, in test_not_equal\n    self.assertEqual(2, 3-2)\nAssertionError: 2 != 1\n\n----------------------------------------------------------------------\nRan 2 tests in 0.000s\n\nFAILED (failures=2)\n```\n\nAll the assert methods above accept a `msg` argument that, if specified, is used as the error message on failure.\n\n## Testing for Exceptions (and Warnings)\n\nThe `TestCase` class provides methods to check for expected exceptions:\n\n* [`TestCase` class](http://docs.python.org/3.3/library/unittest.html#unittest.TestCase)\n* [`assert*` methods](http://docs.python.org/3.3/library/unittest.html#assert-methods)\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth\u003eMethod\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertRaises(exception)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertRaisesRegex(exception, regexp)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertWarns(warn, fun, *args, **kwds)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003e\u003ccode\u003eassertWarnsRegex(warn, fun, *args, **kwds)\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\nAs 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:\n\n```python\nimport unittest\n\ndef raises_error(*args, **kwds):\n    raise ValueError('Invalid value: %s%s' % (args, kwds))\n\nclass ExceptionTest(unittest.TestCase):\n\n    def test_trap_locally(self):\n        try:\n            raises_error('a', b='c')\n        except ValueError:\n            pass\n        else:\n            self.fail('Did not see ValueError')\n\n    def test_assert_raises(self):\n        self.assertRaises(ValueError, raises_error, 'a', b='c')\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nThe results for both are the same, but the second test using `assertRaises()` is more succinct.\n\n```\n$ python3 test_exception.py -v\n\ntest_assert_raises (__main__.ExceptionTest) ... ok\ntest_trap_locally (__main__.ExceptionTest) ... ok\n\n----------------------------------------------------------------------\nRan 2 tests in 0.000s\n\nOK\n```\n\n## Test Fixtures\n\nFixtures 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()`.\n\n```python\nimport unittest\n\nclass FixturesTest(unittest.TestCase):\n\n    def setUp(self):\n        print('In setUp()')\n        self.fixture = range(1, 10)\n\n    def tearDown(self):\n        print('In tearDown()')\n        del self.fixture\n\n    def test(self):\n        print('in test()')\n        self.assertEqual(self.fixture, range(1, 10))\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nWhen this sample test is run, you can see the order of execution of the fixture and test methods:\n\n```\n$ python3 test_fixtures.py\n\n.\n----------------------------------------------------------------------\nRan 1 test in 0.000s\n\nOK\nIn setUp()\nin test()\nIn tearDown()\n```\n\n## Test Suites\n\nThe 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.\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgoldberg%2Fpython-unittest-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcgoldberg%2Fpython-unittest-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgoldberg%2Fpython-unittest-tutorial/lists"}