Explain Codes LogoExplain Codes Logo

Pytest: assert almost equal

python
assertions
float-comparison
testing
Nikita BarsukovbyNikita Barsukov·Jan 12, 2025
TLDR

One of the easiest ways to assert near-equality of floats in pytest is with pytest.approx().

Example:

assert 0.1 * 3 == pytest.approx(0.3)

You can also customize the tolerance level with abs or rel parameters.

Tolerance Example:

assert 0.1 * 3 == pytest.approx(0.3, abs=1e-12)

In the remainder of the post, we'll dive deeper and explore more complex cases, as well as other tools at your disposal.

Cold-hard syntax and pytest for tough problems

Sometimes, problems might get a bit more complex than what you'd expect.

Comparing Bloated Tuples

If you have tuples or lists of floats, instead of going through each element in a painstaking manner, use this neat trick involving map and all functions.

assert all(map(lambda x, y: abs(x - y) < threshold, tuple1, tuple2)) # I find your lack of tolerance disturbing — Darth Vader

The above code essentially loops through the tuples and checks the difference of each pair, making your tests clear and snappy.

Alternatives with NumPy and Unittest

If you're more inclined to the NumPy or unittest libraries, they provide excellent ways to assert near equality of floats.

NumPy's assert_allclose:

import numpy as np np.testing.assert_allclose(actual_array, expected_array, rtol=1e-5) # Close enough only counts in horseshoes and hand grenades. And floats comparisons.

Unittest's assertAlmostEqual:

import unittest class TestFloats(unittest.TestCase): def test_floats(self): self.assertAlmostEqual(0.1 * 3, 0.3, places=5) # Life is like float comparison; sometimes you're a bit off, but it's okay.

Adding Flexibility with Custom Functions

Creating your own custom function can provide the ultimate flexibility and help you adapt to any specific use case.

def are_floats_almost_equal(x, y, tolerance): return abs(x - y) < tolerance assert are_floats_almost_equal(0.1 * 3, 0.3, 1e-12) # I can tolerate everything except intolerance...and large float differences.

Clear, Precision Strikes with math.isclose()

You don't have to sacrifice precision for clear code. Python's math.isclose() is a prime example of such balance:

import math assert math.isclose(0.1 * 3, 0.3, rel_tol=1e-9) # You and I are closer than we math.ceil( )

With good use of comments, you can explain tricky parts of your code, or hide dad jokes in plain sight.

Learning from Errors

Wisely utilizing error messages from assertions can make debugging an enjoyable part of your process:

assert a == pytest.approx(b), f"Expected {b}, but got {a}" # Whoops! Looks like our projectile forgot to aim.

These messages provide crucial information about assertion failures and help speed up debugging.