The bug that passes every test and does nothing. I let an AI write more than I read, and the tests that would have caught all of it.
DEV Community

The bug that passes every test and does nothing. I let an AI write more than I read, and the tests that would have caught all of it.

Six real silent failures from 14 months of shipping alone, the week I let an AI write more than I read, and the tests that would have caught all of it. A crash is honest. It tells you something went wrong. Silence is also a claim. It says everything went fine. That claim is far more expensive when it is false, and it is the one we are now producing at scale. I have shipped a Windows system monitor in public for fourteen months, alone, in the evenings after work. Everything is on GitHub from the first commit, so this is a record I cannot edit. Here are six failures from it, none of which crashed, all of which passed every test I owned. - Browse the source on GitHub - Install PC Workman from the Microsoft Store Read the project story and technical guides โค๏ธ If you want to support me, click here :) โค๏ธ 1. The button that reported success and saved nothing A fan curve editor. Drag points, click Apply, green message. The message appeared. The file was never written. Two releases of users setting a curve, seeing a confirmation, restarting a week later and finding defaults back. Zero reports, because user cannot tell the difference between "it saved" and "it said it saved." A success message is not evidence of success. It is a string. 2. The reading that was always empty temps = psutil.sensors_temperatures() # {} on Windows, always cpu = temps.get("coretemp", []) # [] if cpu and cpu[0].current > 80: # never true warn() psutil.sensors_temperatures() returns an empty dict on Windows. Not an error. So the thermal monitor ran on schedule, found nothing to warn about, and reported all clear. For months. The test asserted warn() was not called when temperatures were normal. An empty reading is indistinguishable from a normal reading if you never assert a reading exists. # Weak: passes when temps is empty, which IS the bug def test_no_false_alarm(): assert not monitor.check(temps={}).warned # Stronger: the reading itself is the subject def test_temperature_source_returns_data(): reading = sensors.read_cpu_temp() assert reading is not None assert 0 [^]]+]', idx, regexp=True) The unit tests used Python's re . The widget's search is evaluated by Tcl, whose bracket expressions do not treat [^]] same way. Two engines, one string, no error message. Every link rendered as plain text. Fix: search for a literal prefix, parse with the engine the pattern was written for. pos = text_widget.search('[-> ', idx) # literal, engine-agnostic m = re.match(r'[-> ([^]]+)]', line_text) # Python parses Python A git reset --hard that wiped a day of uncommitted work. Recoverable only because a full backup existed from an hour earlier. A cleanup script that ate 38 commas. A punctuation pass across 15 HTML files removed the comma after 38 closing tags. "Driver conflicts, leftover GPU packages" became "Driver conflictsleftover GPU packages" . Nothing crashed. Every page rendered perfectly. None of these threw an exception. All of them produced output that looked right. This is not an argument against working this way. Project moves faster because of it. It is an argument about where review has to happen. Generated code is fluent by construction: it compiles, reads well, uses the right function names. Fluency is not correctness, and fluency is exactly what makes the difference invisible. Four rules that came out of that week Verify facts, never accept plausible ones. If a value can be read from the system, read it. A plausible fact is more dangerous than a missing one, because a missing one gets checked.Ask which engine actually runs this. Before trusting a green test, ask whether it exercises the same runtime the user hits. Never let a destructive command through unread. Anything with--hard ,--force ,rm ,DROP orreset gets read character by character. Back up first.Check the output, not the exit code. The comma script "succeeded". The vendor entries "succeeded". All six bugs above "succeeded". The rest of th Write a ratchet the same day. The fix is half the work. The other half is a test that fails the build if it comes back. They only turn one way. Every bug here has one now. Click the thing. After a refactor that split one module into seven, 96 tests stayed green while every sidebar page silently fell back to the dashboard. Not one test built the real window. Five minutes of human clicking caught what the whole suite could not. Instrument the first divergence, not the damage at the end. Three days on a replay bug, measuring how far apart two runs ended up. That number tells you the size of the damage and nothing else. Logging first tick where they stopped agreeing turned evenings into minutes. Trust probes, not names. Detecting a read-only install folder by checking whether the path contains WindowsApps is a guess about the world. A write probe is a fact about it. Why this happened at all I build alone. No reviewer, nobody to ask "did you check that it actually saved?" These bugs did not survive because they were subtle. Several were obvious. They survived because exactly one person could have caught them, and that person had already decided the feature worked. You do not write a test for a feature you already believe works. That is not a technical problem. It is the problem of being the only witness. I am 22, in Poland, self-taught after a technical school, and twelve projects died before this one. The laptop most of it was built on is from 2014 and hits 94 degrees. The day job has been a warehouse, then welding plastic, now a taxi. You do not do careful review at midnight after a twelve-hour shift. You do the thing that feels finished. Everything in the first half of this article is what "feels finished" looks like six months later. Three things help, and none is discipline: write in public (the difference between how you describe a feature and what it does is where these live), ship to people who owe you nothing (a tester refused to accept "it works on my machine" about a console that would not close, and he was right), and keep a log for the version of you in six months. We are getting better at producing code that reads correctly and faster at producing it. Neither makes code more likely to do what you meant. Do not accept an outcome as proof of an action. Not from your code, not from your tools, not from anything that generates text for you, and not from yourself at midnight. Look for the receipt. I build PC Workman, a free Windows system monitor with a fully offline assistant. 331 automated tests and a public list of everything above. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.