liveBook · Manning

White-box testing

As explained in Functional Design and Architecture: Examples in Haskell

White-box unit testing is testing that verifies internal code paths and implementation details in addition to externally observable behavior.

White-box testing verifies behavior with knowledge of internal code paths, dependencies, and implementation details. It is especially useful when public interfaces alone cannot reach subtle branches, failures, or effectful interactions. section 15.1

A testable design hides each external subsystem behind an interface, keeps business logic dependent on those interfaces, and permits every implementation to be replaced with a mock. Tests can then run business logic in a controlled environment, selecting dependency results and driving specific internal paths. section 15.2.1 section 15.2.2

Figure 15.2 Real and test environments, white-box tests, and mocks

The real environment supplies live implementations; the test environment substitutes mocks so a test can control calls beneath the business logic. section 15.2.1

White-box tests can be used to:

  • Lock down sensitive business-logic behavior and protect it from regressions. section 15.2.3
  • Simulate external-service outages and verify the application’s response. section 15.2.3
  • Exercise IO-bound scenarios, including effects, algorithms, and service interactions. section 15.2.3
  • Record expected behavior as executable documentation or investigate stability with fuzzy testing. section 15.2.3

Testing a failed game load

A game-loading test supplies a mocked database connection and a successful labyrinth lookup, then makes the player-position lookup return a database error. The test runs loadGame and asserts that the expected exception is raised. After refactoring, a safe wrapper can convert exceptions into Either results while mocks still steer the failure path. section 15.2.3 section 15.2.3

Control has a cost. Comprehensive internal-path coverage can become laborious, brittle, and expensive to maintain, slowing delivery. Prefer meaningful tests aimed at important requirements and risks rather than treating full coverage as the goal. section 15.2.3 section 15.3

A configurable test runtime can mix mocked, test, and real interpreters, trace call stacks and transferred data, simulate service responses, and support deterministic ordering for concurrent work. Such infrastructure can serve unit, integration, or functional tests. section 15.2.4

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Explains interface-based mocking, stateful mock interpreters, failure tests, runtime dispatch, and tracing; warns against exhaustive coverage.
Examples
Demonstrates mocked random values for a game picker and mocked KV-database failures while loading a labyrinth game session.
What you can do after
Apply it via mock interpreters and controlled runtimes to test sensitive branches and external-service failures.
How it connects
Connects white-box testing with mocking, free monads, interfaces, testability, regression testing, and integration testing.

Also explained in

Compare how 3 books explain white-box testing →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.