Tests check expectations automatically.
Debugging helps us find the cause of a problem we have already noticed. Automated tests check behavior we expect and can warn us when a later change accidentally breaks something that worked before.
# Manual check
print(izracunaj_popust(100, 10))
# Automatic check inside a test
self.assertEqual(izracunaj_popust(100, 10), 90)A manual check asks you to read and judge an output. An automatic assertion compares the actual result with the expected result and reports whether they match.
Tests do not prove that a program has no bugs. They verify the specific cases you choose, so choosing useful examples matters.
A unit is small: A unit test usually checks one focused part of a program, such as a function or method, in a situation you can describe clearly.
import unittest
def saberi(a: int, b: int) -> int:
return a + b
class TestSabiranje(unittest.TestCase):
def test_dva_pozitivna_broja(self):
self.assertEqual(saberi(2, 3), 5)
if __name__ == "__main__":
unittest.main()We import the standard unittest library. unittest.TestCase gives our test class assertion methods. A method beginning with test_ is discovered as a test, and assertEqual compares an actual result with an expected value. unittest.main() is useful when running this file directly, but tests can also run through python -m unittest.
moj_projekat/
├── kalkulator.py
└── test_kalkulator.py
# kalkulator.py
def saberi(a: int, b: int) -> int:
return a + b
# test_kalkulator.py
import unittest
from kalkulator import saberi
class TestKalkulator(unittest.TestCase):
def test_sabiranje(self):
self.assertEqual(saberi(4, 6), 10)Separating the implementation from its tests keeps each file focused. From the project folder, run python -m unittest -v; on some systems use python3 -m unittest -v. The -v option shows more detail, and unittest normally discovers files named like test_kalkulator.py or other test*.py files.
def test_popust_deset_posto(self):
# Arrange
cena = 200
popust = 10
# Act
rezultat = izracunaj_popust(cena, popust)
# Assert
self.assertEqual(rezultat, 180)Arrange prepares input data, Act runs the behavior, and Assert compares the actual result with the expected result. These comments are useful while learning, but a clear test name and clear expectation are often more valuable than many comments.
self.assertEqual(saberi(2, 3), 5)
self.assertTrue(10 > 5)
self.assertFalse(10 < 5)assertEqual checks that two values are equal. assertTrue checks a true expression, and assertFalse checks a false expression. For a specific expected number or text, assertEqual is usually the clearest choice. We will meet assertRaises in the next lesson about exceptions.
python -m unittest -v
python -m unittest discover -v
# Or, on some systems:
python3 -m unittest -v
python3 -m unittest discover -vRun the command from the appropriate project folder. Discovery and its exact output can depend on the file structure and Python version, but the default test-file pattern is test*.py.
Read a test result carefully
- OK means every executed assertion passedAn
OKresult means the test runner completed its checks and none of their assertions failed. - FAIL means an assertion was not trueFor example,
self.assertEqual(10, 12)runs normally but fails because the values are different. - ERROR means the test could not finish normallyFor example,
rezultat = 10 / 0raises an unexpected exception before a later assertion can run. FAIL and ERROR are different clues, not proof that Python itself is broken. - Use normal and edge casesFor a discount function, test 0%, 10%, 100%, and a price of 0. An edge case is a boundary situation that one ordinary example may miss.
- Let tests protect against regressionsA regression happens when a later change breaks behavior that used to work. A test can report FAIL, then debugging helps you find and fix the cause. Do not change an expected result just to make a failing test pass; first decide what behavior is correct.
Common beginner testing mistakes
- Testing only one exampleOne passing example gives limited confidence. Add typical and edge cases that matter for the function.
- Forgetting the test_ prefixA method without the expected
test_prefix may not be discovered and run. - Running from the wrong folderCheck the terminal folder and file names before assuming unittest cannot find your tests.
- Changing an expectation only to get OKA test name should describe what it checks. Investigate whether the implementation or the expected result is wrong before changing either one.
