Learn the concept
A unit test checks a small behavior independently of unrelated systems. Choose cases that reveal the contract: ordinary inputs, boundaries, invalid inputs, and known regressions. Testing the implementation’s exact internal steps often makes harmless refactoring painful.
Keep setup, action, and assertion clear. A failing assertion should make the mismatch understandable. Tests should be repeatable and should not depend on a real network service, changing clock, or execution order unless that dependency is the subject of the test.
Use the standard-library unittest module or another test runner configured by the project. Assertions in tests are appropriate; production input validation should use explicit errors. A passing test suite is evidence about its covered cases, not proof that every input works.
Run and inspect
import unittest
def clamp(value, lower, upper):
if lower > upper: raise ValueError("Invalid bounds")
return min(max(value, lower), upper)
class ClampTests(unittest.TestCase):
def test_boundaries(self):
self.assertEqual(clamp(-1, 0, 10), 0)
self.assertEqual(clamp(11, 0, 10), 10)
def test_invalid_bounds(self):
with self.assertRaises(ValueError): clamp(1, 10, 0)
result = unittest.TestResult()
unittest.defaultTestLoader.loadTestsFromTestCase(ClampTests).run(result)
assert result.wasSuccessful()
Your exercise
Write tests for your CSV validator, including a quoted comma, missing field, and invalid count. Add a regression case for one bug you found.
Check your understanding
Each failure points to a specific contract and tests can run without contacting a service.