liveBook · Manning

Test

As explained in Code Like a Pro in Rust

A test case is a specific input and execution scenario used to check software behavior or reproduce a failure.

A test case pairs an input or execution scenario with behavior to check. In Rust, compile-time checks remove some reasons to test, but they do not prove code is panic-free or verify every requirement. Use cases to check behavior the compiler cannot establish, especially failure paths and regressions. section 6.1 section 6.6

Choose the test boundary and inputs deliberately:

  • Use unit tests for small components, including private functions when their behavior needs checking. Use integration tests in tests/ for behavior exposed through a library’s public interface; Cargo discovers #[test] functions there. section 7.1
  • Keep known inputs when they establish required behavior. For broader input exploration, property testing generates values and reports a minimal failing case; it does not necessarily replace specification examples. section 6.3
  • Use fuzz testing to exercise inputs that might trigger a crash. When it finds one, retain the constructed failing case to reproduce the bug. section 7.5

Check a public sorting operation

An integration test passes [12, 1, 5, 0, 6, 2] to quicksort and asserts that the result is [0, 1, 2, 5, 6, 12]. A separate unit test checks the private partition function. These cases test different boundaries even though both use #[test] and assertions. section 7.1

cargo test
  Compiling proptest v0.1.0
  (/Users/brenden/dev/code-like-a-pro-in-rust/code/c6/6.2/proptest)
   Finished test [unoptimized + debuginfo] target(s) in 0.59s
    Running unittests (target/debug/deps/proptest-db846addc2c2f40d)

running 1 test
test tests::test_add ... FAILED

failures:

----- tests::test_add stdout -----
# ... snip ...
thread ‘tests::test_add’ panicked at ‘Test failed: attempt to add with
overflow; minimal failing input: a = -2452998745726535882,
b = -6770373291128239927
   successes: 1
   local rejects: 0
   global rejects: 0
‘, src/lib.rs:9:5

failures:
   tests::test_add

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered
out; finished in 0.00s

error: test failed, to rerun pass ‘--lib’

The failing proptest run reports the input pair that exposes integer overflow, turning generated input into a concrete case for diagnosis. section 6.3

Prefer cases tied to specifications and public behavior when refactoring: tests of unnecessary implementation details can become expensive to maintain. Review coverage to find gaps, but account for parallel execution when cases depend on timing or synchronization. section 6.6 section 6.10

How Code Like a Pro in Rust covers it

How deep it goes
Works through unit and integration test boundaries, assertions, generated failing inputs, and fuzzing; does not prescribe an exhaustive set of cases.
Examples
Uses quicksort assertions, an overflow-inducing generated input, and a fuzzed string parser to illustrate checked behavior and failures.
What it assumes
Assumes familiarity with Rust rather than teaching basic syntax from zero.
What you can do after
Practice/perform test-case selection across public and private boundaries, and use generated failures to investigate missed edge cases.
How it connects
Connects test cases to unit testing, integration testing, property testing, fuzz testing, code coverage, and refactoring.

Also explained in

Compare how 53 books explain test →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Code Like a Pro in Rust. The section links point to the parts of the book it draws on.