Code Coverage vs Meaningful Testing
By the end of this lesson, you'll be able to:
- Recognize a test written purely to hit a coverage number without verifying behavior
- Explain why 100% coverage doesn't guarantee correctness
- Apply this module's full toolkit to write tests that are both high-coverage and meaningful
Prerequisites: "Mocking HTTP Callouts"
A test that hits 100% coverage and verifies nothing
@isTest
static void testCalculateAndFormat() {
Calculator calc = new Calculator();
calc.calculateAndFormat(12, 5, '+'); // runs every line... but asserts nothing at all!
}
@isTest— marks the test method.static void testCalculateAndFormat() {— this test genuinely executes every line insidecalculateAndFormat, contributing real percentage points to the org's code coverage.Calculator calc = new Calculator();— creates the calculator.calc.calculateAndFormat(12, 5, '+');— runs it, but asserts nothing at all — it would pass even if the method were completely broken, because it never checks the result. This is exactly Lesson 1's warning, made concrete: coverage counts lines executed, not correctness verified.}— closes the test method.
The same coverage, genuinely meaningful
@isTest
static void additionReturnsCorrectlyFormattedSum() {
Calculator calc = new Calculator();
String result = calc.calculateAndFormat(12, 5, '+');
System.assertEquals('12 + 5 = 17.00', result); // Lesson 5's specific-value assertion
}
@isTest
static void divisionByZeroReturnsErrorMessage() {
Calculator calc = new Calculator();
String result = calc.calculateAndFormat(10, 0, '/');
System.assertEquals('Error: cannot divide by zero.', result);
}
@isTest— marks the first test method.static void additionReturnsCorrectlyFormattedSum() {— one scenario per test method (Lesson 2).Calculator calc = new Calculator();— creates the calculator.String result = calc.calculateAndFormat(12, 5, '+');— runs the same lines as the weak test above.System.assertEquals('12 + 5 = 17.00', result);— Lesson 5's specific-value assertion — now this scenario actually verifies a specific, correct outcome.}— closes this test method.- (blank line)
@isTest— marks a second test method.static void divisionByZeroReturnsErrorMessage() {— exception paths tested explicitly (Lesson 6).Calculator calc = new Calculator();— creates the calculator.String result = calc.calculateAndFormat(10, 0, '/');— the division-by-zero scenario.System.assertEquals('Error: cannot divide by zero.', result);— asserts the specific expected error message.}— closes this test method.
Same lines of Calculator covered as the weak test — but now every scenario actually verifies a specific, correct outcome. This is the whole module's toolkit converging.
A checklist for meaningful tests going forward
- Does every test method assert a specific expected value, not just "no exception" or "not null"? (Lesson 5)
- Are both the happy path and the exception/edge-case paths covered? (Lesson 6)
- Is there at least one bulk test (200 records) for every trigger? (Lesson 7)
- Is repeated setup extracted into a factory, keeping each test focused on what it's actually verifying? (Lesson 8)
Coverage percentage tells you how much code ran during testing; this checklist is what actually tells you whether the tests are worth trusting.
Exercise
This test hits 100% coverage but verifies nothing. Rewrite it with a specific assertion.
Show hint
Add a System.assertEquals with the actual expected value.
Code Coverage vs Meaningful Testing Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
This closing lesson returns to Lesson 1's opening warning with the full toolkit now in hand: coverage measures which lines ran, not whether the tests actually verify anything — and every technique in this module exists to close that gap.