Skip to main content
ANVISoftware Solutions
Lesson 1 of 13Intermediate12 min

Why Testing Matters

By the end of this lesson

Explain what tests actually buy you, and use that to judge whether a given test is worth writing.

Tests exist so you can change code without checking everything by hand.

That is the justification, and holding onto it is useful, because it gives you a way to judge any individual test: does this one make me more willing to change the code? Tests written for other reasons — to hit a coverage number, to satisfy a rule — tend to be the ones that get deleted.

The problem they solve

Imagine a pricing calculation used in eleven places. You need to change how discounts combine. Without tests, you make the change and then face a choice: manually exercise eleven scenarios, or hope.

In practice, people hope. Or, more often, they avoid the change altogether and add a special case alongside the old logic. Do that a few times and you have code nobody wants to touch — not because it is complicated, but because nobody can predict what a change will break.

A first test
C#
[Fact]
public void ApplyDiscount_WithTenPercent_ReducesPriceCorrectly()
{
    // Arrange
    var calculator = new PriceCalculator();

    // Act
    decimal result = calculator.ApplyDiscount(200m, 10);

    // Assert
    Assert.Equal(180m, result);
}
  • The name states the scenario and the expected outcome, so a failure is informative before you read any code.
  • Arrange, act, assert: set up the situation, perform one action, check one outcome.
  • This test now runs in milliseconds, every time anyone builds, forever.

What makes a test worth having

  • It tests behaviour, not implementation — it still passes after a refactor that preserves behaviour
  • It fails for exactly one reason, so a failure points at a cause
  • Its name describes the scenario, so you can diagnose from the test run output alone
  • It runs fast enough that nobody is tempted to skip it
  • It does not depend on other tests, or on the order they run in
Test suite proportionsA wide base of many fast unit tests, a narrower middle band of integration tests, and a small top band of end-to-end tests. Unit tests run in milliseconds and catch logic mistakes. Integration tests are slower and catch wiring and query mistakes. End-to-end tests are slowest and most brittle, so only critical journeys are covered by them.E2EIntegrationUnitfew, slow, brittlecritical journeys onlycatch wiring andquery mistakesmany, fast,millisecondsInvert this and you get a slow, flaky suite that the team stops trusting.
Proportions that tend to work: many fast tests, few slow ones

The shape matters more than the labels. Many small fast tests catch logic mistakes immediately. A smaller number of integration tests catch wiring mistakes that unit tests structurally cannot see. A handful of end-to-end tests confirm the critical paths work as a whole.

Inverting this — mostly slow end-to-end tests — produces a suite that takes twenty minutes, fails intermittently, and gets ignored. At that point it costs more than it returns.

Summary

  • Tests exist so code can be changed safely — judge each test against that
  • The real cost of no tests is improvements that never get attempted
  • Test behaviour rather than implementation, or tests punish refactoring
  • Favour many fast tests and few slow ones; a slow suite gets ignored

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Think about it

Think about it

A test checks that a service calls the repository's Save method exactly once. You refactor the service to batch several saves into one call. The behaviour a user sees is unchanged, but the test fails. Was it a good test?

Show solution

No. It asserted an implementation detail — how the work was carried out — rather than the outcome. Since the observable behaviour did not change, a failure here is a false alarm.

A better test would assert the outcome: after the operation, the expected records exist with the expected values. That holds regardless of how many calls it took internally, so it survives the refactor and still catches genuine breakage.

Knowledge check

Nothing is recorded and there is no score. The explanation appears either way.

What is the primary thing a test suite buys you?

Saved in this browser only.