<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gil Zilberfeld</title>
    <description>The latest articles on DEV Community by Gil Zilberfeld (@testingil).</description>
    <link>https://dev.to/testingil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4065719%2F5d44e120-5e4a-4ae4-ae55-1fbffc2898d4.png</url>
      <title>DEV Community: Gil Zilberfeld</title>
      <link>https://dev.to/testingil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/testingil"/>
    <language>en</language>
    <item>
      <title>AI vs CI: Nobody Told the Pipeline</title>
      <dc:creator>Gil Zilberfeld</dc:creator>
      <pubDate>Thu, 20 Aug 2026 11:17:28 +0000</pubDate>
      <link>https://dev.to/testingil/ai-vs-ci-nobody-told-the-pipeline-4e88</link>
      <guid>https://dev.to/testingil/ai-vs-ci-nobody-told-the-pipeline-4e88</guid>
      <description>&lt;p&gt;CI is so commonplace these days, we don’t often think about why it’s there. And that reasoning really matters these days, because of how we use it.&lt;/p&gt;

&lt;p&gt;Especially when you’re writing AI agents and expect the CI system to run a regression test suite, and sound the alarm when something goes wrong.&lt;/p&gt;

&lt;p&gt;Here’s a funny story you may not know. CI - Continuous Integration – was not originally a tool category. It’s a process - it’s how you continuously integrate pieces of code together.&lt;/p&gt;

&lt;p&gt;Anyway, why do you need this process anyway? Because you’re scared. You’re terrified that integration broke something.&lt;/p&gt;

&lt;p&gt;So what do you do? You look for approval. An automation system that runs all the tests all the time is our approval of choice.&lt;/p&gt;

&lt;p&gt;That’s how CI became a tool category. Because in its heart, it’s a simple automation pipeline.&lt;/p&gt;

&lt;p&gt;So, that automation’s holy grail is speed, right?&lt;/p&gt;

&lt;p&gt;Wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mission was to kill “Works on my machine”
&lt;/h2&gt;

&lt;p&gt;Remember when we wrote software in a cave, and we had a sticker on our computers – “Works on my machine. Don’t run it on another cave”?&lt;/p&gt;

&lt;p&gt;Ah, the good old days.&lt;/p&gt;

&lt;p&gt;Because the CI automation #1 OG mission was to kill “Works on my machine”. How? By creating a repeatable process. Independent of all the weird installs on my machine. Multiple versions of libraries. And different configurations. And admin hacks.&lt;/p&gt;

&lt;p&gt;The CI builds, packages, runs and tests the software every time the same way. That way, if a test turns red, you know something bad happened, because it was green until now. And why your stomach turns, when it flakes between red and green – that’s the feeling of lost &lt;a href="https://testingil.com/2023/09/the-4-attributes-of-testability-reproducibility.html" rel="noopener noreferrer"&gt;repeatability&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Yes, repeatability brings bliss. Well, it did, before AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then AI showed up
&lt;/h2&gt;

&lt;p&gt;If your app does not touch AI (although building with code agents, can sometimes count as “touch”), you’ll continue to feel that bliss.&lt;/p&gt;

&lt;p&gt;But if you’re developing AI-based features, or agents, or vibe-coding, you’re in for a new experience every time you push your code (or prompts) into CI.&lt;/p&gt;

&lt;p&gt;Things are not repeatable anymore. Models change, sometimes without warning. And always under your feet. And when a model changes, does it trigger a run?&lt;/p&gt;

&lt;p&gt;You wish! Your alert system is malfunctioning.&lt;/p&gt;

&lt;p&gt;And the worst part is not a regression. Although if it’s a bug in a prompt, you may not be able to &lt;a href="https://testingil.com/2026/07/testing-ai-generated-code-prompt-not-a-fix.html" rel="noopener noreferrer"&gt;fix it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No, the worst part is that Green today doesn’t tell you what kind of Green it is. Things are no longer Working or not, they are Work-ish. But even that’s not the same work-ish every day.&lt;/p&gt;

&lt;p&gt;So we’ve got fewer triggers, results we can’t read, and on top of it – every run means something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the solution?
&lt;/h2&gt;

&lt;p&gt;Repeatability gives us confidence. CI is the process, and tools, that give us the approval we seek, and the confidence we have comes from that repeatability.&lt;/p&gt;

&lt;p&gt;We can’t rely on the trigger anymore, but we can initiate our own runs. And since one run is not enough, we need to run more and look at the trends. Catch drift before it ships.&lt;/p&gt;

&lt;p&gt;What happens to quality when AI meets CI? We need to get back to the reasoning, and change how we manage quality.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://testingil.com/2026/08/ai-vs-ci-repeatability.html" rel="noopener noreferrer"&gt;testingil.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm Gil Zilberfeld. I teach API testing and test automation, and I write about what AI-generated code does to quality.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>programming</category>
      <category>codequality</category>
    </item>
    <item>
      <title>It's Almost Like You Need an Actual Programmer</title>
      <dc:creator>Gil Zilberfeld</dc:creator>
      <pubDate>Thu, 13 Aug 2026 07:07:33 +0000</pubDate>
      <link>https://dev.to/testingil/its-almost-like-you-need-an-actual-programmer-19ko</link>
      <guid>https://dev.to/testingil/its-almost-like-you-need-an-actual-programmer-19ko</guid>
      <description>&lt;p&gt;Vibe coding ain’t what it used to be.&lt;/p&gt;

&lt;p&gt;Back in the old days (2 years ago), we conjured up apps with our own programming language.&lt;/p&gt;

&lt;p&gt;Turns out, it does work, but more for prototypes. If you want an actual working production app, you need that thing from before. How do the old timers call it? Ah yes. Code.&lt;/p&gt;

&lt;p&gt;So our builder says to the genie: “Code me this”.&lt;br&gt;
And the genie does build this. Mostly.&lt;/p&gt;

&lt;p&gt;When we’ve got a prototype and it’s working, two things happen. The first thing is management thinks they have an actual product. In our case, it’s the builder that thinks “code me this” is simply a translation layer.&lt;/p&gt;

&lt;p&gt;But then, another thing happens – we now have to take care of our puppy. I mean the code.&lt;/p&gt;

&lt;p&gt;As long as we don’t need to touch it, it doesn’t matter what it looks like. But then we do.&lt;/p&gt;

&lt;p&gt;So what does our hero think? What worked before, will work again. He tells his favorite code agent – “build me my greatest feature yet”.&lt;/p&gt;

&lt;p&gt;But then weird things start happening. Bugs that weren’t there. Multiple tries of code changes – costly ones, mind you. Performance slows down.&lt;/p&gt;

&lt;p&gt;It’s almost like you need an actual programmer to do the work.&lt;br&gt;
And you do. You know what helps developers? And coding agents?&lt;/p&gt;

&lt;p&gt;Clean code. Readable, maintainable code. The classics are still with us.&lt;/p&gt;

&lt;p&gt;Now, coding agents are getting better at producing code. However, they are only  as good as the code they are trained on. Now think – what do you think the average level of code out there is?&lt;/p&gt;

&lt;p&gt;Exactly. That’s what you’re getting.&lt;/p&gt;

&lt;p&gt;So if you are on a transition from prompts to code, it may look like continuing vibing is the shortest way to more features. Yet, the first thing you need is a good platform to grow your code.&lt;/p&gt;

&lt;p&gt;Now it’s time to take control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the code.
&lt;/h2&gt;

&lt;p&gt;You’ll do this first anyway. The code is the only truth you have. The prompts you used before are scattered across forty chat sessions and there were never any docs.&lt;/p&gt;

&lt;p&gt;Just know what you’re up against. Agents drop a lot of code, and after ten files your eyes glaze over. You won’t read all of it, but try to understand the important bits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write down what it should do.
&lt;/h2&gt;

&lt;p&gt;Ask the agent to derive documentation from the codebase. It’s fast and it beats no docs at all.&lt;/p&gt;

&lt;p&gt;But know what you got. Those docs describe what the code does, not what it should do. If there’s a bug in there, it appears as a requirement. Review and sieve out the wrong stuff.&lt;/p&gt;

&lt;p&gt;If you can find them, collect your prompts. They were the intent for building the app.&lt;/p&gt;

&lt;p&gt;Review both, and drop everything that doesn’t add up. Now you have a documented system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now write tests. Against the requirements.
&lt;/h2&gt;

&lt;p&gt;It’s tempting to generate tests for what’s already there. And for legacy apps, I recommend capturing existing behavior of undocumented knowledge built up for ten years.&lt;/p&gt;

&lt;p&gt;But here? You’re better set. The intent is still around. Capture what the code does today and you’ve just made every mistake a requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then you can change it.
&lt;/h2&gt;

&lt;p&gt;Including asking the genie to change it for you – which is the part everyone wants to skip to.&lt;/p&gt;

&lt;p&gt;But now, with documentation and tests in place, now it’s a lot safer to make changes.&lt;/p&gt;

&lt;p&gt;Next you need to understand the principles of Clean Code. If you don’t, you may ask the genie to change the code for you, but you’ll get more of the same. We don’t want more of that mess.&lt;/p&gt;

&lt;p&gt;Exactly like programming. Who knows, maybe you’ll become one eventually.&lt;/p&gt;

&lt;p&gt;So what do you say – Are you ready for clean up?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://testingil.com/2026/08/its-almost-like-you-need-an-actual-programmer.html" rel="noopener noreferrer"&gt;testingil.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm Gil Zilberfeld. I teach API testing and test automation, and I write about what AI-generated code does to quality.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>programming</category>
      <category>codequality</category>
    </item>
    <item>
      <title>The New Technical Debt</title>
      <dc:creator>Gil Zilberfeld</dc:creator>
      <pubDate>Thu, 13 Aug 2026 07:06:32 +0000</pubDate>
      <link>https://dev.to/testingil/the-new-technical-debt-4ol4</link>
      <guid>https://dev.to/testingil/the-new-technical-debt-4ol4</guid>
      <description>&lt;p&gt;Is AI code debt the new technical debt? As I keep learning, generating code and examining it – it’s worse.&lt;/p&gt;

&lt;p&gt;In the old days, we worked hard to create technical debt. Just kidding, it was easy.&lt;/p&gt;

&lt;p&gt;Technical debt has many definitions, and origin stories. But one thing is common: We leave the code as it is, knowing it could be better. The debt is the gap of effort of making it better.&lt;/p&gt;

&lt;p&gt;And why the gap? Because we know we’ll see that code again. And when we do, it’ll be hard to change. Better code would have made it easier.&lt;/p&gt;

&lt;p&gt;Now we’re in the age of genies. They can write any code. They can change any code. Do we need to worry about AI code debt?&lt;/p&gt;

&lt;p&gt;Sure we do.&lt;/p&gt;

&lt;p&gt;AI code debt is exactly the same as technical debt – we’re leaving the code as it is, knowing it could be better. The gap is still the effort of making it better.&lt;/p&gt;

&lt;p&gt;But this time the gap is a lot bigger. There’s a lot more code, it’s probably a lot more complex, and some of it – let’s be frank – is code we didn’t review. So the gap is a lot bigger than we guess.&lt;/p&gt;

&lt;p&gt;But that’s a bot problem, right? The code agent will deal with all the needed changes. We don’t need to even look at the code.&lt;/p&gt;

&lt;p&gt;Nah, you know you will. You know what code is generated, and it’s not how you would have written it. And coding agents have the same problem of making sense of complex code bases as us.&lt;/p&gt;

&lt;p&gt;And they’ll make mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can the code agent clean the code up by itself?
&lt;/h2&gt;

&lt;p&gt;Cleaning is not just “make it readable”. It’s preparing it for more changes, reducing dependencies and isolating interfaces – all in the context of future plans. And the agent doesn’t have this context.&lt;/p&gt;

&lt;p&gt;In fact, it will assume another context, and we get stuck with the code and the assumptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you pay down AI code debt?
&lt;/h2&gt;

&lt;p&gt;Same as always: &lt;a href="https://testingil.com/2026/08/its-almost-like-you-need-an-actual-programmer.html" rel="noopener noreferrer"&gt;find the code you know you’ll touch again&lt;/a&gt;, and make that code easier to change. The problem starts when you don’t know where that code is.&lt;/p&gt;

&lt;p&gt;Because, you didn’t write it. And you didn’t review all of it. If any.&lt;/p&gt;

&lt;p&gt;Putting a price on technical debt before was an exercise in imagination. Now it’s pure fantasy.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you avoid it next time?
&lt;/h2&gt;

&lt;p&gt;First know what code was generated. And for that you need to enforce smaller code generation.&lt;/p&gt;

&lt;p&gt;If you don’t enforce it, you’ll have a lot more to review. And if that happens you won’t review it all. It’s a human thing.&lt;/p&gt;

&lt;p&gt;Then, you can &lt;a href="https://testingil.com/2026/07/testing-ai-generated-code-prompt-not-a-fix.html" rel="noopener noreferrer"&gt;wish the genie&lt;/a&gt; to refactor it to take the shape you want. Genies are good at transformations. And if the genie breaks something, your tests will tell you.&lt;/p&gt;

&lt;p&gt;You do have tests, right?&lt;/p&gt;

&lt;p&gt;The old technical debt was based on maintenance work. Now we have bigger maintenance queued up, along with risks of unverified code. Not cool.&lt;/p&gt;

&lt;p&gt;So, first, we need to be aware of the AI code debt – we’re creating code that will cost a lot more to maintain, than “regular” code.&lt;/p&gt;

&lt;p&gt;Before, we thought “it’s ok, we’ll take care of that later”, and then, when the bill came it was a lot more than we thought.&lt;/p&gt;

&lt;p&gt;Now? Expect a much bigger one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions people ask about AI code debt
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is AI code debt?
&lt;/h3&gt;

&lt;p&gt;AI code debt is technical debt created by generated code: you leave the code as it is, knowing it could be better, and the debt is the effort of making it better. The difference is scale. There’s more of it, it’s more complex, and some of it was never reviewed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is AI code debt different from technical debt?
&lt;/h3&gt;

&lt;p&gt;Not in kind, only in size and visibility. The old debt was something you put there and remembered. This debt arrived while you were reading something else, so you don’t know where it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can an AI agent clean up its own code debt?
&lt;/h3&gt;

&lt;p&gt;Not on its own. Cleaning up means preparing code for changes you plan to make, and the agent doesn’t have that context. It will assume a different one, and you’re left with the code and the assumptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you check that an AI refactor didn’t break anything?
&lt;/h3&gt;

&lt;p&gt;With tests you wrote before the refactor. Directing the genie to reshape code is fine as long as something independent tells you when it breaks.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://testingil.com/2026/08/ai-code-debt.html" rel="noopener noreferrer"&gt;testingil.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm Gil Zilberfeld. I teach API testing and test automation, and I write about what AI-generated code does to quality.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>programming</category>
      <category>codequality</category>
    </item>
    <item>
      <title>You Can't Fix A Bug With A Prompt</title>
      <dc:creator>Gil Zilberfeld</dc:creator>
      <pubDate>Thu, 06 Aug 2026 10:46:27 +0000</pubDate>
      <link>https://dev.to/testingil/you-cant-fix-a-bug-with-a-prompt-3ini</link>
      <guid>https://dev.to/testingil/you-cant-fix-a-bug-with-a-prompt-3ini</guid>
      <description>&lt;p&gt;Let's talk about fixing bugs. My second favorite activity after creating them.&lt;/p&gt;

&lt;p&gt;How do I know the bug is fixed? Well, I've been taught by wiser and more experienced people than me (way back when), that if you want to make sure the bug never shows its face again - write an automated test for it.&lt;/p&gt;

&lt;p&gt;Ok, I admit that there were times I didn't write a test. Some fixes are so trivial, that sometimes a test is a luxury.&lt;/p&gt;

&lt;p&gt;But even then, I was working on a hidden assumption. Just like in Fallout, code never changes. Until it does. But between those times it never changes.&lt;/p&gt;

&lt;p&gt;I fix the bug. From this point until it actually changes by a human, or a bot or someone in-between - that code will compile, or transpile, or whatever we call "runs" the same way. A statement will execute, a condition evaluated, an exception caught - every time in the same way.&lt;/p&gt;

&lt;p&gt;And now we come to modern programming languages: Prompts. Agents, prompts, workflows - they don't run the same way every time. What they do is run their interpretation of the request. If they run tools - they run the deterministic parts. If they run sub-agents, they run interpretations based on other interpretations.&lt;/p&gt;

&lt;p&gt;Interpretations work mostly the same way, until they don't. When I was teaching my agent to develop in TDD, I had a couple of requests. One of them was to not create code without a test.&lt;/p&gt;

&lt;p&gt;Which I thought was a very normal request from an agent. In fact, when I started out by telling it - we're working in TDD - I assumed it knows what TDD is. Ha.&lt;/p&gt;

&lt;p&gt;Always remember that what LLMs know is exactly what most of the population knows. And usually the "don't create any code without a test" falls through the cracks.&lt;/p&gt;

&lt;p&gt;So I made it official: One of the agent rules was exactly that. This was a legitimate bug fix. At least I thought so.&lt;/p&gt;

&lt;p&gt;But it really was a suggestion. Which the agent considered, and depending on its mood, sometimes did, and sometimes didn't.&lt;/p&gt;

&lt;p&gt;I won't go into the full solution (still in progress, if you want me to elaborate, comment), but part of it was to run a targeted coverage tool - a deterministic one, check it and stop the process if it found extra code. The TDD sequence looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Per step:
&lt;span class="p"&gt;1.&lt;/span&gt; Write test(s).
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="sb"&gt;`node scripts/tdd.mjs red &amp;lt;test-file&amp;gt;`&lt;/span&gt; — all newly added tests must fail. Pre-existing passing tests in the same file are allowed to remain passing.
&lt;span class="p"&gt;3.&lt;/span&gt; Implement minimum to pass.
&lt;span class="p"&gt;4.&lt;/span&gt; &lt;span class="sb"&gt;`node scripts/tdd.mjs targeted &amp;lt;test-file&amp;gt;`&lt;/span&gt; — targeted coverage + pass check.
&lt;span class="p"&gt;5.&lt;/span&gt; &lt;span class="sb"&gt;`node scripts/tdd.mjs lint`&lt;/span&gt; — ESLint.
&lt;span class="p"&gt;6.&lt;/span&gt; &lt;span class="sb"&gt;`node scripts/tdd.mjs full`&lt;/span&gt; — full suite + coverage.
&lt;span class="p"&gt;7.&lt;/span&gt; Script says STOP. Human reviews.
&lt;span class="p"&gt;8.&lt;/span&gt; Human runs &lt;span class="sb"&gt;`node scripts/tdd.mjs commit "message"`&lt;/span&gt;.
&lt;span class="p"&gt;9.&lt;/span&gt; Human confirms next step. AI runs &lt;span class="sb"&gt;`/clear`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But each step here is the suggestion. The real enforcement is done in the tdd.mjs code. Real code.&lt;/p&gt;

&lt;p&gt;But this is just an example. The real problem is that more and more "code" is not programmed. It's interpreted. That means that bugs are a lot more flaky to catch, but also are not permanently fixable.&lt;/p&gt;

&lt;p&gt;And don't get me started on companies switching model capabilities every other Tuesday. In the past, updating versions was a whole ceremony because we were worried something would break.&lt;/p&gt;

&lt;p&gt;Now LLM providers do it for us without us knowing.&lt;br&gt;
We can live with that. We should make sure we know.&lt;/p&gt;

&lt;p&gt;And remember - bug fixes in prompts are not real bug fixes. They are more like wishes. Which may or may not come true.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://testingil.com/2026/07/testing-ai-generated-code-prompt-not-a-fix.html" rel="noopener noreferrer"&gt;testingil.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm Gil Zilberfeld. I teach API testing and test automation, and I write about what AI-generated code does to quality.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>programming</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
