LevelJar Sign in

Python course / Applied

Testing

Write tests that fail when the code is wrong, and make hard-to-test code testable. A test that passes whatever the code does is worse than no test, because it buys false confidence.

  • assertions
  • boundaries
  • unittest
  • setUp
  • subTest
  • doctest
  • mocks and patching
  • async tests

Start this module

Runs in your browser. Start straight away; create an account when you want your progress kept.

a case table and a failure
import unittest


def portion(total, people):
    if people <= 0:
        raise ValueError("people must be positive")
    return total / people


class PortionTests(unittest.TestCase):
    def test_shares(self):
        for total, people, each in [(10, 4, 2.5), (9, 3, 3.0)]:
            with self.subTest(total=total, people=people):
                self.assertEqual(portion(total, people), each)

    def test_refuses_nobody(self):
        with self.assertRaises(ValueError):
            portion(10, 0)


unittest.main(argv=["tests"], exit=False, verbosity=2)
test_refuses_nobody (__main__.PortionTests.test_refuses_nobody) ... ok
test_shares (__main__.PortionTests.test_shares) ... ok

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

OK

What you will learn

The lessons in this module

  • What a test is
  • Choosing the cases
  • unittest
  • Fresh objects for every test: setUp
  • Tables of cases: subTest
  • Examples that check themselves: doctest
  • Passing in what varies
  • Mock objects
  • Patching
  • Testing input and output
  • Testing with files
  • Testing async code
  • Testing properties
  • Test behaviour, not insides
  • Tests first
  • A test for every bug
  • Capstone: a test suite for an inventory
  • Module review: a table-driven test runner

Ready when you are

Start this module

Previous: Async syntax and event loops. Next: Patterns and architecture. All modules are on the course page.