How do you design for testability? What do you ask developers to build in?
60-second answer
Testability is designed, not added later. I ask for stable test hooks like data-testid attributes and accessible roles; APIs for setup and teardown of test data; feature flags and configuration that tests can control; deterministic behaviour through injectable clocks and seeds; observability with correlation IDs, structured logs and health endpoints; idempotent operations and clear error contracts; and the ability to run services locally or in containers with their dependencies stubbed. I raise these in design reviews, and I measure the effect through faster, more reliable tests.
Explanation
Testability checklist for a design review:
- Can we observe state? (APIs, logs, metrics)
- Can we control inputs? (flags, time, data)
- Can we isolate the component? (interfaces, containers)
- Are failures explicit and distinguishable? (error codes)
- Is behaviour deterministic?
- Are there seams for mocking third parties?
Frame requests as reducing cost of change for developers too.
Example
Adding a test-only POST /test/orders/{id}/advance-to/SHIPPED endpoint (disabled in production) cut order-state tests from 4 minutes of waiting to seconds.
Sample code
export interface Clock { now(): Date }
export const systemClock: Clock = { now: () => new Date() };
export function isOfferActive(offer: Offer, clock: Clock = systemClock) {
const t = clock.now().getTime();
return t >= offer.startsAt.getTime() && t < offer.endsAt.getTime();
}
// Test: pass a fixed clock, no sleeping or time-zone surprises