Unit and integration
The layer that buys the most confidence per second of runtime. Dense logic tested directly, real databases and queues in containers rather than mocks, fixtures versioned so any run reproduces anywhere.
Containerised test suiteQuality engineering
Testing work for a product that already has users and cannot afford a bad Friday. We build the suite, the harness and the merge gate, then hand all of it to your team.
Most teams who call us are not short of tests. They are short of a suite anyone believes. The build goes red, someone reruns it, it goes green, and the release ships on a hunch. At that point the suite has stopped being a safety net and become a tax, and every test added makes the tax bigger. The work is to reverse that: to get a suite where a red build is news and a green build is permission to ship.
So we do not sell coverage. A percentage records that a line executed while a test was running, not that anything would have failed had the line been wrong. We judge a suite by whether it catches faults we inject on purpose and whether it would have caught your last ten incidents. The same scepticism applies to generated tests: they are strong on the happy path and prone to asserting whatever the code does today, bugs included. No test is accepted here until it has been seen failing against broken code for the right reason.
| What is true of this work | What it forces | What we do about it |
|---|---|---|
| The product changes under the tests | Tests coupled to structure break | Locate by role, not selector |
| Production data cannot enter staging | No realistic fixtures by copying | Generators and masked subsets |
| The gate must stay fast | Slow suites get routed around | Blocking suite budgeted under ten minutes |
| A red build blocks everyone | Flakes teach the team to rerun | Quarantine with owner and deadline |
| AI output differs every run | Exact-match assertions fail constantly | Graded rubrics with tolerance bands |
The layer that buys the most confidence per second of runtime. Dense logic tested directly, real databases and queues in containers rather than mocks, fixtures versioned so any run reproduces anywhere.
Containerised test suiteA deliberately short list: signing up, paying, the path where money moves. Elements located by role and label, not CSS position, run against a fresh environment per pull request.
Pinned journey setSchema-driven checks generated from your OpenAPI definition, plus consumer-driven contracts so a provider deploy cannot silently break a client. One question answered before release: can this version deploy safely?
Published consumer contractsThresholds taken from the latency and error budget you actually promise, then a spike above it and a soak long enough to expose leaks. Dependencies slowed and killed on purpose.
Load and soak scriptsFixtures that keep referential integrity across related tables, seeded deterministically so a failure reproduces, and masked where a record must come from production. Every database dies with its run.
Masked data generatorsQuality that varies run to run needs a baseline, not an assertion. We freeze a graded example set, have your domain experts settle the disputed cases, and fail on score drift.
Graded example setWe start from your incident log, support tickets and commit history, not your feature list. Every area is scored on blast radius and change frequency, and that ranking decides what gets tested first.
You getRanked risk map with coverage targets
Before the suite exists we build the machinery it needs: runner, ephemeral environment, seeded data, parallel sharding and reporting your team can read without us. Three tests prove the pipeline before volume arrives.
You getWorking harness in your pipeline
We work down the ranking, reproducing real defects from your history as failing tests first. Then we mutate the source, rerun against unchanged code to expose flakes, and cut dependencies mid-run.
You getGreen suite plus mutation and flake report
We set the gate with you: which checks block, which only report, and who may override. It lands in branch protection, written down. Handover ends with your engineers triaging a deliberately broken build.
You getWritten gate policy and runbook
Automate the regression, keep humans for exploration and judgement.
A scripted test only re-checks an expectation someone already wrote down; judging whether a screen makes sense stays human. The exception inside automation is generative — property-based tests and schema fuzzing reach cases nobody thought to write.
We’d choose otherwise whenthe product still changes shape weekly and every recorded test dies within a sprint.
Fewer journeys than you want, only where failure costs money.
End-to-end tests are the slowest to run, the likeliest to flake, and the most expensive to keep alive through a redesign. A handful of pinned journeys — signup, payment, the path where data moves — earns its keep. The rest belongs lower down.
We’d choose otherwise whenyour system is mostly orchestration over third-party services, where unit tests prove almost nothing.
Block on fast and deterministic; warn on everything else.
Unit, integration, contract verification, the pinned journeys, and coverage measured on the diff rather than a global percentage that punishes whoever touches an old file. Load, mutation and the full sweep run nightly. A gate people routinely override teaches everyone that red means nothing.
We’d choose otherwise whena warning has run clean for a fortnight — then it earns promotion to blocker.
Contracts once you pass two services or one external consumer.
Integration on a shared environment becomes a queue: teams wait for a slot, failures are irreproducible, and nobody owns the breakage. Contracts move that check into each side’s own pipeline. They demand discipline in return — a contract nobody updates is a lie you now trust.
We’d choose otherwise whenyou ship one deployable to one client and staging genuinely reproduces production.
Environment and data setup, not the number of tests. If one journey needs a seeded tenant, a stubbed payment provider, a queue drained before the assertion and a nightly job triggered by hand, the harness is the expense — tests after it are cheap. A system that runs locally with one command costs a fraction.
You own all of it, transferred outright on final payment and living in your repository from the first commit. Open-source runners, no proprietary scripting language, no test-management subscription holding your cases hostage. The genuine portability risks are hosted device grids and contract brokers; we name each at design time and say what running without it takes.
Every failure is classified within a day as defect, environment or flake. Flakes get quarantined with a named owner and a deadline rather than muted, and if the flake rate passes the budget we agree, fixing it takes priority over writing new tests. A suite the team has learned to ignore costs more than none.
Not with string comparison. We build a versioned set of graded examples, score them against a written rubric, and set thresholds as bands so ordinary variation does not fail the build while a genuine regression does. Around that core go deterministic checks: schema validity, tool-call correctness, refusal behaviour, cost and latency ceilings.
We keep whatever earns its place, and you see the deletion list before anything goes. The triage is simple: which tests have ever caught a real defect, which fail for reasons unrelated to correctness, which assert nothing at all. Unit tests usually survive it. Recorded browser scripts coupled to markup are cheaper to rewrite.
Thirty minutes with the engineers who would build it. You leave with a scope, a timeline and a fixed price — or an honest no, and the reason why.