unittest

TestCase, assertEqual, setUp, and TextTestRunner.

unittest ships with Python. A test is a method on a TestCase whose name starts with test_. Run the suite with TextTestRunner.

Goal

Write two tests for city_label and line_total, and print whether the suite passed.

A first TestCase

import unittest

def city_label(city):
    return str(city or "").strip().title()

class LabelTests(unittest.TestCase):
    def test_strip_and_title(self):
        self.assertEqual(city_label("  nairobi "), "Nairobi")

    def test_empty(self):
        self.assertEqual(city_label(""), "")

suite = unittest.defaultTestLoader.loadTestsFromTestCase(LabelTests)
result = unittest.TextTestRunner(verbosity=2).run(suite)
print("ok" if result.wasSuccessful() else "failed")

setUp

import unittest

TAX = 0.16

def line_total(units, price):
    return round(units * price * (1 + TAX), 2)

class PriceTests(unittest.TestCase):
    def setUp(self):
        self.price = 10.0

    def test_two_units(self):
        self.assertEqual(line_total(2, self.price), 23.2)

    def test_zero_units(self):
        self.assertEqual(line_total(0, self.price), 0.0)

suite = unittest.defaultTestLoader.loadTestsFromTestCase(PriceTests)
result = unittest.TextTestRunner(verbosity=2).run(suite)
print("ok" if result.wasSuccessful() else "failed")

assertRaises

import unittest

def line_total(units, price):
    if units < 0 or price < 0:
        raise ValueError("units and price must be >= 0")
    return round(units * price * 1.16, 2)

class PriceTests(unittest.TestCase):
    def test_negative_units(self):
        with self.assertRaises(ValueError):
            line_total(-1, 10)

suite = unittest.defaultTestLoader.loadTestsFromTestCase(PriceTests)
result = unittest.TextTestRunner(verbosity=2).run(suite)
print("ok" if result.wasSuccessful() else "failed")
Pitfall

unittest.main() wants to exit the process. In this editor use TextTestRunner(...).run(suite) and print the result.