---
title: "Testing, builds, and code quality"
chapter: "16"
---

# Testing, builds, and code quality

A reliable build produces the same reviewed artifact from the same source and
toolchain.

## Test layers

- Unit tests: one behavior in memory, fast and focused.
- Integration tests: real database, filesystem, network, or broker boundary.
- Contract tests: producer and consumer agree on a protocol.
- Property tests: invariants across many generated values.
- Concurrency tests: coordinated races, timeouts, cancellation, and invariants.
- End-to-end tests: a few critical deployed journeys.

Use JUnit 5 concepts such as lifecycle, parameterized tests, nested tests,
assertions, and timeouts. Tests should be deterministic and independent.

## Build tools

Maven and Gradle compile, test, package, resolve dependencies, and run plugins.
Use the Maven/Gradle wrapper, Java toolchains, dependency locking or controlled
resolution, reproducible archive settings, and CI verification.

## Static quality

Compile with useful warnings. Apply formatting, static analysis, dependency
vulnerability scanning, architecture rules, and coverage as evidence—not as
substitutes for review.

## Test design

Assert observable behavior. Avoid sleeping to coordinate concurrency. Use
latches, barriers, fake clocks, and deterministic executors. Test boundaries:
zero, negative, maximum, empty, null where allowed, overflow, DST, duplicate
events, partial I/O, interruption, and malformed input.

## Delivery

Package immutable JARs or runtime images. Record source revision, JDK, dependency
graph, SBOM, checksums, and provenance. Deploy progressively and verify user
health before promotion.

## Feynman check

A unit test checks one gear. An integration test connects machines. A
reproducible build is a factory that produces the same sealed parcel every time.
