Test-driven development (TDD) means deciding what code should do by writing tests before implementing it. The tests fail at first. You then write code to make them pass, one by one. It is a choice, not the only way to test, and it is especially useful when you know—or are still working out—what the finished behavior should be. section 14.3 section 14.4
A practical cycle is:
- Write tests for the behavior you expect. Give each test a descriptive name so a failure is easy to recognize. section 14.3.1
- Run them before the implementation works. A minimal function or method can let the tests run even while it returns the wrong answer. section 14.3.1
- Implement behavior, rerun the tests, and use failures to choose the next correction. Add tests when you think of more cases. section 14.3.2
Start with a subtraction test
Suppose a Rust method named math takes the string "1 - 2" and should return -1. A test can state that expectation with assert_eq!(calc.math("1 - 2"), -1). For now, math can simply return 6: the test runs and fails, showing the result that needs to change. Other tests can specify consecutive minus signs, trailing spaces and minus signs, and an input such as "7 - seven" that should panic. section 14.3.1
struct Subtractor;
impl Subtractor {
fn math(&mut self, input: &str) -> i32 {
6
}
}
#[test]
fn one_minus_two_is_minus_one() {
let mut calc = Subtractor; #1
assert_eq!(calc.math("1 - 2"), -1);
}
#[test]
fn one_minus_minus_one_is_two() {
let mut calc = Subtractor;
assert_eq!(calc.math("1 - -1"), 2);
}
#[test]
fn three_minus_three_minus_three_minus_minus_three_is_zero() {
let mut calc = Subtractor;
assert_eq!(calc.math("3-3-3--3"), 0);
}
#[test]
fn eighteen_minus_nine_minus_nine_is_zero_even_with_characters_on_the_end() {
let mut calc = Subtractor;
assert_eq!(calc.math("18 - 9 -9-----"), 0);
}
#[test]
#[should_panic] #2
fn panics_when_characters_not_right() {
let mut calc = Subtractor;
calc.math("7 - seven");
}
The initial Subtractor listing keeps the implementation deliberately incomplete while five named tests spell out the behavior to build. section 14.3.1
The first improvement checks for invalid characters. That makes the expected-panic test pass, while the arithmetic tests still fail. Later failures reveal other gaps, including how to handle consecutive minus signs and a number left to process at the end of the input. Each result gives a smaller problem to fix. section 14.3.1 section 14.3.2
Passing tests remain useful when code changes: rerunning them can reveal behavior that has broken. They do not prove the code is perfect, because they check only the cases someone thought to write. Once the tests pass, refactoring is possible; changing the calculator to return a Result instead of panicking is left for another time. section 14.3.2














