Differences between revisions 4 and 12 (spanning 8 versions)
Revision 4 as of 2020-05-14 18:32:55
Size: 4389
Comment:
Revision 12 as of 2023-03-02 16:08:53
Size: 4970
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
= Python UnitTest = = Python Unittest =
Line 3: Line 3:
Python has a built-in test suite library. It is rudimentary, but requires no external libraries or tools. '''`unittest`''' is a module for unit testing code. It is ''by design'' a basic and minimal tool; it was designed for use within Python and requiring no external libraries or tools.
Line 11: Line 11:
== Test Cases == == Module ==
Line 13: Line 13:
The basic implementation of a test case is as follows: === Usage ===
Line 20: Line 20:
Line 47: Line 48:
=== Setup and Teardown === ==== Setup and Teardown ====
Line 63: Line 64:
=== Subtests === ==== Subtests ====
Line 80: Line 81:
=== Conditional Testing === ==== Conditional Testing ====
Line 96: Line 97:
== Test Methods == === Test Methods ===
Line 117: Line 118:
||`assertRaises` || ||`with self.assertRaises(e,msg=m):`    || ||`assertRaises` || ||`with self.assertRaises(e,msg=m): ...`||
Line 123: Line 124:
== CLI Execution == === CLI Execution ===
Line 125: Line 126:
Verbosity is set with `-q` and `-v` flags. Verbosity is set with `--quiet` (`-q`) and `--verbose` (`-v`) flags.
Line 127: Line 128:
The `discover` subcommand searches for files names as `test_*.py`. A search directory can be supplied additionally. The `discover` subcommand searches for files names matching the pattern `test*.py`. A search directory can be optionally supplied using `--start-directory` (`-s`). An alternate pattern can be optionally supplied using `--pattern` (`-p`).
Line 130: Line 131:
$ python -m unittest discover -s tests/ $ python -m unittest discover -s tests/ -v
Line 132: Line 133:

----



== Writing Unit Tests ==

=== Bad File Inputs ===

To create a file with a bad encoding, try:

{{{
def write_bad_file(fn):
    with open(fn, 'w') as f:
        f.write('fooß'.encode('utf-8'))
        f.write('barß'.encode('cp1252'))
}}}

----



== See also ==

[[https://docs.python.org/3/library/unittest.html|Python unittest module documentation]]

Python Unittest

unittest is a module for unit testing code. It is by design a basic and minimal tool; it was designed for use within Python and requiring no external libraries or tools.


Module

Usage

import unittest

class Test1(unittest.TestCase):
    """This is a class docstring."""

    def test_1(self):
        #This will print "test_1 (__main__.Test1) ... ok"
        return

    def test_2(self):
        #This will print "test_1 (__main__.Test1) ... FAIL"
        self.fail()

    def test_3(self):
        #This will print "test_3 (__main__.Test1) ... ERROR"
        raise AttributeError

    @u.skip('foo bar')
    def test_4(self):
        #This will print "test_3 (__main__.Test1) ... skipped 'foo bar'"
        return

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

Any methods with a docstring print both the method's name and the docstring.

All failures or errors print tracebacks, the only difference being the label ('FAIL' or 'ERROR').

Setup and Teardown

The most common reason for grouping a set of tests into a test case is shared objects. These can be generated using the TestCase.setUp() method. (A tearDown() method is also available if needed.)

class TestWidget(unittest.TestCase):

    def setUp(self):
        self.widget = Widget('The widget')\

    def tearDown(self):
        self.widget.dispose()

Subtests

Sometimes a test needs to be run iteratively, as to test multiple possible inputs. Rather than requiring redundant coding, the subtests context will provide this functionality.

class TestEven(unittest.TestCase):

    def test_1(self):
        for i in range(0, 6):
            with self.subTest(i=i):
                self.assertEqual(i % 2, 0)

The i=i may seem redundant, but it will cause the subtest's value of i to print on execution.

Conditional Testing

Tests can be skipped conditionally. This can be used to prevent trivial test failures.

class TestVersion(unittest.TestCase):

    @unittest.skipIf(mylib.__version__ < (1, 3))
    def test_1(self):
        return


Test Methods

Method

Equivalent to...

Usage

assertEqual

a == b

self.assertEqual(a,b,msg=m)

assertNotEqual

a != b

self.assertNotEqual(a,b,msg=m)

assertGreater

a > b

self.assertGreater(a,b,msg=m)

assertGreaterEqual

a >= b

self.assertGreaterEqual(a,b,msg=m)

assertLesser

a < b

self.assertLesser(a,b,msg=m)

assertLesserEqual

a <= b

self.assertLesserEqual(a,b,msg=m)

assertTrue

bool(a) == True

self.assertTrue(a,msg=m)

assertFalse

bool(a) == False

self.assertFalse(a,msg=m)

assertIs

a is b

self.assertIs(a,b,msg=m)

assertIsNot

a is not

self.assertIsNot(a,b,msg=m)

assertIsNone

a is None

self.assertIsNone(a,b,msg=m)

assertIsNotNone

a is not None

self.assertIsNotNone(a,b,msg=m)

assertIn

a in b

self.assertIn(a,b,msg=m)

assertNotIn

a not in b

self.assertNotIn(a,b,msg=m)

assertRegex

re.search(b,a)

self.assertRegex(a,b)

assertNotRegex

not re.search(b,a)

self.assertNotRegex(a,b)

assertIsInstance

isinstance(a,b)

self.assertIsInstance(a,b,msg=m)

assertIsNotInstance

not isinstance(a,b)

self.assertIsNotInstance(a,b,msg=m)

assertRaises

with self.assertRaises(e,msg=m): ...


CLI Execution

Verbosity is set with --quiet (-q) and --verbose (-v) flags.

The discover subcommand searches for files names matching the pattern test*.py. A search directory can be optionally supplied using --start-directory (-s). An alternate pattern can be optionally supplied using --pattern (-p).

$ python -m unittest discover -s tests/ -v


Writing Unit Tests

Bad File Inputs

To create a file with a bad encoding, try:

def write_bad_file(fn):
    with open(fn, 'w') as f:
        f.write('fooß'.encode('utf-8'))
        f.write('barß'.encode('cp1252'))


See also

Python unittest module documentation


CategoryRicottone

Python/Unittest (last edited 2023-06-15 18:41:57 by DominicRicottone)