Layers of confidence

Testing software is like checking a bicycle. You can inspect each individual brake component, test whether the assembled brake stops a wheel, and finally ride the complete bicycle on a track. Each check answers a different question.

Automated tests are usually written in code and kept with the product code. People also test software by using it themselves.

  • Unit tests check small pieces of logic, such as a price calculation.
  • Integration tests check whether these smaller parts work together, such as the checkout and the payment service.
  • End-to-end tests exercise a complete automated user journey through the application.
  • Manual and exploratory testing use human judgement to find behaviour automated tests may miss.

For a calculator, a unit test might give the addition function 2 + 3 and check that it returns 5, then try negative numbers. Another could check the code that displays a number. An integration test could check that the answer reaches the display. An end-to-end test might open the calculator in a browser, click buttons, and check the result on screen. A person exploring the app may find cases nobody thought to automate.

Automated tests run against a version of the code and report which checks passed or failed, often called “green” or “red”. Teams keep these tests so later changes can catch regressions: behaviour that used to work but now fails. A change in one part of the system can affect another, so teams run the relevant tests and broader checks when needed.

Passing tests does not mean “bug-free”

Testing starts during development and continues after release. Developers can run tests locally; CI/CD runs automated checks, and broader checks may use a shared test environment. Tests cover only situations the team chose to check. They raise confidence but cannot prove the software will work in every case, especially when production differs from the test environment.

Good testing follows risk. A payment calculation needs stronger coverage than a minor visual flourish because the cost of failure is much higher. Clear acceptance criteria help everyone agree on the behaviour being checked. Regression testing checks that a fix has not broken something that previously worked.