another way to write tests

I used unittest in how to make a Python test driven development environment manually to run tests manually before I learned to run them automatically with pytest-watcher.

The unittest library is part of The Python Standard Library and can also be used to write tests. You can think of it as a toolbox with different tools I can use to test code.


preview

I have these tests by the end of the chapter

  1import unittest
  2
  3
  4class TestUnittest(unittest.TestCase):
  5
  6    def test_attributes_and_methods_of_unittest(self):
  7        reality = dir(unittest)
  8        my_expectation = [
  9            'BaseTestSuite', 'FunctionTestCase',
 10            'IsolatedAsyncioTestCase', 'SkipTest',
 11            'TestCase', 'TestLoader', 'TestProgram',
 12            'TestResult', 'TestSuite', 'TextTestResult',
 13            'TextTestRunner', '__all__', '__builtins__',
 14            '__cached__', '__dir__', '__doc__',
 15            '__file__', '__getattr__', '__loader__',
 16            '__name__', '__package__', '__path__',
 17            '__spec__', '__unittest', 'addModuleCleanup',
 18            'case', 'defaultTestLoader', 'doModuleCleanups',
 19            'enterModuleContext', 'expectedFailure',
 20            'installHandler', 'loader', 'main',
 21            'registerResult', 'removeHandler', 'removeResult',
 22            'result', 'runner', 'signals', 'skip', 'skipIf',
 23            'skipUnless', 'suite', 'util'
 24        ]
 25        assert reality == my_expectation
 26        self.assertEqual(reality, my_expectation)
 27
 28    def test_attributes_and_methods_of_unittest_testcase(self):
 29        reality = dir(unittest.TestCase)
 30        my_expectation = [
 31            '__call__', '__class__', '__delattr__',
 32            '__dict__', '__dir__', '__doc__', '__eq__',
 33            '__firstlineno__', '__format__', '__ge__',
 34            '__getattribute__', '__getstate__', '__gt__',
 35            '__hash__', '__init__', '__init_subclass__',
 36            '__le__', '__lt__', '__module__', '__ne__',
 37            '__new__', '__reduce__', '__reduce_ex__',
 38            '__repr__', '__setattr__', '__sizeof__',
 39            '__static_attributes__', '__str__',
 40            '__subclasshook__', '__weakref__',
 41            '_addDuration', '_addExpectedFailure',
 42            '_addUnexpectedSuccess', '_assertNotWarns',
 43            '_baseAssertEqual', '_callCleanup',
 44            '_callSetUp', '_callTearDown', '_callTestMethod',
 45            '_diffThreshold', '_formatMessage',
 46            '_getAssertEqualityFunc', '_tail_type_check',
 47            '_truncateMessage', 'addClassCleanup',
 48            'addCleanup', 'addTypeEqualityFunc',
 49            'assertAlmostEqual', 'assertCountEqual',
 50            'assertDictEqual', 'assertEndsWith',
 51            'assertEqual', 'assertFalse', 'assertGreater',
 52            'assertGreaterEqual', 'assertHasAttr',
 53            'assertIn', 'assertIs', 'assertIsInstance',
 54            'assertIsNone', 'assertIsNot',
 55            'assertIsNotNone', 'assertIsSubclass',
 56            'assertLess', 'assertLessEqual',
 57            'assertListEqual', 'assertLogs',
 58            'assertMultiLineEqual', 'assertNoLogs',
 59            'assertNotAlmostEqual', 'assertNotEndsWith',
 60            'assertNotEqual', 'assertNotHasAttr',
 61            'assertNotIn', 'assertNotIsInstance',
 62            'assertNotIsSubclass', 'assertNotRegex',
 63            'assertNotStartsWith', 'assertRaises',
 64            'assertRaisesRegex', 'assertRegex',
 65            'assertSequenceEqual', 'assertSetEqual',
 66            'assertStartsWith', 'assertTrue',
 67            'assertTupleEqual', 'assertWarns',
 68            'assertWarnsRegex', 'countTestCases',
 69            'debug', 'defaultTestResult',
 70            'doClassCleanups', 'doCleanups',
 71            'enterClassContext', 'enterContext', 'fail',
 72            'failureException', 'id', 'longMessage',
 73            'maxDiff', 'run', 'setUp', 'setUpClass',
 74            'shortDescription', 'skipTest', 'subTest',
 75            'tearDown', 'tearDownClass'
 76        ]
 77        assert reality == my_expectation
 78        self.assertEqual(reality, my_expectation)
 79
 80    def test_assert_is_not(self):
 81        assert None is not False
 82        self.assertIsNot(None, False)
 83
 84    def test_assert_is(self):
 85        assert False is False
 86        self.assertIs(False, False)
 87
 88    def test_assert_not_equal(self):
 89        assert True != 0
 90        self.assertNotEqual(True, 0)
 91
 92    def test_assert_equal(self):
 93        assert 0.0 == 0.0
 94        self.assertEqual(0.0, 0.0)
 95
 96    def test_assert_not_is_instance(self):
 97        assert not isinstance(
 98            unittest.TestCase, unittest.TestCase
 99        )
100        self.assertNotIsInstance(
101            unittest.TestCase, unittest.TestCase
102        )
103
104    def test_assert_is_instance(self):
105        a_class = unittest.TestCase
106        an_instance = a_class()
107
108        assert isinstance(an_instance, a_class)
109        self.assertIsInstance(
110            an_instance, a_class
111        )
112        self.assertIsInstance(
113            self, unittest.TestCase
114        )
115
116    def test_assert_not_is_subclass(self):
117        assert not issubclass(
118            unittest.TestCase, list
119        )
120        self.assertNotIsSubclass(
121            unittest.TestCase, dict
122        )
123
124    def test_assert_is_subclass(self):
125        assert issubclass(unittest.TestCase, object)
126        self.assertIsSubclass(
127            unittest.TestCase, object
128        )
129        self.assertIsSubclass(
130            TestUnittest, unittest.TestCase
131        )
132
133
134# Exceptions seen
135# AssertionError
136# NameError
137# TypeError
138# AttributeError

Questions about unittest

Questions to think about as I go through the chapter


start the project

  • I name this project unittest

  • I open a terminal

  • I change directory to the unittest folder in the pumping_python folder

    cd unittest
    

    the terminal shows

    cd: no such file or directory: unittest
    
  • I use uv to make a directory for the project and initialize it

    uv init unittest
    

    the terminal shows

    Initialized project `unittest`
    at `.../pumping_python/unittest`
    
  • I change directory to unittest

    cd unittest
    

    the terminal shows I am in the unittest folder

    .../pumping_python/unittest
    
  • I make a directory for the tests

    mkdir tests
    
  • I make the tests directory a Python package

    Danger

    use 2 underscores (__) before and after init for __init__.py not _init_.py

    touch tests/__init__.py
    
    New-Item tests/__init__.py
    
  • I use the mv program to change the name of main.py to test_unittest.py and move it to the tests folder

    mv main.py tests/test_unittest.py
    
    Move-Item main.py tests/test_unittest.py
    
  • I open test_unittest.py

  • I delete the text in the file then add the first failing test to test_unittest.py

    1def test_failure():
    2    assert False is True
    
  • I go back to the terminal to make a requirements file for the Python packages I need

    echo "pytest" > requirements.txt
    
  • I add pytest-watcher to the requirements file

    echo "pytest-watcher" >> requirements.txt
    
  • I use uv to install pytest-watcher with the requirements file

    uv add --requirement requirements.txt
    
  • I add the new files and folder to git for tracking

    git add .
    
  • I add a git commit message

    git commit -am 'setup project'
    
  • I use pytest-watcher to run the tests

    uv run pytest-watcher . --now
    

    the terminal is my friend, and shows AssertionError

    ======================== FAILURES ========================
    ______________________ test_failure ______________________
    
        def test_failure():
    >       assert False is True
    E       assert False is True
    
    test_unittest.py:2: AssertionError
    ================ short test summary info =================
    FAILED test_unittest.py::test_failure - assert False is True
    =================== 1 failed in X.YZs ====================
    

    because True is NOT False.

    if the terminal does not show the same error, then check

    • if your tests/__init__.py has two underscores (__) before and after init for __init__.py not _init_.py

    • if you ran echo "pytest-watcher" >> requirements.txt, to add pytest-watcher to the requirements file

    and try uv run pytest-watcher . --now again

  • I add AssertionError to the list of Exceptions seen in test_unittest.py

    1def test_failure():
    2    assert False is True
    3
    4
    5# Exceptions seen
    6# AssertionError
    
  • I change True to False in the assertion

    1def test_failure():
    2    # assert False is True
    3    assert False is False
    4
    5
    6# Exceptions seen
    7# AssertionError
    

    the test passes.


test_attributes_and_methods_of_unittest

I want to see what comes with the unittest module.


RED: make it fail


  • I change test_failure to test_attributes_and_methods_of_unittest in test_unittest.py

    1def test_attributes_and_methods_of_unittest():
    2    reality = dir(unittest)
    3    my_expectation = []
    4    assert reality == my_expectation
    5
    6
    7# Exceptions seen
    

    the terminal is my friend, and shows NameError

    NameError: name 'unittest' is not defined.
                Did you forget to import 'unittest'?
    
  • I add NameError to the list of Exceptions seen

    7# Exceptions seen
    8# AssertionError
    9# NameError
    

GREEN: make it pass


  • I add an import statement for unittest

    1import unittest
    2
    3
    4def test_attributes_and_methods_of_unittest():
    

    the terminal is my friend, and shows AssertionError

    E       AssertionError:
              assert ['BaseTestSui...tLoader', ...]
           == []
    E
    E         Left contains 44 more items,
              first extra item: 'BaseTestSuite'
    E         Use -v to get more diff
    
  • I click in the terminal where the tests are running then press v on the keyboard for pytest-watcher to show me more of the difference between reality and my_expectation and it shows AssertionError

    E         ...Full output truncated (44 lines hidden),
                 use '-vv' to show
    
  • I press w on the keyboard in the terminal where the tests are running, to show the menu for pytest-watcher and it shows

    [pytest-watcher]
    Current runner args: [-v]
    
    Controls:
    > Enter : Invoke test runner
    > r     : reset all runner args
    > c     : change runner args
    > f     : run only failed tests (--lf)
    > p     : drop to pdb on fail (--pdb)
    > v     : increase verbosity (-v)
    > e     : Erase terminal screen
    > q     : quit pytest-watcher
    
  • I press c on the keyboard to change runner args, and the terminal shows

    [pytest-watcher]
    Current runner args: []
    
    Controls:
    > Enter : Invoke test runner
    > r     : reset all runner args
    > c     : change runner args
    > f     : run only failed tests (--lf)
    > p     : drop to pdb on fail (--pdb)
    > v     : increase verbosity (-v)
    > e     : Erase terminal screen
    > q     : quit pytest-watcher
    
    Enter new runner args: -vv
    
  • I press -+v+v on the keyboard then press enter to show the full difference, and the terminal shows AssertionError with the full list.

  • I copy (ctrl/command+c) the values from the terminal and paste (ctrl/command+v) them as my_expectation

     4def test_attributes_and_methods_of_unittest():
     5    reality = dir(unittest)
     6    my_expectation = [
     7        'BaseTestSuite', 'FunctionTestCase',
     8        'IsolatedAsyncioTestCase', 'SkipTest',
     9        'TestCase', 'TestLoader', 'TestProgram',
    10        'TestResult', 'TestSuite', 'TextTestResult',
    11        'TextTestRunner', '__all__', '__builtins__',
    12        '__cached__', '__dir__', '__doc__',
    13        '__file__', '__getattr__', '__loader__',
    14        '__name__', '__package__', '__path__',
    15        '__spec__', '__unittest', 'addModuleCleanup',
    16        'case', 'defaultTestLoader', 'doModuleCleanups',
    17        'enterModuleContext', 'expectedFailure',
    18        'installHandler', 'loader', 'main',
    19        'registerResult', 'removeHandler', 'removeResult',
    20        'result', 'runner', 'signals', 'skip', 'skipIf',
    21        'skipUnless', 'suite', 'util'
    22    ]
    23    assert reality == my_expectation
    24
    25
    26# Exceptions seen
    

    the test passes because when import unittest runs, Python brings in an object (everything in Python is an object) for the unittest module from The Python Standard Library so I can use it in test_unittest.py as unittest.

    This means that there is a file or folder on the computer named unittest that got added when I installed Python.

    Caution

    Your list of attributes and methods may be different depending on your Python version

  • I open a new terminal then make sure I am in classes folder

    cd classes
    
  • I add a git commit message in the new terminal

    git commit -am \
    'add test_attributes_and_methods_of_unittest'
    

test_attributes_and_methods_of_unittest_testcase

One of the names in the list of attributes and methods of unittest is TestCase, this is the class (toolbox) that contains the things I will use to write tests for code.


RED: make it fail


I add a new test for the attributes and methods of TestCase

23    assert reality == my_expectation
24
25
26def test_attributes_and_methods_of_unittest_testcase():
27    reality = dir(unittest.TestCase)
28    my_expectation = []
29    assert reality == my_expectation
30
31
32# Exceptions seen

the terminal is my friend, and shows AssertionError

E       AssertionError: assert
          ['__call__', ...__doc__', ...] == []
E
E         Left contains 108 more items,
          first extra item: '__call__'
E         Use -v to get more diff

GREEN: make it pass


  • I click in the terminal where the tests are running then press v on the keyboard for pytest-watcher to show me more of the difference between reality and my_expectation and it shows AssertionError

    E         ...Full output truncated (108 lines hidden),
                 use '-vv' to show
    
  • I press w on the keyboard in the terminal where the tests are running, to show the menu for pytest-watcher and it shows

    [pytest-watcher]
    Current runner args: [-v]
    
    Controls:
    > Enter : Invoke test runner
    > r     : reset all runner args
    > c     : change runner args
    > f     : run only failed tests (--lf)
    > p     : drop to pdb on fail (--pdb)
    > v     : increase verbosity (-v)
    > e     : Erase terminal screen
    > q     : quit pytest-watcher
    
  • I press c on the keyboard to change runner args, and the terminal shows

    [pytest-watcher]
    Current runner args: []
    
    Controls:
    > Enter : Invoke test runner
    > r     : reset all runner args
    > c     : change runner args
    > f     : run only failed tests (--lf)
    > p     : drop to pdb on fail (--pdb)
    > v     : increase verbosity (-v)
    > e     : Erase terminal screen
    > q     : quit pytest-watcher
    
    Enter new runner args: -vv
    
  • I press -+v+v on the keyboard then press enter to show the full difference, and the terminal shows AssertionError with the entire list.

  • I copy (ctrl/command+c) the values from the terminal and paste (ctrl/command+v) them as my_expectation

     4def test_attributes_and_methods_of_unittest_testcase():
     5    reality = dir(unittest.TestCase)
     6    my_expectation = [
     7        '__call__', '__class__', '__delattr__',
     8        '__dict__', '__dir__', '__doc__', '__eq__',
     9        '__firstlineno__', '__format__', '__ge__',
    10        '__getattribute__', '__getstate__', '__gt__',
    11        '__hash__', '__init__', '__init_subclass__',
    12        '__le__', '__lt__', '__module__', '__ne__',
    13        '__new__', '__reduce__', '__reduce_ex__',
    14        '__repr__', '__setattr__', '__sizeof__',
    15        '__static_attributes__', '__str__',
    16        '__subclasshook__', '__weakref__',
    17        '_addDuration', '_addExpectedFailure',
    18        '_addUnexpectedSuccess', '_assertNotWarns',
    19        '_baseAssertEqual', '_callCleanup',
    20        '_callSetUp', '_callTearDown', '_callTestMethod',
    21        '_diffThreshold', '_formatMessage',
    22        '_getAssertEqualityFunc', '_tail_type_check',
    23        '_truncateMessage', 'addClassCleanup',
    24        'addCleanup', 'addTypeEqualityFunc',
    25        'assertAlmostEqual', 'assertCountEqual',
    26        'assertDictEqual', 'assertEndsWith',
    27        'assertEqual', 'assertFalse', 'assertGreater',
    28        'assertGreaterEqual', 'assertHasAttr',
    29        'assertIn', 'assertIs', 'assertIsInstance',
    30        'assertIsNone', 'assertIsNot',
    31        'assertIsNotNone', 'assertIsSubclass',
    32        'assertLess', 'assertLessEqual',
    33        'assertListEqual', 'assertLogs',
    34        'assertMultiLineEqual', 'assertNoLogs',
    35        'assertNotAlmostEqual', 'assertNotEndsWith',
    36        'assertNotEqual', 'assertNotHasAttr',
    37        'assertNotIn', 'assertNotIsInstance',
    38        'assertNotIsSubclass', 'assertNotRegex',
    39        'assertNotStartsWith', 'assertRaises',
    40        'assertRaisesRegex', 'assertRegex',
    41        'assertSequenceEqual', 'assertSetEqual',
    42        'assertStartsWith', 'assertTrue',
    43        'assertTupleEqual', 'assertWarns',
    44        'assertWarnsRegex', 'countTestCases',
    45        'debug', 'defaultTestResult',
    46        'doClassCleanups', 'doCleanups',
    47        'enterClassContext', 'enterContext', 'fail',
    48        'failureException', 'id', 'longMessage',
    49        'maxDiff', 'run', 'setUp', 'setUpClass',
    50        'shortDescription', 'skipTest', 'subTest',
    51        'tearDown', 'tearDownClass'
    52    ]
    53    assert reality == my_expectation
    54
    55
    56# Exceptions seen
    

REFACTOR: make it better


  • I see names that begin with assert and look like some of the assertions I have written so far.

    assertIsNot

    assert X is not Y

    assertIs

    assert X is Y

    assertNotEqual

    assert X != Y

    assertEqual

    assert X == Y

    assertNotIsInstance

    assert not isinstance(X, Y)

    assertIsInstance

    assert isinstance(X, Y)

    assertNotIsSubclass

    assert not issubclass(X, Y)

    assertIsSubclass

    assert issubclass(X, Y)

  • I type these names below the test as a TODO list to test what I can do with them

    75assert reality == my_expectation
    76
    77
    78'assertIsNot'
    79'assertIs'
    80'assertNotEqual'
    81'assertEqual'
    82'assertNotIsInstance'
    83'assertIsInstance'
    84'assertNotIsSubclass'
    85'assertIsSubclass'
    86
    87
    88# Exceptions seen
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_attributes_and_methods_of_unittest_testcase'
    

test_assert_is_not

RED: make it fail



GREEN: make it pass


  • I change the call to use an instance instead of a class

    78def test_assert_is_not():
    79    # unittest.TestCase.assertIsNot()
    80    unittest.TestCase().assertIsNot()
    81
    82
    83'assertIsNot'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertIsNot() missing
               2 required positional arguments:
               'expr1' and 'expr2'
    

    I no longer need to provide self because it is the instance of the class (unittest.TestCase())

  • I add two things to the call to unittest.TestCase.assertIsNot

    78def test_assert_is_not():
    79    # unittest.TestCase.assertIsNot()
    80    # unittest.TestCase().assertIsNot()
    81    unittest.TestCase().assertIsNot(None, None)
    82
    83
    84'assertIsNot'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: unexpectedly identical: None
    

    because None is None.

  • I change the assertion to make it True

    78def test_assert_is_not():
    79    # unittest.TestCase.assertIsNot()
    80    # unittest.TestCase().assertIsNot()
    81    # unittest.TestCase().assertIsNot(None, None)
    82    unittest.TestCase().assertIsNot(None, False)
    83
    84
    85'assertIsNot'
    

    the test passes.


REFACTOR: make it better


  • I add an assertion to compare it with the assertIsNot method

    78def test_assert_is_not():
    79    # unittest.TestCase.assertIsNot()
    80    # unittest.TestCase().assertIsNot()
    81    # unittest.TestCase().assertIsNot(None, None)
    82    assert None is not None
    83    unittest.TestCase().assertIsNot(None, False)
    84
    85
    86'assertIsNot'
    

    the terminal is my friend, and shows AssertionError

    E       assert None is not None
    
  • I change the assertion to make it True

    78def test_assert_is_not():
    79    # unittest.TestCase.assertIsNot()
    80    # unittest.TestCase().assertIsNot()
    81    # unittest.TestCase().assertIsNot(None, None)
    82    # assert None is not None
    83    assert None is not False
    84    unittest.TestCase().assertIsNot(None, False)
    85
    86
    87'assertIsNot'
    88'assertIs'
    

    the test passes.

  • I remove assertIsNot from the TODO list

    84    unittest.TestCase().assertIsNot(None, False)
    85
    86
    87'assertIs'
    88'assertNotEqual'
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_is_not'
    

I imagine Python follows this path when unittest.TestCase.assertIsNot is called

unittest
└── class TestCase:
    └── def assertIsNot(self, expr1, expr2):
        └── assert expr1 is not expr2

Compare the error message for assertIsNot(None, None) with the one for assert None is not None

AssertionError: unexpectedly identical: None

vs

assert None is not None

Which do you like better?


test_assert_is

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for the assertIs method

    78def test_assert_is_not():
    79    # unittest.TestCase.assertIsNot()
    80    # unittest.TestCase().assertIsNot()
    81    # unittest.TestCase().assertIsNot(None, None)
    82    # assert None is not None
    83    assert None is not False
    84    unittest.TestCase().assertIsNot(None, False)
    85
    86
    87def test_assert_is():
    88    assert False is True
    89
    90
    91'assertIs'
    

    the terminal is my friend, and shows AssertionError

    E       assert False is True
    

GREEN: make it pass


I change the assertion to make it True

87def test_assert_is():
88    # assert False is True
89    assert False is False
90
91
92'assertIs'

the test passes.


REFACTOR: make it better


  • I add a call to the assertIs method

    87def test_assert_is():
    88    # assert False is True
    89    assert False is False
    90    unittest.TestCase.assertIs()
    91
    92
    93'assertIs'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertIs() missing
               3 required positional arguments:
               'self', 'expr1', and 'expr2'
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I change the call to use an instance instead of a class

    87def test_assert_is():
    88    # assert False is True
    89    assert False is False
    90    # unittest.TestCase.assertIs()
    91    unittest.TestCase().assertIs()
    92
    93
    94'assertIs'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertIs() missing
               2 required positional arguments:
               'expr1' and 'expr2'
    

    I no longer need to provide self because it is the instance of the class (unittest.TestCase())

  • I add two things to the call to unittest.TestCase.assertIs

    87def test_assert_is():
    88    # assert False is True
    89    assert False is False
    90    # unittest.TestCase.assertIs()
    91    # unittest.TestCase().assertIs()
    92    unittest.TestCase().assertIs(False, True)
    93
    94
    95'assertIs'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: False is not True
    

    because False is not True.

  • I change the assertion to make it True

    87def test_assert_is():
    88    # assert False is True
    89    assert False is False
    90    # unittest.TestCase.assertIs()
    91    # unittest.TestCase().assertIs()
    92    # unittest.TestCase().assertIs(False, True)
    93    unittest.TestCase().assertIs(False, False)
    94
    95
    96'assertIs'
    97'assertNotEqual'
    

    the test passes.

  • I remove assertIs from the TODO list

    93    unittest.TestCase().assertIs(False, False)
    94
    95
    96'assertNotEqual'
    97'assertEqual'
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_is'
    

I imagine Python follows this path when unittest.TestCase.assertIs is called

unittest
└── class TestCase:
    └── def assertIs(self, expr1, expr2):
        └── assert expr1 is expr2

Compare the error message for assertIs(False, True) with the one for assert False is True

AssertionError: False is not True

vs

E       assert False is True

test_assert_not_equal

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for assertNotEqual

     87def test_assert_is():
     88    # assert False is True
     89    assert False is False
     90    # unittest.TestCase.assertIs()
     91    # unittest.TestCase().assertIs()
     92    # unittest.TestCase().assertIs(False, True)
     93    unittest.TestCase().assertIs(False, False)
     94
     95
     96def test_assert_not_equal():
     97    unittest.TestCase().assertNotEqual()
     98
     99
    100'assertNotEqual'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertNotEqual() missing
               2 required positional arguments:
               'first', and 'second'
    

    the definition of the assertNotEqual method of the TestCase class of the unittest library (unittest.TestCase.assertNotEqual) has two required positional arguments (first and second).


GREEN: make it pass


  • I add two things to the call to unittest.TestCase.assertNotEqual

     96def test_assert_not_equal():
     97    # unittest.TestCase().assertNotEqual()
     98    unittest.TestCase().assertNotEqual(True, True)
     99
    100
    101'assertNotEqual'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: True == True
    

    because True is True.

  • I change the assertion to make it True

     96def test_assert_not_equal():
     97    # unittest.TestCase().assertNotEqual()
     98    # unittest.TestCase().assertNotEqual(True, True)
     99    unittest.TestCase().assertNotEqual(True, 0)
    100
    101
    102'assertNotEqual'
    

    the test passes.


REFACTOR: make it better


  • I add an assertion to compare it with the assertNotEqual method

     96def test_assert_not_equal():
     97    # unittest.TestCase().assertNotEqual()
     98    # unittest.TestCase().assertNotEqual(True, True)
     99    assert True != True
    100    unittest.TestCase().assertNotEqual(True, 0)
    101
    102
    103'assertNotEqual'
    

    the terminal is my friend, and shows AssertionError

    E       assert True != True
    
  • I change the assertion to make it True

     96def test_assert_not_equal():
     97    # unittest.TestCase().assertNotEqual()
     98    # unittest.TestCase().assertNotEqual(True, True)
     99    # assert True != True
    100    assert True != 0
    101    unittest.TestCase().assertNotEqual(True, 0)
    102
    103
    104'assertNotEqual'
    105'assertEqual'
    

    the test passes.

  • I remove assertNotEqual from the TODO list

    101    unittest.TestCase().assertNotEqual(True, 0)
    102
    103
    104'assertEqual'
    105'assertNotIsInstance'
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_not_equal'
    

I imagine Python follows this path when unittest.TestCase.assertNotEqual is called

unittest
└── class TestCase:
    └── def assertNotEqual(self, first, second):
        └── assert first != second

Compare the error message for assertNotEqual(True, True) with the one for assert True != True

AssertionError: True == True

vs

E       assert True != True

test_assert_equal

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for the assertEqual method

     96def test_assert_not_equal():
     97    # unittest.TestCase().assertNotEqual()
     98    # unittest.TestCase().assertNotEqual(True, True)
     99    # assert True != True
    100    assert True != 0
    101    unittest.TestCase().assertNotEqual(True, 0)
    102
    103
    104def test_assert_equal():
    105    assert 0.0 == '0.0'
    106
    107
    108'assertEqual'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: assert 0.0 == '0.0'
    

GREEN: make it pass


I change the assertion to make it True

104def test_assert_equal():
105    # assert 0.0 == '0.0'
106    assert 0.0 == 0.0
107
108
109'assertEqual'

the test passes.


REFACTOR: make it better


  • I add a call to the assertEqual method

    104def test_assert_equal():
    105    # assert 0.0 == '0.0'
    106    assert 0.0 == 0.0
    107    unittest.TestCase().assertEqual(0.0, '0.0')
    108
    109
    110'assertEqual'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 0.0 != '0.0'
    

    because a float is not a string.

  • I change the assertion to make it True

    104def test_assert_equal():
    105    # assert 0.0 == '0.0'
    106    assert 0.0 == 0.0
    107    # unittest.TestCase().assertEqual(0.0, '0.0')
    108    unittest.TestCase().assertEqual(0.0, 0.0)
    109
    110
    111'assertEqual'
    112'assertNotIsInstance'
    

    the test passes.

  • I remove the commented lines and assertEqual from the TODO list

    108    unittest.TestCase().assertEqual(0.0, 0.0)
    109
    110
    111'assertNotIsInstance'
    112'assertIsInstance'
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_equal'
    

I imagine Python follows this path when unittest.TestCase.assertEqual is called

unittest
└── class TestCase:
    └── def assertEqual(self, first, second):
        └── assert first is second

Compare the error message for assertEqual(0.0, '0.0') with the one for assert 0.0 == '0.0'

AssertionError: 0.0 != '0.0'

vs

AssertionError: assert 0.0 == '0.0'

test_assert_not_is_instance

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for the assertNotIsInstance method

    104def test_assert_equal():
    105    # assert 0.0 == '0.0'
    106    assert 0.0 == 0.0
    107    # unittest.TestCase().assertEqual(0.0, '0.0')
    108    unittest.TestCase().assertEqual(0.0, 0.0)
    109
    110
    111def test_assert_not_is_instance():
    112    unittest.TestCase.assertNotIsInstance()
    113
    114
    115'assertNotIsInstance'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertNotIsInstance() missing
               3 required positional arguments:
               'self', 'obj', and 'cls'
    

GREEN: make it pass


  • I change the call to use an instance instead of a class

    111def test_assert_not_is_instance():
    112    # unittest.TestCase.assertNotIsInstance()
    113    unittest.TestCase().assertNotIsInstance()
    114
    115
    116'assertNotIsInstance'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertNotIsInstance()
               missing 2 required positional arguments:
               'obj' and 'cls'
    
  • I add two things to the call to unittest.TestCase.assertNotIsInstance

    111def test_assert_not_is_instance():
    112    # unittest.TestCase.assertNotIsInstance()
    113    # unittest.TestCase().assertNotIsInstance()
    114    unittest.TestCase().assertNotIsInstance(
    115        unittest.TestCase(), unittest.TestCase
    116    )
    117
    118
    119'assertNotIsInstance'
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <unittest.case.TestCase testMethod=runTest>
        is an instance of
        <class 'unittest.case.TestCase'>
    
  • I change the assertion to make it True

    111def test_assert_not_is_instance():
    112    # unittest.TestCase.assertNotIsInstance()
    113    # unittest.TestCase().assertNotIsInstance()
    114    unittest.TestCase().assertNotIsInstance(
    115        # unittest.TestCase(), unittest.TestCase
    116        unittest.TestCase, unittest.TestCase
    117    )
    118
    119
    120'assertNotIsInstance'
    

    the test passes because a class is not an instance of itself.


REFACTOR: make it better


  • I add an assertion to compare it with the assertNotIsInstance method

    111def test_assert_not_is_instance():
    112    # unittest.TestCase.assertNotIsInstance()
    113    # unittest.TestCase().assertNotIsInstance()
    114    assert not isinstance(
    115        unittest.TestCase(), unittest.TestCase
    116    )
    117    unittest.TestCase().assertNotIsInstance(
    118        # unittest.TestCase(), unittest.TestCase
    119        unittest.TestCase, unittest.TestCase
    120    )
    121
    122
    123'assertNotIsInstance'
    

    the terminal is my friend, and shows AssertionError

    E       AssertionError: assert not True
    
  • I change the assertion to make it True

    111def test_assert_not_is_instance():
    112    # unittest.TestCase.assertNotIsInstance()
    113    # unittest.TestCase().assertNotIsInstance()
    114    assert not isinstance(
    115        # unittest.TestCase(), unittest.TestCase
    116        unittest.TestCase, unittest.TestCase
    117    )
    118    unittest.TestCase().assertNotIsInstance(
    119        # unittest.TestCase(), unittest.TestCase
    120        unittest.TestCase, unittest.TestCase
    121    )
    122
    123
    124'assertNotIsInstance'
    125'assertIsInstance'
    

    the test passes.

  • I remove assertNotIsInstance from the TODO list

    118    unittest.TestCase().assertNotIsInstance(
    119        # unittest.TestCase(), unittest.TestCase
    120        unittest.TestCase, unittest.TestCase
    121    )
    122
    123
    124'assertIsInstance'
    125'assertNotIsSubclass'
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_not_is_instance'
    

I imagine Python follows this path when unittest.TestCase.assertNotIsInstance is called

unittest
└── class TestCase:
    └── def assertNotIsInstance(self, obj, cls):
        └── assert not isinstance(obj, cls)

Compare the error message for unittest.TestCase().assertNotIsInstance(unittest.TestCase(), unittest.TestCase) with the one for assert not isinstance(unittest.TestCase(), unittest.TestCase)

AssertionError:
    <unittest.case.TestCase testMethod=runTest>
    is an instance of
    <class 'unittest.case.TestCase'>

vs

AssertionError: assert not True

test_assert_is_instance

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for assertIsInstance

    118    unittest.TestCase().assertNotIsInstance(
    119        # unittest.TestCase(), unittest.TestCase
    120        unittest.TestCase, unittest.TestCase
    121    )
    122
    123
    124def test_assert_is_instance():
    125    unittest.TestCase.assertIsInstance()
    126
    127
    128'assertIsInstance'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertIsInstance() missing
               3 required positional arguments:
               'self', 'obj', and 'cls'
    

GREEN: make it pass


  • I change the call to use an instance instead of a class

    124def test_assert_is_instance():
    125    # unittest.TestCase.assertIsInstance()
    126    unittest.TestCase().assertIsInstance()
    127
    128
    129'assertIsInstance'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertIsInstance()
               missing 2 required positional arguments:
               'obj' and 'cls'
    
  • I add two things to the call to unittest.TestCase.assertIsInstance

    124def test_assert_is_instance():
    125    # unittest.TestCase.assertIsInstance()
    126    # unittest.TestCase().assertIsInstance()
    127    unittest.TestCase().assertIsInstance(
    128        unittest.TestCase, unittest.TestCase
    129    )
    130
    131
    132'assertIsInstance'
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <class 'unittest.case.TestCase'>
        is not an instance of
        <class 'unittest.case.TestCase'>
    

    because a class is not an instance of itself.

  • I change the assertion to make it True

    124def test_assert_is_instance():
    125    # unittest.TestCase.assertIsInstance()
    126    # unittest.TestCase().assertIsInstance()
    127    unittest.TestCase().assertIsInstance(
    128        # unittest.TestCase, unittest.TestCase
    129        unittest.TestCase(), unittest.TestCase
    130    )
    131
    132
    133'assertIsInstance'
    

    the test passes.


REFACTOR: make it better


  • I add an assertion to compare it with the assertIsInstance method

    124def test_assert_is_instance():
    125    # unittest.TestCase.assertIsInstance()
    126    # unittest.TestCase().assertIsInstance()
    127    assert isinstance(
    128        unittest.TestCase, unittest.TestCase
    129    )
    130    unittest.TestCase().assertIsInstance(
    131        # unittest.TestCase, unittest.TestCase
    132        unittest.TestCase(), unittest.TestCase
    133    )
    134
    135
    136'assertIsInstance'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: assert False
    
  • I change the assertion to make it True

    124def test_assert_is_instance():
    125    # unittest.TestCase.assertIsInstance()
    126    # unittest.TestCase().assertIsInstance()
    127    assert isinstance(
    128        # unittest.TestCase, unittest.TestCase
    129        unittest.TestCase(), unittest.TestCase
    130    )
    131    unittest.TestCase().assertIsInstance(
    132        # unittest.TestCase, unittest.TestCase
    133        unittest.TestCase(), unittest.TestCase
    134    )
    135
    136
    137'assertIsInstance'
    

    the test passes.

  • I add variables

    124def test_assert_is_instance():
    125    a_class = unittest.TestCase
    126    an_instance = a_class()
    127    # unittest.TestCase.assertIsInstance()
    128    # unittest.TestCase().assertIsInstance()
    129    assert isinstance(
    130        # unittest.TestCase, unittest.TestCase
    131        unittest.TestCase(), unittest.TestCase
    132    )
    133    unittest.TestCase().assertIsInstance(
    134        # unittest.TestCase, unittest.TestCase
    135        unittest.TestCase(), unittest.TestCase
    136    )
    137
    138
    139'assertIsInstance'
    140'assertNotIsSubclass'
    
  • I use the variables to remove repetition of unittest.TestCase and unittest.TestCase()

    124def test_assert_is_instance():
    125    a_class = unittest.TestCase
    126    an_instance = a_class()
    127    # unittest.TestCase.assertIsInstance()
    128    # unittest.TestCase().assertIsInstance()
    129    assert isinstance(
    130        # unittest.TestCase, unittest.TestCase
    131        # unittest.TestCase(), unittest.TestCase
    132        an_instance, a_class
    133    )
    134    unittest.TestCase().assertIsInstance(
    135        # unittest.TestCase, unittest.TestCase
    136        # unittest.TestCase(), unittest.TestCase
    137        an_instance, a_class
    138    )
    139
    140
    141'assertIsInstance'
    

    the test is still green.

  • I remove assertIsInstance from the TODO list

    134    unittest.TestCase().assertIsInstance(
    135        # unittest.TestCase, unittest.TestCase
    136        # unittest.TestCase(), unittest.TestCase
    137        an_instance, a_class
    138    )
    139
    140
    141'assertNotIsSubclass'
    142'assertIsSubclass'
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_is_instance'
    

I imagine Python follows this path when unittest.TestCase.assertIsInstance is called

unittest
└── class TestCase:
    └── def assertIsInstance(self, obj, cls):
        └── assert not isinstance(obj, cls)

Compare the error message for unittest.TestCase().assertIsInstance(unittest.TestCase, unittest.TestCase) with the one for assert isinstance(unittest.TestCase, unittest.TestCase)

AssertionError:
    <class 'unittest.case.TestCase'>
    is not an instance of
    <class 'unittest.case.TestCase'>

vs

AssertionError: assert False

test_assert_not_is_subclass

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for assertNotIsSubclass

    134    unittest.TestCase().assertIsInstance(
    135        # unittest.TestCase, unittest.TestCase
    136        # unittest.TestCase(), unittest.TestCase
    137        an_instance, a_class
    138    )
    139
    140
    141def test_assert_not_is_subclass():
    142    unittest.TestCase().assertNotIsSubclass()
    143
    144
    145'assertNotIsSubclass'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertNotIsSubclass() missing
               2 required positional arguments:
               'cls', and 'superclass'
    

GREEN: make it pass


  • I add two things to the call to unittest.TestCase.assertNotIsSubclass

    141def test_assert_not_is_subclass():
    142    # unittest.TestCase().assertNotIsSubclass()
    143    unittest.TestCase().assertNotIsSubclass(
    144        unittest.TestCase(), object
    145    )
    146
    147
    148'assertNotIsSubclass'
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <unittest.case.TestCase testMethod=runTest>
        is not a class
    

    because an instance is not a class.

  • I change the assertion to use a class

    141def test_assert_not_is_subclass():
    142    # unittest.TestCase().assertNotIsSubclass()
    143    unittest.TestCase().assertNotIsSubclass(
    144        # unittest.TestCase(), object
    145        unittest.TestCase, object
    146    )
    147
    148
    149'assertNotIsSubclass'
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <class 'unittest.case.TestCase'>
        is a subclass of <class 'object'>
    

    because all classes inherit from ‘object’.

  • I change the assertion to make it True

    141def test_assert_not_is_subclass():
    142    # unittest.TestCase().assertNotIsSubclass()
    143    unittest.TestCase().assertNotIsSubclass(
    144        # unittest.TestCase(), object
    145        # unittest.TestCase, object
    146        unittest.TestCase, dict
    147    )
    148
    149
    150'assertNotIsSubclass'
    

    the test passes because the unittest.TestCase class is not a subclass of the dict class (the class for dictionaries).


REFACTOR: make it better


  • I add an assertion to compare it with the assertNotIsSubclass method

    141def test_assert_not_is_subclass():
    142    # unittest.TestCase().assertNotIsSubclass()
    143    assert not issubclass(
    144        unittest.TestCase, object
    145    )
    146    unittest.TestCase().assertNotIsSubclass(
    147        # unittest.TestCase(), object
    148        # unittest.TestCase, object
    149        unittest.TestCase, dict
    150    )
    151
    152
    153'assertNotIsSubclass'
    

    the terminal is my friend, and shows AssertionError

    E       AssertionError: assert not True
    
  • I change the assertion to make it True

    141def test_assert_not_is_subclass():
    142    # unittest.TestCase().assertNotIsSubclass()
    143    assert not issubclass(
    144        # unittest.TestCase, object
    145        unittest.TestCase, list
    146    )
    147    unittest.TestCase().assertNotIsSubclass(
    148        # unittest.TestCase(), object
    149        # unittest.TestCase, object
    150        unittest.TestCase, dict
    151    )
    152
    153
    154'assertNotIsSubclass'
    155'assertIsSubclass'
    

    the test passes because the unittest.TestCase class is not a subclass of the list class (the class for lists).

  • I remove assertNotIsSubclass from the TODO list

    147    unittest.TestCase().assertNotIsSubclass(
    148        # unittest.TestCase(), object
    149        # unittest.TestCase, object
    150        unittest.TestCase, dict
    151    )
    152
    153
    154'assertIsSubclass'
    155
    156
    157# Exceptions seen
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_not_is_subclass'
    

I imagine Python follows this path when unittest.TestCase.assertNotIsSubclass is called

unittest
└── class TestCase:
    └── def assertNotIsSubclass(self, cls, superclass):
        └── assert not issubclass(cls, superclass)

Compare the error message for unittest.TestCase().assertNotIsSubclass(unittest.TestCase, object) with the one for assert not issubclass(unittest.TestCase, object)

AssertionError:
    <class 'unittest.case.TestCase'>
    is a subclass of <class 'object'>

vs

AssertionError: assert not True

test_assert_is_subclass

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test for the assertIsSubclass method

    147    unittest.TestCase().assertNotIsSubclass(
    148        # unittest.TestCase(), object
    149        # unittest.TestCase, object
    150        unittest.TestCase, dict
    151    )
    152
    153
    154def test_assert_is_subclass():
    155    assert issubclass(unittest.TestCase(), set)
    156
    157
    158'assertIsSubclass'
    

    the terminal is my friend, and shows TypeError

    TypeError: issubclass() arg 1 must be a class
    

GREEN: make it pass


  • I change the instance to a class

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    assert issubclass(unittest.TestCase, set)
    157
    158
    159'assertIsSubclass'
    

    the terminal is my friend, and shows AssertionError

    AssertionError: assert False
    
  • I change the assertion to make it True

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    # assert issubclass(unittest.TestCase, set)
    157    assert issubclass(unittest.TestCase, object)
    158
    159
    160'assertIsSubclass'
    

    the test passes.

  • I add a call to assertIsSubclass

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    # assert issubclass(unittest.TestCase, set)
    157    assert issubclass(unittest.TestCase, object)
    158    unittest.TestCase.assertIsSubclass()
    159
    160
    161'assertIsSubclass'
    

    the terminal is my friend, and shows TypeError

    TypeError: TestCase.assertIsSubclass()
               missing 3 required positional arguments:
               'self', 'cls', and 'superclass'
    
  • I change the call to use an instance instead of a class, then add two things to the parentheses

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    # assert issubclass(unittest.TestCase, set)
    157    assert issubclass(unittest.TestCase, object)
    158    # unittest.TestCase.assertIsSubclass()
    159    unittest.TestCase().assertIsSubclass(
    160        unittest.TestCase(), set
    161    )
    162
    163
    164'assertIsSubclass'
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <unittest.case.TestCase testMethod=runTest>
        is not a class
    

    because an instance is not a class.

  • I change the instance to a class

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    # assert issubclass(unittest.TestCase, set)
    157    assert issubclass(unittest.TestCase, object)
    158    # unittest.TestCase.assertIsSubclass()
    159    unittest.TestCase().assertIsSubclass(
    160        # unittest.TestCase(), set
    161        unittest.TestCase, set
    162    )
    163
    164
    165'assertIsSubclass'
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <class 'unittest.case.TestCase'>
        is not a subclass of <class 'set'>
    
  • I change the assertion to make it True

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    # assert issubclass(unittest.TestCase, set)
    157    assert issubclass(unittest.TestCase, object)
    158    # unittest.TestCase.assertIsSubclass()
    159    unittest.TestCase().assertIsSubclass(
    160        # unittest.TestCase(), set
    161        # unittest.TestCase, set
    162        unittest.TestCase, object
    163    )
    164
    165
    166'assertIsSubclass'
    167
    168
    169# Exceptions seen
    

    the test passes because all classes inherit from ‘object’.


REFACTOR: make it better


  • I remove assertIsSubclass from the TODO list

    154def test_assert_is_subclass():
    155    # assert issubclass(unittest.TestCase(), set)
    156    # assert issubclass(unittest.TestCase, set)
    157    assert issubclass(unittest.TestCase, object)
    158    # unittest.TestCase.assertIsSubclass()
    159    unittest.TestCase().assertIsSubclass(
    160        # unittest.TestCase(), set
    161        # unittest.TestCase, set
    162        unittest.TestCase, object
    163    )
    164
    165
    166# Exceptions seen
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_assert_is_subclass'
    

I imagine Python follows this path when unittest.TestCase.assertIsSubclass is called

unittest
└── class TestCase:
    └── def assertIsSubclass(self, cls, superclass):
        └── assert not issubclass(cls, superclass)

Compare the error message for unittest.TestCase().assertIsSubclass(unittest.TestCase, tuple) with the one for assert issubclass(unittest.TestCase, set)

AssertionError:
    <class 'unittest.case.TestCase'>
    is not a subclass of <class 'tuple'>

vs

AssertionError: assert False

Which of the error messages in this chapter do you like better?


extract TOOLBOX variable

I make an instance of the unittest.TestCase class to use its assert methods in every test. I can use a variable to remove repetition of that process (unittest.TestCase()) from every test.

  • I add a variable for unittest.TestCase() at the top of the file

    1import unittest
    2
    3
    4TOOLBOX = unittest.TestCase()
    5
    6
    7def test_attributes_and_methods_of_unittest():
    
  • I use the variable for unittest.TestCase() in test_assert_is_not

    81def test_assert_is_not():
    82    # unittest.TestCase.assertIsNot()
    83    # unittest.TestCase().assertIsNot()
    84    # unittest.TestCase().assertIsNot(None, None)
    85    # assert None is not None
    86    assert None is not False
    87    # unittest.TestCase().assertIsNot(None, False)
    88    TOOLBOX.assertIsNot(None, False)
    89
    90
    91def test_assert_is():
    

    the test is still green.

  • I remove the commented lines from test_assert_is_not

    81def test_assert_is_not():
    82    assert None is not False
    83    TOOLBOX.assertIsNot(None, False)
    84
    85
    86def test_assert_is():
    
  • I use the variable for unittest.TestCase() in test_assert_is

    86def test_assert_is():
    87    # assert False is True
    88    assert False is False
    89    # unittest.TestCase.assertIs()
    90    # unittest.TestCase().assertIs()
    91    # unittest.TestCase().assertIs(False, True)
    92    # unittest.TestCase().assertIs(False, False)
    93    TOOLBOX.assertIs(False, False)
    94
    95
    96def test_assert_not_equal():
    

    still green.

  • I remove the commented lines from test_assert_is

    86def test_assert_is():
    87    assert False is False
    88    TOOLBOX.assertIs(False, False)
    89
    90
    91def test_assert_not_equal():
    
  • I use the variable for unittest.TestCase() in test_assert_not_equal

     91def test_assert_not_equal():
     92    # unittest.TestCase().assertNotEqual()
     93    # unittest.TestCase().assertNotEqual(True, True)
     94    # assert True != True
     95    assert True != 0
     96    # unittest.TestCase().assertNotEqual(True, 0)
     97    TOOLBOX.assertNotEqual(True, 0)
     98
     99
    100def test_assert_equal():
    

    green.

  • I remove the commented lines from test_assert_not_equal

    91def test_assert_not_equal():
    92    assert True != 0
    93    TOOLBOX.assertNotEqual(True, 0)
    94
    95
    96def test_assert_equal():
    
  • I use the variable for unittest.TestCase() in test_assert_equal

     96def test_assert_equal():
     97    # assert 0.0 == '0.0'
     98    assert 0.0 == 0.0
     99    # unittest.TestCase().assertEqual(0.0, '0.0')
    100    # unittest.TestCase().assertEqual(0.0, 0.0)
    101    TOOLBOX.assertEqual(0.0, 0.0)
    102
    103
    104def test_assert_not_is_instance():
    

    still green.

  • I remove the commented lines from test_assert_equal

     96def test_assert_equal():
     97    assert 0.0 == 0.0
     98    TOOLBOX.assertEqual(0.0, 0.0)
     99
    100
    101def test_assert_not_is_instance():
    
  • I use the variable for unittest.TestCase() in test_assert_not_is_instance

    101def test_assert_not_is_instance():
    102    # unittest.TestCase.assertNotIsInstance()
    103    # unittest.TestCase().assertNotIsInstance()
    104    assert not isinstance(
    105        # unittest.TestCase(), unittest.TestCase
    106        unittest.TestCase, unittest.TestCase
    107    )
    108    # unittest.TestCase().assertNotIsInstance(
    109    TOOLBOX.assertNotIsInstance(
    110        # unittest.TestCase(), unittest.TestCase
    111        unittest.TestCase, unittest.TestCase
    112    )
    113
    114
    115def test_assert_is_instance():
    

    the test is still green.

  • I remove the commented lines from test_assert_not_is_instance

    101def test_assert_not_is_instance():
    102    assert not isinstance(
    103        unittest.TestCase, unittest.TestCase
    104    )
    105    TOOLBOX.assertNotIsInstance(
    106        unittest.TestCase, unittest.TestCase
    107    )
    108
    109
    110def test_assert_is_instance():
    
  • I use the variable for unittest.TestCase() in test_assert_is_instance

    110def test_assert_is_instance():
    111    a_class = unittest.TestCase
    112    an_instance = a_class()
    113    # unittest.TestCase.assertIsInstance()
    114    # unittest.TestCase().assertIsInstance()
    115    assert isinstance(
    116        # unittest.TestCase, unittest.TestCase
    117        # unittest.TestCase(), unittest.TestCase
    118        an_instance, a_class
    119    )
    120    # unittest.TestCase().assertIsInstance(
    121    TOOLBOX.assertIsInstance(
    122        # unittest.TestCase, unittest.TestCase
    123        # unittest.TestCase(), unittest.TestCase
    124        an_instance, a_class
    125    )
    126
    127
    128def test_assert_not_is_subclass():
    

    still green.

  • I remove the commented lines from test_assert_is_instance

    110def test_assert_is_instance():
    111    a_class = unittest.TestCase
    112    an_instance = a_class()
    113
    114    assert isinstance(an_instance, a_class)
    115    TOOLBOX.assertIsInstance(
    116        an_instance, a_class
    117    )
    118
    119
    120def test_assert_not_is_subclass():
    
  • I use the variable for unittest.TestCase() in test_assert_not_is_subclass

    120def test_assert_not_is_subclass():
    121    # unittest.TestCase().assertNotIsSubclass()
    122    assert not issubclass(
    123        # unittest.TestCase, object
    124        unittest.TestCase, list
    125    )
    126    # unittest.TestCase().assertNotIsSubclass(
    127    TOOLBOX.assertNotIsSubclass(
    128        # unittest.TestCase(), object
    129        # unittest.TestCase, object
    130        unittest.TestCase, dict
    131    )
    132
    133
    134def test_assert_is_subclass():
    

    green.

  • I remove the commented lines from test_assert_not_is_subclass

    120def test_assert_not_is_subclass():
    121    assert not issubclass(
    122        unittest.TestCase, list
    123    )
    124    TOOLBOX.assertNotIsSubclass(
    125        unittest.TestCase, dict
    126    )
    127
    128
    129def test_assert_is_subclass():
    
  • I use the variable for unittest.TestCase() in test_assert_is_subclass

    129def test_assert_is_subclass():
    130    # assert issubclass(unittest.TestCase(), set)
    131    # assert issubclass(unittest.TestCase, set)
    132    assert issubclass(unittest.TestCase, object)
    133    # unittest.TestCase.assertIsSubclass()
    134    # unittest.TestCase().assertIsSubclass(
    135    TOOLBOX.assertIsSubclass(
    136        # unittest.TestCase(), set
    137        # unittest.TestCase, set
    138        unittest.TestCase, object
    139    )
    140
    141
    142# Exceptions seen
    

    still green.

  • I remove the commented lines from test_assert_is_subclass

    129def test_assert_is_subclass():
    130    assert issubclass(unittest.TestCase, object)
    131    TOOLBOX.assertIsSubclass(
    132        unittest.TestCase, object
    133    )
    134
    135
    136# Exceptions seen
    
  • I add a git commit message in the other terminal

    git commit -am \
    'extract TOOLBOX variable'
    

The unittest.TestCase() instance is now made once then used in every test for its assert methods.

The problem with this solution is that anyone reading it has to know what the TOOLBOX variable points to at the beginning of the file to understand why the calls work.


extract TestUnittest class

I can put the test functions together in a class since they are related.


RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a class named Unittest

     4TOOLBOX = unittest.TestCase()
     5
     6
     7class Unittest(object):
     8
     9    def test_failure():
    10        TOOLBOX.assertEqual(True, False)
    11
    12
    13def test_attributes_and_methods_of_unittest():
    

    this is a problem. I expect TOOLBOX.assertEqual(True, False) to fail since True is not equal to False

  • I add Test to the name of the class

     4TOOLBOX = unittest.TestCase()
     5
     6
     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    def test_failure():
    

    the terminal is my friend, and shows TypeError

    TypeError: TestUnittest.test_failure() takes 0
               positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.


GREEN: make it pass


  • I add the staticmethod decorator to test_failure since I can use it if I do not want to add self to the method definition. This way I do not send more information than what the method needs when it does not use anything in the class

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    @staticmethod
    11    def test_failure():
    12        TOOLBOX.assertEqual(True, False)
    13
    14
    15def test_attributes_and_methods_of_unittest():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: True != False
    
  • I change False to True in the assertion

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    @staticmethod
    11    def test_failure():
    12        # TOOLBOX.assertEqual(True, False)
    13        TOOLBOX.assertEqual(True, True)
    14
    15
    16def test_attributes_and_methods_of_unittest():
    

    the test passes.


REFACTOR: make it better


  • I move test_attributes_and_methods_of_unittest to replace test_failure As a method of the TestUnittest class

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    def test_attributes_and_methods_of_unittest():
    11        reality = dir(unittest)
    12        my_expectation = [
    13            'BaseTestSuite', 'FunctionTestCase',
    14            'IsolatedAsyncioTestCase', 'SkipTest',
    15            ...
    

    Caution

    Indentation matters in Python. It is how it knows what blocks belong to what function/method, class or module

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_attributes_and_methods_of_unittest()
        takes 0 positional arguments but 1 was given
    
  • I add the staticmethod decorator to test_attributes_and_methods_of_unittest

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    @staticmethod
    11    def test_attributes_and_methods_of_unittest():
    

    the test passes.

  • I add a call to the assertNotEqual method

    30        assert reality == my_expectation
    31        TOOLBOX.assertNotEqual(reality, my_expectation)
    32
    33
    34def test_attributes_and_methods_of_unittest_testcase():
    

    the terminal is my friend, and shows AssertionError.

  • I change assertNotEqual to assertEqual

    30        assert reality == my_expectation
    31        # TOOLBOX.assertNotEqual(reality, my_expectation)
    32        TOOLBOX.assertEqual(reality, my_expectation)
    33
    34
    35def test_attributes_and_methods_of_unittest_testcase():
    

    the test passes.

  • I move test_attributes_and_methods_of_unittest_testcase to make it a method of the TestUnittest class

    32        TOOLBOX.assertEqual(reality, my_expectation)
    33
    34    def test_attributes_and_methods_of_unittest_testcase():
    35        reality = dir(unittest.TestCase)
    36        my_expectation = [
    37            '__call__', '__class__', '__delattr__',
    38            ...
    

    the terminal shows TypeError

    TypeError:
        TestUnittest.test_attributes_and_methods_of_unittest_testcase()
        takes 0 positional arguments but 1 was given
    
  • I add the staticmethod decorator to test_attributes_and_methods_of_unittest_testcase

    32        TOOLBOX.assertEqual(reality, my_expectation)
    33
    34    @staticmethod
    35    def test_attributes_and_methods_of_unittest_testcase():
    

    the test passes.

  • I add a call to the assertNotEqual method

    84        assert reality == my_expectation
    85        TOOLBOX.assertNotEqual(reality, my_expectation)
    86
    87
    88def test_assert_is_not():
    

    the terminal is my friend, and shows AssertionError.

  • I change assertNotEqual to assertEqual

    84        assert reality == my_expectation
    85        # TOOLBOX.assertNotEqual(reality, my_expectation)
    86        TOOLBOX.assertEqual(reality, my_expectation)
    87
    88
    89def test_assert_is_not():
    

    the test passes.

  • I indent (move with four spaces) test_assert_is_not to make it a method of the TestUnittest class

    86        TOOLBOX.assertEqual(reality, my_expectation)
    87
    88    def test_assert_is_not():
    89        assert None is not False
    90        TOOLBOX.assertIsNot(None, False)
    91
    92
    93def test_assert_is():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_is_not()
        takes 0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add the staticmethod decorator to test_assert_is_not

    86        TOOLBOX.assertEqual(reality, my_expectation)
    87
    88    @staticmethod
    89    def test_assert_is_not():
    

    the test passes.

  • I move test_assert_is to make it a method of the TestUnittest class

    91        TOOLBOX.assertIsNot(None, False)
    92
    93    def test_assert_is():
    94        assert False is False
    95        TOOLBOX.assertIs(False, False)
    96
    97
    98def test_assert_not_equal():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_is()
        takes 0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add the staticmethod decorator to test_assert_is

    91        TOOLBOX.assertIsNot(None, False)
    92
    93    @staticmethod
    94    def test_assert_is():
    

    the test passes.

  • I indent test_assert_not_equal to make it a method of the TestUnittest class

     96        TOOLBOX.assertIs(False, False)
     97
     98    def test_assert_not_equal():
     99        assert True != 0
    100        TOOLBOX.assertNotEqual(True, 0)
    101
    102
    103def test_assert_equal():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_not_equal()
        takes 0 positional arguments but 1 was given
    

    because …

  • I add the staticmethod decorator to test_assert_not_equal

    96        TOOLBOX.assertIs(False, False)
    97
    98    @staticmethod
    99    def test_assert_not_equal():
    

    the test passes.

  • I move test_assert_equal to make it a method of the TestUnittest class

    101        TOOLBOX.assertNotEqual(True, 0)
    102
    103    def test_assert_equal():
    104        assert 0.0 == 0.0
    105        TOOLBOX.assertEqual(0.0, 0.0)
    106
    107
    108def test_assert_not_is_instance():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_equal()
        takes 0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add the staticmethod decorator to test_assert_equal

    101        TOOLBOX.assertNotEqual(True, 0)
    102
    103    @staticmethod
    104    def test_assert_equal():
    

    the test passes.

  • I move test_assert_not_is_instance to make it a method of the TestUnittest class

    106        TOOLBOX.assertEqual(0.0, 0.0)
    107
    108    def test_assert_not_is_instance():
    109        assert not isinstance(
    110            unittest.TestCase, unittest.TestCase
    111        )
    112        TOOLBOX.assertNotIsInstance(
    113            unittest.TestCase, unittest.TestCase
    114        )
    115
    116
    117def test_assert_is_instance():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_not_is_instance()
        takes 0 positional arguments but 1 was given
    
  • I add the staticmethod decorator to test_assert_not_is_instance

    106        TOOLBOX.assertEqual(0.0, 0.0)
    107
    108    @staticmethod
    109    def test_assert_not_is_instance():
    

    the test passes.

  • I move test_assert_is_instance to make it a method of the TestUnittest class

    113        TOOLBOX.assertNotIsInstance(
    114            unittest.TestCase, unittest.TestCase
    115        )
    116
    117    def test_assert_is_instance():
    118        a_class = unittest.TestCase
    119        an_instance = a_class()
    120
    121        assert isinstance(an_instance, a_class)
    122        TOOLBOX.assertIsInstance(
    123            an_instance, a_class
    124        )
    125
    126
    127def test_assert_not_is_subclass():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_is_instance()
        takes 0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add the staticmethod decorator to test_assert_is_instance

    113        TOOLBOX.assertNotIsInstance(
    114            unittest.TestCase, unittest.TestCase
    115        )
    116
    117    @staticmethod
    118    def test_assert_is_instance():
    

    the test passes.

  • I move test_assert_not_is_subclass to make it a method of the TestUnittest class

    123        TOOLBOX.assertIsInstance(
    124            an_instance, a_class
    125        )
    126
    127    def test_assert_not_is_subclass():
    128        assert not issubclass(
    129            unittest.TestCase, list
    130        )
    131        TOOLBOX.assertNotIsSubclass(
    132            unittest.TestCase, dict
    133        )
    134
    135
    136def test_assert_is_subclass():
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_not_is_subclass()
        takes 0 positional arguments but 1 was given
    
  • I add the staticmethod decorator to test_assert_not_is_subclass

    113        TOOLBOX.assertIsInstance(
    114            an_instance, a_class
    115        )
    116
    117    @staticmethod
    118    def test_assert_not_is_subclass():
    

    the test passes.

  • I move test_assert_is_subclass to make it a method of the TestUnittest class

    132        TOOLBOX.assertNotIsSubclass(
    133            unittest.TestCase, dict
    134        )
    135
    136    def test_assert_is_subclass():
    137        assert issubclass(unittest.TestCase, object)
    138        TOOLBOX.assertIsSubclass(
    139            unittest.TestCase, object
    140        )
    141
    142
    143# Exceptions seen
    

    the terminal is my friend, and shows TypeError

    TypeError:
        TestUnittest.test_assert_is_subclass()
        takes 0 positional arguments but 1 was given
    

    because a method of an instance takes the instance of the class (self) it belongs to as the first argument.

  • I add the staticmethod decorator to test_assert_is_subclass

    132        TOOLBOX.assertNotIsSubclass(
    133            unittest.TestCase, dict
    134        )
    135
    136    @staticmethod
    137    def test_assert_is_subclass():
    

    the test passes.


  • I add the TOOLBOX variable to TestUnittest to make it a class attribute

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    TOOLBOX = unittest.TestCase()
    11
    12    @staticmethod
    13    def test_attributes_and_methods_of_unittest():
    
  • I use the new class attribute for TOOLBOX in test_attributes_and_methods_of_unittest

    32        assert reality == my_expectation
    33        # TOOLBOX.assertNotEqual(reality, my_expectation)
    34        # TOOLBOX.assertEqual(reality, my_expectation)
    35        self.TOOLBOX.assertEqual(reality, my_expectation)
    36
    37    @staticmethod
    38    def test_attributes_and_methods_of_unittest_testcase():
    

    the terminal is my friend, and shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses of test_attributes_and_methods_of_unittest

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    TOOLBOX = unittest.TestCase()
    11
    12    @staticmethod
    13    # def test_attributes_and_methods_of_unittest():
    14    def test_attributes_and_methods_of_unittest(self):
    

    the terminal is my friend, and shows

    E       fixture 'self' not found
    
  • I remove the staticmethod decorator since I am using self in the test_attributes_and_methods_of_unittest

     7# class Unittest(object):
     8class TestUnittest(object):
     9
    10    TOOLBOX = unittest.TestCase()
    11
    12    # @staticmethod
    13    # def test_attributes_and_methods_of_unittest():
    14    def test_attributes_and_methods_of_unittest(self):
    15        reality = dir(unittest)
    

    the test is green again.

  • I use the new class attribute for TOOLBOX in test_attributes_and_methods_of_unittest_testcase

    88        assert reality == my_expectation
    89        # TOOLBOX.assertNotEqual(reality, my_expectation)
    90        # TOOLBOX.assertEqual(reality, my_expectation)
    91        self.TOOLBOX.assertEqual(reality, my_expectation)
    92
    93    @staticmethod
    94    def test_assert_is_not():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_attributes_and_methods_of_unittest_testcase

    36        self.TOOLBOX.assertEqual(reality, my_expectation)
    37
    38    # @staticmethod
    39    # def test_attributes_and_methods_of_unittest_testcase():
    40    def test_attributes_and_methods_of_unittest_testcase(self):
    41        reality = dir(unittest.TestCase)
    

    green again.

  • I use the class attribute for TOOLBOX in test_assert_is_not

     94    @staticmethod
     95    def test_assert_is_not():
     96        assert None is not False
     97        # TOOLBOX.assertIsNot(None, False)
     98        self.TOOLBOX.assertIsNot(None, False)
     99
    100    @staticmethod
    101    def test_assert_is():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_is_not

    94    # @staticmethod
    95    # def test_assert_is_not():
    96    def test_assert_is_not(self):
    

    the test is green again.

  • I use the class attribute for TOOLBOX in test_assert_is

    101    @staticmethod
    102    def test_assert_is():
    103        assert False is False
    104        # TOOLBOX.assertIs(False, False)
    105        self.TOOLBOX.assertIs(False, False)
    106
    107    @staticmethod
    108    def test_assert_not_equal():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_is

    101    # @staticmethod
    102    # def test_assert_is():
    103    def test_assert_is(self):
    

    green again.

  • I use the class attribute for TOOLBOX in test_assert_not_equal

    108    @staticmethod
    109    def test_assert_not_equal():
    110        assert True != 0
    111        # TOOLBOX.assertNotEqual(True, 0)
    112        self.TOOLBOX.assertNotEqual(True, 0)
    113
    114    @staticmethod
    115    def test_assert_equal():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_not_equal

    108    # @staticmethod
    109    # def test_assert_not_equal():
    110    def test_assert_not_equal(self):
    

    the test is green again.

  • I use the class attribute for TOOLBOX in test_assert_equal

    115    @staticmethod
    116    def test_assert_equal():
    117        assert 0.0 == 0.0
    118        # TOOLBOX.assertEqual(0.0, 0.0)
    119        self.TOOLBOX.assertEqual(0.0, 0.0)
    120
    121    @staticmethod
    122    def test_assert_not_is_instance():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_equal

    115    # @staticmethod
    116    # def test_assert_equal():
    117    def test_assert_equal(self):
    

    green again.

  • I use the class attribute for TOOLBOX in test_assert_not_is_instance

    122    @staticmethod
    123    def test_assert_not_is_instance():
    124        assert not isinstance(
    125            unittest.TestCase, unittest.TestCase
    126        )
    127        # TOOLBOX.assertNotIsInstance(
    128        self.TOOLBOX.assertNotIsInstance(
    129            unittest.TestCase, unittest.TestCase
    130        )
    131
    132    @staticmethod
    133    def test_assert_is_instance():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_not_is_instance

    122    # @staticmethod
    123    # def test_assert_not_is_instance():
    124    def test_assert_not_is_instance(self):
    

    the test is green again.

  • I use the class attribute for TOOLBOX in test_assert_is_instance

    133    @staticmethod
    134    def test_assert_is_instance():
    135        a_class = unittest.TestCase
    136        an_instance = a_class()
    137
    138        assert isinstance(an_instance, a_class)
    139        # TOOLBOX.assertIsInstance(
    140        self.TOOLBOX.assertIsInstance(
    141            an_instance, a_class
    142        )
    143
    144    @staticmethod
    145    def test_assert_not_is_subclass():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_is_instance

    133    # @staticmethod
    134    # def test_assert_is_instance():
    135    def test_assert_is_instance(self):
    

    the test is green again.

  • I use the class attribute for TOOLBOX in test_assert_not_is_subclass

    145    @staticmethod
    146    def test_assert_not_is_subclass():
    147        assert not issubclass(
    148            unittest.TestCase, list
    149        )
    150        # TOOLBOX.assertNotIsSubclass(
    151        self.TOOLBOX.assertNotIsSubclass(
    152            unittest.TestCase, dict
    153        )
    154
    155    @staticmethod
    156    def test_assert_is_subclass():
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_not_is_subclass

    145    # @staticmethod
    146    # def test_assert_not_is_subclass():
    147    def test_assert_not_is_subclass(self):
    

    the test is green again.

  • I use the class attribute for TOOLBOX in test_assert_is_subclass

    156    @staticmethod
    157    def test_assert_is_subclass():
    158        assert issubclass(unittest.TestCase, object)
    159        # TOOLBOX.assertIsSubclass(
    160        self.TOOLBOX.assertIsSubclass(
    161            unittest.TestCase, object
    162        )
    163
    164
    165# Exceptions seen
    

    the terminal shows NameError

    NameError: name 'self' is not defined
    
  • I add self to the parentheses and comment out the staticmethod decorator for test_assert_is_subclass

    156    # @staticmethod
    157    # def test_assert_is_subclass():
    158    def test_assert_is_subclass(self):
    

    the test is green again.

  • I remove the TOOLBOX variable because it is no longer used

    1import unittest
    2
    3
    4# class Unittest(object):
    5class TestUnittest(object):
    
  • I add a git commit message in the other terminal

    git commit -am 'extract TestUnittest class'
    

use unittest.TestCase

I can use the unittest.TestCase class as a parent of the TestUnittest class which will allow me to use self to access its attributes and methods.

It also means I will not need the TOOLBOX class attribute which points to an instance of the unittest.TestCase class.


RED: make it fail


  • I go back to the terminal where the tests are running.

  • I change the call to the assertEqual method in test_attributes_and_methods_of_unittest

    30        assert reality == my_expectation
    31        # TOOLBOX.assertNotEqual(reality, my_expectation)
    32        # TOOLBOX.assertEqual(reality, my_expectation)
    33        # self.TOOLBOX.assertEqual(reality, my_expectation)
    34        self.assertEqual(reality, my_expectation)
    35
    36    # @staticmethod
    37    # def test_attributes_and_methods_of_unittest_testcase():
    38    def test_attributes_and_methods_of_unittest_testcase(self):
    

    the terminal is my friend, and shows AttributeError

    AttributeError: 'TestUnittest' object
                    has no attribute 'assertEqual'
    
  • I add AttributeError to the list of Exceptions seen

    165# Exceptions seen
    166# AssertionError
    167# NameError
    168# TypeError
    169# AttributeError
    

GREEN: make it pass


I add unittest.TestCase as the parent of the TestUnittest class so that it can have all the attributes and methods of unittest.TestCase

 4# class Unittest(object):
 5# class TestUnittest(object):
 6class TestUnittest(unittest.TestCase):
 7
 8    TOOLBOX = unittest.TestCase()
 9
10    # @staticmethod
11    # def test_attributes_and_methods_of_unittest():
12    def test_attributes_and_methods_of_unittest(self):
13        reality = dir(unittest)

the test passes because


REFACTOR: make it better


  • I remove the commented lines from test_attributes_and_methods_of_unittest and TestUnittest

     1import unittest
     2
     3
     4class TestUnittest(unittest.TestCase):
     5
     6    TOOLBOX = unittest.TestCase()
     7
     8    def test_attributes_and_methods_of_unittest(self):
     9        reality = dir(unittest)
    10        my_expectation = [
    
    26        ]
    27        assert reality == my_expectation
    28        self.assertEqual(reality, my_expectation)
    29
    30    # @staticmethod
    31    # def test_attributes_and_methods_of_unittest_testcase():
    32    def test_attributes_and_methods_of_unittest_testcase(self):
    
  • I add an assertion to test_assert_is_subclass to show that TestUnittest is a subclass of the unittest.TestCase class

    148    # @staticmethod
    149    # def test_assert_is_subclass():
    150    def test_assert_is_subclass(self):
    151        assert issubclass(unittest.TestCase, object)
    152        # TOOLBOX.assertIsSubclass(
    153        self.TOOLBOX.assertIsSubclass(
    154            unittest.TestCase, object
    155        )
    156        self.assertNotIsSubclass(
    157            TestUnittest, unittest.TestCase
    158        )
    159
    160
    161# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <class 'tests.test_unittest.TestUnittest'>
        is a subclass of
        <class 'unittest.case.TestCase'>
    
  • I change the assertion to make it True

    148    # @staticmethod
    149    # def test_assert_is_subclass():
    150    def test_assert_is_subclass(self):
    151        assert issubclass(unittest.TestCase, object)
    152        # TOOLBOX.assertIsSubclass(
    153        self.TOOLBOX.assertIsSubclass(
    154            unittest.TestCase, object
    155        )
    156        # self.assertNotIsSubclass(
    157        self.assertIsSubclass(
    158            TestUnittest, unittest.TestCase
    159        )
    160
    161
    162# Exceptions seen
    

    the test passes.

  • I change the call to self.TOOLBOX.assertIsSubclass

    148    # @staticmethod
    149    # def test_assert_is_subclass():
    150    def test_assert_is_subclass(self):
    151        assert issubclass(unittest.TestCase, object)
    152        # TOOLBOX.assertIsSubclass(
    153        # self.TOOLBOX.assertIsSubclass(
    154        self.assertIsSubclass(
    155            unittest.TestCase, object
    156        )
    157        # self.assertNotIsSubclass(
    158        self.assertIsSubclass(
    159            TestUnittest, unittest.TestCase
    160        )
    161
    162
    163# Exceptions seen
    

    the test is still green.

  • I remove the commented lines from test_assert_is_subclass

    148    def test_assert_is_subclass(self):
    149        assert issubclass(unittest.TestCase, object)
    150        self.assertIsSubclass(
    151            unittest.TestCase, object
    152        )
    153        self.assertIsSubclass(
    154            TestUnittest, unittest.TestCase
    155        )
    156
    157
    158# Exceptions seen
    159# AssertionError
    160# NameError
    161# TypeError
    162# AttributeError
    
  • I change the call to the assertNotIsSubclass method in test_assert_not_is_subclass

    137    # @staticmethod
    138    # def test_assert_not_is_subclass():
    139    def test_assert_not_is_subclass(self):
    140        assert not issubclass(
    141            unittest.TestCase, list
    142        )
    143        # TOOLBOX.assertNotIsSubclass(
    144        # self.TOOLBOX.assertNotIsSubclass(
    145        self.assertNotIsSubclass(
    146            unittest.TestCase, dict
    147        )
    148
    149    def test_assert_is_subclass(self):
    

    still green.

  • I remove the commented lines from test_assert_not_is_subclass

    137    def test_assert_not_is_subclass(self):
    138        assert not issubclass(
    139            unittest.TestCase, list
    140        )
    141        self.assertNotIsSubclass(
    142            unittest.TestCase, dict
    143        )
    144
    145    def test_assert_is_subclass(self):
    
  • I add an assertion to test_assert_is_instance to show that self in the TestUnittest class is an instance of the unittest.TestCase class

    125    # @staticmethod
    126    # def test_assert_is_instance():
    127    def test_assert_is_instance(self):
    128        a_class = unittest.TestCase
    129        an_instance = a_class()
    130
    131        assert isinstance(an_instance, a_class)
    132        # TOOLBOX.assertIsInstance(
    133        # self.TOOLBOX.assertIsInstance(
    134        self.TOOLBOX.assertIsInstance(
    135            an_instance, a_class
    136        )
    137        self.assertNotIsInstance(
    138            self, unittest.TestCase
    139        )
    140
    141    def test_assert_not_is_subclass(self):
    

    the terminal is my friend, and shows AssertionError

    AssertionError:
        <
            tests.test_unittest.TestUnittest
            testMethod=test_assert_is_instance
        > is an instance of
        <class 'unittest.case.TestCase'>
    
  • I change assertNotIsInstance to assertIsInstance

    125    # @staticmethod
    126    # def test_assert_is_instance():
    127    def test_assert_is_instance(self):
    128        a_class = unittest.TestCase
    129        an_instance = a_class()
    130
    131        assert isinstance(an_instance, a_class)
    132        # TOOLBOX.assertIsInstance(
    133        # self.TOOLBOX.assertIsInstance(
    134        self.TOOLBOX.assertIsInstance(
    135            an_instance, a_class
    136        )
    137        # self.assertNotIsInstance(
    138        self.assertIsInstance(
    139            self, unittest.TestCase
    140        )
    141
    142    def test_assert_not_is_subclass(self):
    

    the test passes.

  • I change the call to self.TOOLBOX.assertIsInstance

    125# @staticmethod
    126    # def test_assert_is_instance():
    127    def test_assert_is_instance(self):
    128        a_class = unittest.TestCase
    129        an_instance = a_class()
    130
    131        assert isinstance(an_instance, a_class)
    132        # TOOLBOX.assertIsInstance(
    133        # self.TOOLBOX.assertIsInstance(
    134        # self.TOOLBOX.assertIsInstance(
    135        self.assertIsInstance(
    136            an_instance, a_class
    137        )
    138        # self.assertNotIsInstance(
    139        self.assertIsInstance(
    140            self, unittest.TestCase
    141        )
    142
    143    def test_assert_not_is_subclass(self):
    
  • I remove the commented lines from test_assert_is_instance

    125    def test_assert_is_instance(self):
    126        a_class = unittest.TestCase
    127        an_instance = a_class()
    128
    129        assert isinstance(an_instance, a_class)
    130        self.assertIsInstance(
    131            an_instance, a_class
    132        )
    133        self.assertIsInstance(
    134            self, unittest.TestCase
    135        )
    136
    137    def test_assert_not_is_subclass(self):
    
  • I change the call to the assertNotIsInstance method in test_assert_not_is_instance

    114    # @staticmethod
    115    # def test_assert_not_is_instance():
    116    def test_assert_not_is_instance(self):
    117        assert not isinstance(
    118            unittest.TestCase, unittest.TestCase
    119        )
    120        # TOOLBOX.assertNotIsInstance(
    121        # self.TOOLBOX.assertNotIsInstance(
    122        self.assertNotIsInstance(
    123            unittest.TestCase, unittest.TestCase
    124        )
    125
    126    def test_assert_is_instance(self):
    

    the test is still green.

  • I remove the commented lines from test_assert_not_is_instance

    114    def test_assert_not_is_instance(self):
    115        assert not isinstance(
    116            unittest.TestCase, unittest.TestCase
    117        )
    118        self.assertNotIsInstance(
    119            unittest.TestCase, unittest.TestCase
    120        )
    121
    122    def test_assert_is_instance(self):
    
  • I change the call to assertEqual in test_assert_equal

    107    # @staticmethod
    108    # def test_assert_equal():
    109    def test_assert_equal(self):
    110        assert 0.0 == 0.0
    111        # TOOLBOX.assertEqual(0.0, 0.0)
    112        # self.TOOLBOX.assertEqual(0.0, 0.0)
    113        self.assertEqual(0.0, 0.0)
    114
    115    def test_assert_not_is_instance(self):
    

    still green.

  • I remove the commented lines from test_assert_equal

    107    def test_assert_equal(self):
    108        assert 0.0 == 0.0
    109        self.assertEqual(0.0, 0.0)
    110
    111    def test_assert_not_is_instance(self):
    
  • I change the call to the assertNotEqual method in test_assert_not_equal

    100    # @staticmethod
    101    # def test_assert_not_equal():
    102    def test_assert_not_equal(self):
    103        assert True != 0
    104        # TOOLBOX.assertNotEqual(True, 0)
    105        # self.TOOLBOX.assertNotEqual(True, 0)
    106        self.assertNotEqual(True, 0)
    107
    108    def test_assert_equal(self):
    

    still green.

  • I remove the commented lines from test_assert_not_equal

    100    def test_assert_not_equal(self):
    101        assert True != 0
    102        self.assertNotEqual(True, 0)
    103
    104    def test_assert_equal(self):
    
  • I change the call to the assertIs method in test_assert_is

     93    # @staticmethod
     94    # def test_assert_is():
     95    def test_assert_is(self):
     96        assert False is False
     97        # TOOLBOX.assertIs(False, False)
     98        # self.TOOLBOX.assertIs(False, False)
     99        self.assertIs(False, False)
    100
    101    def test_assert_not_equal(self):
    

    green.

  • I remove the commented lines from test_assert_is

    93    def test_assert_is(self):
    94        assert False is False
    95        self.assertIs(False, False)
    96
    97    def test_assert_not_equal(self):
    
  • I change the call to the assertIsNot method in test_assert_is_not

    86    # @staticmethod
    87    # def test_assert_is_not():
    88    def test_assert_is_not(self):
    89        assert None is not False
    90        # TOOLBOX.assertIsNot(None, False)
    91        # self.TOOLBOX.assertIsNot(None, False)
    92        self.assertIsNot(None, False)
    93
    94    def test_assert_is(self):
    

    the test is still green.

  • I remove the commented lines from test_assert_is_not

    86    def test_assert_is_not(self):
    87        assert None is not False
    88        self.assertIsNot(None, False)
    89
    90    def test_assert_is(self):
    
  • I change the call to the assertEqual method in test_attributes_and_methods_of_unittest_testcase

    81        assert reality == my_expectation
    82        # TOOLBOX.assertNotEqual(reality, my_expectation)
    83        # TOOLBOX.assertEqual(reality, my_expectation)
    84        # self.TOOLBOX.assertEqual(reality, my_expectation)
    85        self.assertEqual(reality, my_expectation)
    86
    87    def test_assert_is_not(self):
    

    the test is still green.

  • I remove the commented lines from test_attributes_and_methods_of_unittest_testcase

    27        assert reality == my_expectation
    28        self.assertEqual(reality, my_expectation)
    29
    30    def test_attributes_and_methods_of_unittest_testcase(self):
    31        reality = dir(unittest.TestCase)
    32        my_expectation = [
    
    78        ]
    79        assert reality == my_expectation
    80        self.assertEqual(reality, my_expectation)
    81
    82    def test_assert_is_not(self):
    
  • I remove the TOOLBOX class attribute since it is no longer used

    4class TestUnittest(unittest.TestCase):
    5
    6    def test_attributes_and_methods_of_unittest(self):
    

    all the tests are still passing.

  • I add a git commit message in the other terminal

    git commit -am 'use unittest.TestCase'
    

close the project

  • I close test_unittest.py

  • I click in the terminal where the tests are running

  • I use q on the keyboard to leave the tests. The terminal goes back to the command line.

  • I change directory to the parent of unittest

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory.


review

I can write tests with the unittest.TestCase class which comes with assert methods I can use in place of basic assert_ statements:

How many questions can you answer about unittest?


code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

You now know

Would you like to use unittest with the assertion_error project?


rate pumping python

If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.