Python Module unittest

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

External

Internal

Overview

unittest mimics JUnit.

unittest vs. pytest

TODO: https://www.pythonpool.com/python-unittest-vs-pytest/

Concepts

Test Fixture

A test fixture represents the code needed to prepare the context for running one or more tests (create temporary databases, directories, etc.), and any associated cleanup actions. Also see Class and Module Fixtures section below.

Test Case

A test case is the individual unit of testing. In unittest, the test cases inherit from the base class TestCase.

Test Suite

A collection of test cases, test suites or both.

Grouping Tests

TO PROCESS: https://docs.python.org/3/library/unittest.html#grouping-tests

Test Runner

The test runner is the component that orchestrates the execution of tests and provides the outcomes to the user.

Loading and Running Tests

TO PROCESS: https://docs.python.org/3/library/unittest.html#loading-and-running-tests

unittest.mock

See Mocking below.

Organizing Test Code

TO PROCESS: https://docs.python.org/3/library/unittest.html#organizing-test-code

API

TestCase

A simple test case can be implemented by subclassing TestCase as shown below. The individual test methods are have names that start with test. This is a naming convention that informs the test runner about which methods to invoke as tests.

from unittest import TestCase

from my_code_to_test import some_function


class TestMyCode(TestCase):

    def test_empty(self):
        self.assertFalse(some_function(''))

    def test_lower_case(self):
        self.assertEqual('A', some_function('a'))

    def test_upper_case(self):
        self.assertEqual('A', some_function('A'))

    def test_exception(self):
        with self.assertRaises(ValueError):
            some_function('special')

Setup and Teardown

setUp() and tearDown() define instructions to be executed before and after each test method execution.

setUp()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp

tearDown()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.tearDown

setUpClass()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUpClass

tearDownClass()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.tearDownClass

Assertion Methods

These methods are used instead of the assert statement so the test runner can accumulate all test results and produce a report. Really? pytest can produce reports and it uses assert.

assertEquals()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual

assertNotEqual()

assertTrue()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue

assertFalse()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertFalse

assertRaises()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises

assertIs(), assertIsNot()

assertIsNone(), assertIsNotNone()

assertIn(), assertNotIn()

assertIsInstance(), assertNotIsInstance()

assertMultiLineEqual()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertMultiLineEqual

assertSequenceEqual()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertSequenceEqual

assertListEqual()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertListEqual

assertTupleEqual()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTupleEqual

assertSetEqual()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertSetEqual

assertDictEqual()

https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertDictEqual

TestResult

https://docs.python.org/3/library/unittest.html#unittest.TestResult

Operations

Command Line Syntax

Running tests from command line:

python -m unittest test_module_1 test_module_2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
python -m unittest tests/test_something.py # The file must be still importable as a module.

More verbosity: command line parameter -v.

If the unittest module is executed without arguments, the module invokes test discovery.

Command Line Options

https://docs.python.org/3/library/unittest.html#command-line-options

Test Discovery

https://docs.python.org/3/library/unittest.html#test-discovery

Run the unittest module without arguments:

python -m unittest

TO PROCESS: https://docs.python.org/3/library/unittest.html#test-discovery

Other Subjects

Skipping Tests and Expected Failures

TO PROCESS: https://docs.python.org/3/library/unittest.html#skipping-tests-and-expected-failures

Distinguishing Test Iterations using Subtests

TO PROCESS: https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests

Class and Module Fixtures

TO PROCESS: https://docs.python.org/3/library/unittest.html#class-and-module-fixtures

Mocking

To mock a class and a method of that class:

from unittest.mock import Mock


class SomeClass:
    def __init__(self, state):
        self.state = state

    def some_method(self):
        return self.state


sc = SomeClass('A')
assert 'A' == sc.some_method()

sc_mock = Mock(SomeClass)
sc_mock.some_method = Mock(return_value='blah')

assert 'blah' == sc_mock.some_method()


How to simulate different return values for a mocked function depending on an argument value?

Mocking a Property

https://docs.python.org/3/library/unittest.mock.html#unittest.mock.PropertyMock
from unittest.mock import patch, PropertyMock

class A:
    @property
    def property_a(self):
        return "pa"

with patch('__main__.A.property_a', new_callable=PropertyMock) as mock_property:
    mock_property.return_value = 'mocked pa'
    a = A()
    assert a.property_a == 'mocked pa'

Mocking a Method

from unittest.mock import patch

class A:
    def method_a(self):
        return "ma"

with patch.object(A, 'method_a', return_value='mocked ma') as mock_method:
    a = A()
    assert a.method_a() == 'mocked ma'