Skip to content

Using assertEqual and Other Assertions

assert_equal.py
self.assertEqual(actual, expected)
self.assertNotEqual(actual, expected)
assert_truthy.py
self.assertTrue(condition)
self.assertFalse(condition)
assert_none.py
self.assertIsNone(value)
self.assertIsNotNone(value)
assert_type.py
self.assertIs(a, b)
self.assertIsInstance(obj, dict)

Use assertRaises for exception behavior.

assert_raises.py
import unittest
 
 
def parse_age(s: str) -> int:
    age = int(s)
    if age < 0:
        raise ValueError("age must be >= 0")
    return age
 
 
class TestParseAge(unittest.TestCase):
    def test_negative_age_raises(self):
        with self.assertRaises(ValueError):
            parse_age("-1")

Prefer specific assertions (e.g., assertIsNone) instead of assertTrue(x is None).

The assertion you choose decides what a failure tells you

Section titled “The assertion you choose decides what a failure tells you”

Both of these test the same thing. Only one is useful when it breaks:

tests/test_msgs.py
def test_assertTrue_says_nothing(self):
    self.assertTrue([1, 2, 3] == [1, 2, 4])
 
def test_assertEqual_shows_a_diff(self):
    self.assertEqual([1, 2, 3], [1, 2, 4])

Measured output:

assertTrue
AssertionError: False is not true
assertEqual
AssertionError: Lists differ: [1, 2, 3] != [1, 2, 4]
 
First differing element 2:
3
4
 
- [1, 2, 3]
?        ^
+ [1, 2, 4]
?        ^

assertTrue reduced the comparison to a boolean before the framework saw it, so all it could report was False. assertEqual received both objects and produced a diff naming the differing element.

diagram Diagram mermaid
assertionuse for
assertEqual(a, b)any equality — gives type-aware diffs
assertAlmostEqual(a, b)floats
assertIn(a, b)membership, with both operands reported
assertIs(a, b)identity — None, True, False
assertIsNone(x)clearer than assertEqual(x, None)
assertRaises(Err)as a context manager
assertRaisesRegex(Err, "text")the exception and its message
assertCountEqual(a, b)same items, order irrelevant
floats.py
self.assertEqual(0.1 + 0.2, 0.3)         # AssertionError: 0.30000000000000004 != 0.3
self.assertAlmostEqual(0.1 + 0.2, 0.3)   # passes

Measured both. Binary floating point cannot represent 0.3 exactly, so exact equality is the wrong question for any computed float.

raises.py
with self.assertRaises(ZeroDivisionError):
    div(1, 0)
 
with self.assertRaisesRegex(ZeroDivisionError, "cannot divide"):
    div(1, 0)

The context-manager form is important: assertRaises(Err, div, 1, 0) also works but reads badly and cannot wrap several statements. Prefer assertRaisesRegex when the message matters — a test that accepts any ValueError will keep passing when the code starts failing for an entirely different reason.

sketch Same bug, different assertion p5.js
assertTrue collapses the comparison to a boolean before the framework sees it. assertEqual receives both values and can diff them.
pch.quizTag pch.quizDefaultTitle
  1. assertTrue([1,2,3] == [1,2,4]) fails. What does it print?

    pch.quizShowAnswer

    B — AssertionError: False is not true — Python evaluated the comparison to False before unittest saw it, so False is all it could report. assertEqual receives both objects and produces a diff.

  2. Why does assertEqual(0.1 + 0.2, 0.3) fail?

    pch.quizShowAnswer

    B — binary floating point cannot represent 0.3 exactly, so the sum is 0.30000000000000004 — Measured exactly that value. Use assertAlmostEqual for any computed float, which measured as passing.

  3. Why prefer assertRaisesRegex over assertRaises?

    pch.quizShowAnswer

    B — it checks the message too, so the test does not keep passing when the code starts failing for a different reason — A test that accepts any ValueError will happily pass on an unrelated ValueError introduced later.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading