$4.3M seed + Cue is liveRead the announcement
Blog/Research/Nearly 1 in 4 tests Claude wrote were useless. Then we made our test runs 9x faster
Research

Nearly 1 in 4 tests Claude wrote were useless. Then we made our test runs 9x faster

Nearly 1 in 4: in two apps built by Claude coding agents, 23% of the browser tests could not fail on the product's own features: 133 of 578 tested a demo the product does not have, or were empty. Across three builds, the tests caught 0 of 65 bugs before a human did. Then we made our own test runs about 9x faster, from 55 minutes to about 6. What went wrong, explained from zero, and what to change on Monday.

Author
Nexus Team
Published
Sep 30, 2026
Last revised
Sep 30, 2026
Reading time
22 min
Research note1 in 4 browser tests could not fail0 of 65 bugs caught first9x faster test runsSeptember 2026
The short version
  • Nearly 1 in 4 browser tests could not fail. In two apps built by Claude coding agents, 133 of 578 browser tests tested a demo the product does not contain, or were empty. They could not fail on anything the product itself does.
  • 0 of 65. Across three builds, humans found 65 bugs. No test caught a single one first. In 34 cases a test sat on the exact path and was green while the bug was live.
  • The important tests did not run. 145 unit-test files in one app never ran automatically. Our own guard rails run 15 of their 499 test suites automatically.
  • Red did not mean red. 217 of 287 "test finished" notices said "success" whatever the result.
  • Waiting was the default. 88% to 98% of test runs froze the agent. Our full test run took 55 minutes. Four plain fixes made it about 9 times faster.
  • Our own "useless" lists were partly wrong too. Two different reviews of what to delete had to be corrected on inspection.
  • My answer: judge each test by one question, "could it fail on something a user would see?" Make the default runner the gate, make red stop the work, and run tests in the background, in plain view.

1Why this matters

AI coding agents now write a large share of new software. Left to themselves, they also write tests. Lots of them. A team sees a wall of green checkmarks and concludes the software works.

That conclusion is the most expensive assumption in AI-built software right now.

  • A test suite is the last wall between a bug and your user. Nobody reads a thousand tests to check they mean anything.
  • Agents depend on tests more than people do. A developer notices when a screen looks wrong. An agent has no picture of the product. Between one task and the next, the test suite is its only memory of "this works".
  • A hollow suite makes the agent blind, and it does not know it. It will report "all tests pass" in good faith while the one screen your customer uses is broken.

The owner of these builds put it bluntly: "I'm sure you have a lot of useless test and are not running important tests." So we stopped building and counted.

So what? If agents write your code, the tests are the agent's only eyes. A green suite that cannot see the product is worse than no suite, because it tells everyone the product works.

The words, explained once

This section assumes you have never written software. If you have, skip to section 3.

The agent

  • Language model. Software that reads text and writes text.
  • AI coding agent. A language model given tools: it reads files, edits them, runs commands and reads the results, in a loop, until a task is done. Here, the agents were Claude.
  • Helper agents. A lead agent can hand parts of a job to helpers that work at the same time.

The test

  • Test. A small program that checks another program: set up a situation, do something, check the result. "Put 2 and 2 in the calculator, press equals, expect ."
  • Green and red. A test that passes shows green; one that fails shows red. The whole value of a test is its ability to go red. A test that never can is decoration.
  • Unit test. Checks one small piece of code on its own. Fast, and blind to everything around it.
  • Journey test, also called an end-to-end or browser test. Drives the real app like a person: open the browser, click, type, check what appears on screen. Slow, and the closest thing to a real user.
  • Regression test. Written after a bug is fixed, so that the same bug cannot come back unnoticed.

The fakes

  • Mock. A fake stand-in for a real service. It answers the way the test author expects, which is not always the way the real service does.
  • Fixture. The pretend data a test runs on: three invented hotels, one invented customer.
  • Local build versus hosted app. The app on the developer's computer, versus the real one on the internet that users open.

The machinery

  • CI, continuous integration. A robot that runs the tests on every change and refuses the change if a test fails.
  • Default runner. Whatever runs the tests when nobody thinks about it. A test it does not load runs only when someone remembers. In practice, never.
  • Hook. A small program that watches an AI agent and steps in at set moments. Our own agents run inside several hundred of these checks. We call them the guard rails. They have tests too, and those tests are part of this study.
  • Foreground and background. In the foreground, the agent waits for the test and does nothing else. In the background, the test runs alone and the agent keeps working, then gets a notice.
  • Exit code. The number a program returns when it ends. usually means success.
So what? Every word above hides a gap between the test's world and the user's world. The mock is not the service, the fixture is not the data, the local build is not the hosted app. The rest of this piece is about those gaps.

3What we measured

Three real builds, all done by Claude coding agents in September 2026.

The three builds

  • A hotel group's field app. Staff prepare hotel visits, fill in a visit on a phone or laptop, dictate notes and send a report. unit tests, active journey tests, and extra check and probe files. We studied a build session of about a week.
  • A tender-writing app. A team answers public tenders: a document editor, a compliance matrix that scores the answer against the requirements, a radar of upcoming tenders, and a chat assistant. unit test cases and browser test cases of its own. Built over hours.
  • Our own agent guard rails. The hooks above. test suites, roughly individual checks.

Four questions per build

  • Every bug a human reported, from the owner or from a client through the owner. A bug reported three times counts once.
  • Was there a test on that exact path, and was it green while the bug was live?
  • What do the tests themselves check? We read and graded them, one by one where we could.
  • What happened at each test run? About runs, replayed from the agents' own session records: how long, did the agent wait, what happened after a failure.

One rule

Every number here was counted from the code, the session records or a fresh test run. An agent saying "done" or "all green" was never accepted as evidence. As you will see, that rule is the whole story.

So what? These are not benchmark toys. They are real builds with real owners and real bugs, which is why the results transfer to your team.

4Zero of

Humans found 65 bugs across the three builds. No test caught any of them first. Not one.

hover or tap a row
A test on the path was green while the bug was liveA test existed, but skipped, stale or never runNo test on the path
Tender-writing app, bugs
caught
Hotel group's field app, bugs
0 caught
Our guard rails, defect classes
0 caught
All three, 65
0 caught
Figure . Every human-reported bug in the three builds, counted once, as a share of each build's bugs. Black is the worst case: a test sat on the exact path, ran, and said everything was fine. of 65.
So what? "We have a test for that" is not an answer. In more than half the cases we did have a test for that, and it was green.

What green-while-broken looks like

  • The test was built on the wrong answer. The owner of the tender-writing app said app state belongs in a database, not a shared file. The agent's tests required the shared file, and stayed green until the owner noticed.
  • The test faked the one step that broke. A user selects a paragraph in the editor and asks the assistant about it. The test handed the selection to the panel directly. The bug was that the selection never left the editor.
  • The test used tidy data. The owner could not open a document on the live app. The test had opened one too: a known file with a plain name, on the developer's computer. The owner's file had a curly apostrophe in its name, and the hosted storage refused it.
  • The test used a clean browser. In the field app, an "add address" button did not work for the owner, twice. The tests passed. They ran in a clean automated browser; the owner's browser had an ad blocker that hid the button because of its name.
  • The test used short data. A data-table test fed in months of figures. The real hotel had .

Our own code did it to us

  • Two guard-rail suites checked for the exact line of code that later caused a false alarm. They did not miss the defect. They locked it in: fixing it would have turned them red.
  • One afternoon, the full test run went green minutes after a live trial of the same guard rails stopped the agent times, against a budget of 1.
So what? The question is never whether a test exists. It is whether the test runs in your user's world: the hosted app, real data, the real browser, the real click path.

The useless

Now the provocative number, and exactly where it comes from.

Take the browser tests of the two apps, the tests meant to act like a real user. There are . of them, 23%, could not fail on anything the product itself does.

hover or tap a row
Share that could not fail on the product's own features
Field app journeys: starter demo
of 516
Tender app browser cases: empty
of 62
Both apps
133 of 578 ยท 23%
Figure 2. Browser tests in the two apps that cannot fail on the product's own features. A few of the demo journeys still exercise shared server code (section 5.2), so read this as "not testing the product", not "testing nothing at all".

5.1 Where the 23% comes from

  • 120 tested a demo app. The field app started from a starter kit: a ready-made skeleton that ships with a demo sales tool, with companies, deals and a kanban board. The field app has none of those screens. The demo tests were never removed, so every run still carefully tested a deals board nobody uses. That is 23% of the field app's journeys and of its test time.
  • 13 were empty. In the tender-writing app, 13 of browser test files are placeholders: a title marked "to do", with no test inside. A review round asked for the tests to be "listed", and they were listed.

5.2 Where our own "useless" verdicts were wrong

A provocative number deserves an honest footnote. Grading tests is itself a test, and it can be wrong in both directions.

  • The field app's build session checked our delete list item by item, and kept of its items. Two suites we called useless test live screens. One has passing checks. One is the only check for a set of figures. The loose probe files hold the only regression tests for three of the owner's bugs. One test was deleted.
  • The 6 kept include the 120 demo journeys, kept for now. Several of them exercise shared server code (sign-in, storage, permissions) that the real app uses too. They do not test the product's features, but they are not all worthless.
  • Our guard rails, reviewed by an AI reviewer, show the same pattern. It called roughly to of 499 suites useless. Four it named each cover at least one check that is live and enforcing today, and our own audit tool grades all four "keep".
  • Our automated audit erred the other way. It reported zero useless suites. Its detector for "tests the wording, not the behaviour" was broken, so it scored almost everything clean.

That is why the headline uses the narrow 23% and the narrow claim: tests that cannot fail on the product's own features. For everything wider, a "useless" verdict is a claim, and it gets checked before anything is deleted.

5.3 The zone around the 23%

  • Tests of the screen you replaced. The tender-writing app changed its document editor twice. Its editor browser tests still target the old one, and 9 skip themselves unless special settings are present. The editor people actually use has zero browser tests. Three unit-test files were pinned to the old editor so they would keep passing.
  • Coverage that follows the work, not the product. In the field app, of features have no journey test, including the whole new home screen. One feature holds journeys, of the suite, because each review round added its own file.
  • A "last verified" date on nothing. features with zero tests still show a date in the field app's feature list.
  • Tests of wording, not behaviour. In our guard rails, at least suites hold at least checks of the form "this exact text appears in the source code".
  • Never-green journeys. The tender-writing app's two best browser suites, for the compliance matrix and the radar, have never passed. Of browser runs, 5 passed, none of them those two. Nothing stopped the build.
  • Unit tests were mostly fine. In the tender-writing app, the 5,425 unit cases were mostly on target and green. The problem sits in the layer meant to act like the user, which is where users find bugs.
So what? Almost a quarter of the browser tests in two apps were not testing the product. Count yours the same way, then treat every "delete these" list, including an AI's and including ours, as a hypothesis to check.

6The tests that never ran

Worse than useless tests: the tests that mattered most did not run by default.

  • The field app. unit-test files never ran in CI or in the pre-release check. CI ran the build and the journeys; the pre-release check only read a stamp saying "the journeys passed in the last hours". Most of the regression tests for the owner's bugs lived in those 145 files. For days mid-build, there was no recorded green run at all. (The field app's session has since wired those unit tests into its pre-release check.)
  • The tender-writing app. CI fired only when someone proposed a change to the main branch. The agents worked on other branches and never did. So no browser test and no full run ever gated a change. The mutation tool, which breaks the code on purpose to check the tests notice, had reported a false score of zero for weeks.
  • Our guard rails. of 499 test suites run automatically. The other , , run only when someone launches them.
  • And the real thing was locked. of attempts to run the tender app's journeys on the hosted app stopped at the sign-in screen. The robot had no account. Nobody followed up, because nothing was waiting for the result.
So what? A test that the default runner does not load does not exist. Before asking whether your tests are good, ask which of them run when nobody remembers to run them.

7Red that meant nothing

A test runs and fails. That is the moment the whole system exists for. Here is what happened in that moment.

  • The failure notice said "success". The agents almost always added a small command after the test: print the last few lines, or a status message. The notice then carried the exit code of that printing, which succeeds. Of background test runs set up this way, notices said "completed, exit code 0" whatever the result. In the guard rails' main session, of .
  • The agent saw a slice. In the field app, of test runs were piped through a filter that showed a few lines. In the tender-writing app, main-session browser runs were cut so short that the pass or fail line never showed.
  • Failures got relabelled. In the tender-writing app, of failing runs never reached a pass. were called "pre-existing", "environment" or "another lane's problem". were closed with a "green" claim and no re-run.
  • Red got committed. In the field app, red runs were chained straight into saving and publishing the code. One helper agent, afterwards: "The suite shows failures, and my chain pushed anyway."

None of this is malice. Each move is locally sensible for an agent trying to finish a task. But nothing forced a red result to be dealt with, so red became a mood, not a stop sign.

So what? A test is only as good as what happens when it fails. Make red stop the work, and make relabelling a red a decision a human signs.

8Waiting for green

The owner's other complaint was simpler: the builds felt slow and the agent often looked idle. The records agree.

hover or tap a row
Share of test runs where the agent stopped and waited
Our guard rails
ยท h
Hotel group's field app
ยท h
Tender-writing app
ยท h
Figure 3. Share of test runs in the foreground, with total agent time blocked. Counted from every test run in the three builds' session records.
  • The agent froze. , and hours of blocked agent time.
  • The human saw nothing. No progress, no count, no time left. The owner typed "status" several times during runs, and once, after a long one: "I don't care about the test, let's finish this."
  • Background runs already worked. When a run did go to the background, the field app's agent kept working in of cases.

That quote is the real cost. When tests are slow, blocking and invisible, people resent them, and a team that resents its tests finds ways to skip them.

So what? An agent waiting on a test is not working, and a person who cannot see the test stops trusting it. Background by default, progress in plain view.

9From minutes to

Our guard rails' full test run had crept from about 6 minutes in mid-September to 55 by the end of the month. Four plain fixes made it about 9 times faster.

Table 1 ยท Where the 55 minutes went, and the fix
CauseWhat it didFixMeasured
A GB folder inside the test folderThree suites copied the whole test folder for each case, so each run copied the big folder over and overSkip that folder in the copy s per copy, down to s
suites in single fileThey touched shared files, so they ran one after another: of the runGive each a private copy, run them side by side s, down to s
Slowest suites started lastThe whole run waited on them; the slowest took s against a s limitStart the longest first897 s, down to s
Stopwatch checks checks in suites asserted "under N milliseconds" and failed at random on a busy machine, forcing full re-runsRun them alone, in a quiet speed run of the last reds
hover or tap a row
BeforeNew runner
Before
3,329 s
Proof run
376 s
Latest live run
327 s
faster on the proof run
55 minbefore
6 minafter
Figure 4. One full run of our guard rails' 499 test suites, before and after the four fixes in Table 1.
So what? Slow test runs are usually a handful of dumb causes: data in the wrong folder, work in single file, the slowest job last, stopwatch checks on a busy machine. Measure where the minutes go before buying a bigger machine.

10What we learned

Every finding traces back to five mechanisms. They are not specific to our agents. They are what any agent does by default, because they are cheapest.

Table 2 ยท Five mechanisms, one fix each
MechanismWhat it looks likeThe fix
Tests check parts, not what the user sees"a link exists", "a frame loaded", "this text is in the code"Assert the visible result, reached by the user's own clicks
Tests run in a world nobody useslocal build, invented data, clean browser, a server that never restartsHosted app, a test account, data captured from the real system
Coverage follows the work, not the product93 journeys on one feature, 36 features with noneStart from what must never break; each test names its risk
Nothing forces red to be acted on"pre-existing", a filtered exit code, a commit after a red runRed blocks "done" and the commit; relabelling needs a human
Runs are slow, blocking and invisible88% to 98% foreground, 55 minute runs, nothing on screenBackground by default, the real exit code, a live progress line

Three laws

  • A test counts only if it can fail on something a user would see. Not "does a test exist?" but "if this broke tomorrow, the way a user would notice, would this test go red?"
  • The default runner is the gate. Anything it does not load is not a test. The 145 unit files and the 484 local-only suites were written with care and protected nothing.
  • The builder does not grade its own tests. The same agent writing the feature and its test passes its assumptions on, including the wrong ones. A separate seat designs the test, from the user's side, before the code.

What already works

  • "Seen red first." When the field app's briefs required each new test to be shown failing on the old code first, the share of helper commits that said why a test existed rose from to .
  • Every finding becomes a test. Turning each adversarial review finding into a labelled test grew one of our suites from to cases, each a real past failure.

Why sentences did not work

  • This was not our first attempt. "Tests that prove nothing" shows up in previous improvement cycles.
  • Every past fix was a sentence in the agents' instructions. Sentences did not hold. What holds is structure: a check that refuses the commit, a runner that loads the tests, a notice that carries the real result.
So what? Telling an agent "write good tests" does not work; we tried fifteen times. Change what the system accepts: what counts as a test, what runs by default, what a red result is allowed to do.

11Eight moves for Monday

If your team uses AI coding agents, do these this week, in order. Each takes hours, not weeks.

  1. Count your zero. Take the last bugs a human found. Was a test on that path, and was it green while the bug was live?
  2. Count your theatre. Find browser tests that are empty, skipped, or aimed at screens you no longer have. Check each one, then delete the truly dead ones in one change, listed by name.
  3. Make the default runner load everything, on the branches your agents actually use. Then open the last automatic run and count what it ran.
  4. Give the robot an account on your hosted app, so browser tests run where your users are.
  5. Turn every human-found bug into a failing test first. Show it red on today's code, then fix until green, in a folder the default runner loads.
  6. Make red stop the work. A red test blocks "done" and the commit. "Pre-existing" or "flaky" needs a named person to agree.
  7. Run tests in the background, with the real result. No filter after the test command that swallows its exit code.
  8. Put a test line on screen. For example: running, of 499, about minutes left, last result green. Nobody paying for the work should have to type "status".
So what? None of this needs a new tool. It needs a team to decide that a green checkmark is a claim, and to start checking it.

12The fine print

  • Three builds, one month, one team's agents. The mechanisms are general; the exact percentages are ours.
  • Bugs are the ones humans reported. Bugs nobody noticed are not counted, so the true miss rate is no better than this and may be worse.
  • The guard rails count defect classes, not individual reports.
  • Some classifications are heuristic. About 5,400 test runs were classified by script, with samples checked by hand. The per-bug tables were read case by case.
  • The 23% covers browser tests in the two apps only, and means "cannot fail on the product's own features". Some demo journeys still exercise shared server code.
  • The speed "before" run shared a busy machine. An earlier run the same day took s. The new runner is still about times faster than that.
  • We did not count duplicates.

13Glossary

AI coding agent
A language model given tools to read, edit and run code, working in a loop until a task is done.
Background run
A test that runs on its own while the agent keeps working.
CI (continuous integration)
A robot that runs the tests on every change and refuses the change if a test fails.
Default runner
Whatever runs the tests when nobody thinks about it. Tests it does not load effectively do not exist.
Exit code
The number a program returns when it ends. usually means success. A command added after the test can replace the test's exit code with its own.
Fixture
Pretend data a test runs on. Useful, and dangerous when it is tidier than real data.
Foreground run
A test the agent waits on, unable to do anything else.
Green / red
Pass / fail. A test that can never go red proves nothing.
Hook
A small program that watches an AI agent and steps in at set moments.
Hosted app
The real app on the internet, as opposed to the local build on a developer's computer.
Journey test
A test that drives the real app like a person and checks what appears on screen. Also called end-to-end or browser test.
Mock
A fake stand-in for a real service, used in tests.
Mutation test
A check on the tests themselves: break the code on purpose and see whether any test notices.
Regression test
A test that catches a fixed bug if it ever comes back.
Starter kit
A ready-made app skeleton new projects start from, often with a demo and tests for that demo.
Unit test
A test of one small piece of code on its own.
  1. Bug counts: every human-reported bug in the three builds' session records, deduplicated; for the guard rails, defect classes found by the owner, a live trial or an adversarial review. "Green while live" means a test on the path passed while the bug was in the code.
  2. The 23% figure: 120 starter-demo journeys out of 516 active journeys in the field app, plus 13 empty placeholder cases out of 62 browser cases in the tender-writing app. 133 of 578.
  3. Speed: full runs of the same suites on 30 September 2026: s before; s on the new runner (proof run on a scratch copy, ); s on the live folder.
Method note: all figures counted from code, session records and fresh test runs; no agent self-report was accepted as evidence. Client builds anonymised.September 2026Series: building with agents
Written by
NT
Nexus Team
Next step

Tell us where the work piles up.

We build the first procedure with your team and run it with you.

Talk to our team
Nearly 1 in 4 tests Claude wrote were useless. Then we made our test runs 9x faster
ยง1/13 ยท 0% ยท 22 min left00:00/ 29:00Map

Start with one procedure

Tell us where the work piles up.

A Nexus engineer builds the first procedure with your team and shows it running in your own tools. Four weeks to a procedure that runs itself. And a number you can defend.

Talk to our team