8 Evaluation is king: how to trust code you didn’t write
AI-generated code changes the software workflow because the main problem is no longer producing code, but deciding whether it should be trusted. The chapter argues that generated code behaves like legacy code from the moment it is created: it has no human author to explain intent, no built-in understanding of edge cases, and often looks deceptively polished even when it is wrong. This creates a growing trust deficit, where code can be produced much faster than it can be verified, and where familiar habits like quick review or “works for me” checks are no longer enough.
To close that gap, the chapter presents evaluation as a layered pipeline rather than a single test. Basic gates such as compilation, type checking, linting, dependency scanning, and diff checks catch structural and security issues, but they do not prove correctness. The next layer uses tests as contracts: manual exploration helps form a mental model, unit tests define intended behavior, test-driven prompting turns tests into specifications, and higher-signal techniques like property-based testing, fuzzing, mutation testing, and differential testing are used to attack blind spots and uncover hidden failures. The core lesson is that tests should describe intent, not implementation, and that AI-generated code needs adversarial verification because its blind spots often overlap with the blind spots of the tests humans naturally write.
The chapter then expands evaluation to the system level and production. Design by contract, contract testing, integration tests, and end-to-end tests help ensure the code fits the surrounding architecture and does not silently break other services or workflows. For critical cases, stronger methods such as formal verification, stronger type systems, and SMT solvers offer higher assurance, while runtime verification, observability, canary rollouts, and chaos testing catch the failures that only appear under real conditions. The overarching message is that the developer’s role shifts from code author to trust engineer: someone who knows how to measure uncertainty, choose the right verification method for the risk, and build confidence that AI-generated code deserves to exist.
Impact vs Ease of Implementation.
Example of Approval Request.
Example of Visual Regression Tests.
Modern LLM verification stack.
Summary
- AI creates a trust deficit: code is produced faster than it can be verified, making evaluation the new bottleneck.
- Benchmarks like HumanEval and SWE-bench measure isolated problems, not production readiness.
- Static analysis catches errors AI rarely makes while missing errors AI makes constantly.
- Unit tests tend to verify the cases AI handles well - the blind spots correlate.
- Test-Driven Prompting shifts the burden to thinking of edge cases before generation, not after.
- Code coverage can be gamed when AI generates tests alongside implementation.
- Property-based testing does not only find bugs in code. It finds the places where you never had a specification.
- Mutation testing measures test quality - surviving mutants reveal what your tests don't actually verify.
- Contract testing catches breaking changes AI makes without knowing other systems depend on current behavior.
- Characterization testing detects collateral damage when AI modifies more than intended.
- Formal methods provide mathematical proof - and AI is lowering the barrier by automating annotations.
- Runtime observability turns production into continuous testing where every request is a test case.
- Verification investment should match system criticality - regeneration can be cheaper than debugging.
- QA skills become core engineering competencies when code generation is automated.
Vibe Engineering ebook for free