<?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: SVS_Praveen</title>
    <description>The latest articles on DEV Community by SVS_Praveen (@svspraveen).</description>
    <link>https://dev.to/svspraveen</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%2F4100356%2F2b971c9b-fd17-4c86-b195-fcd61e4ed247.png</url>
      <title>DEV Community: SVS_Praveen</title>
      <link>https://dev.to/svspraveen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/svspraveen"/>
    <language>en</language>
    <item>
      <title>Why 100% Line Coverage is Lying to You in AI-Generated Code (And How We Catch It)</title>
      <dc:creator>SVS_Praveen</dc:creator>
      <pubDate>Sat, 29 Aug 2026 14:15:45 +0000</pubDate>
      <link>https://dev.to/svspraveen/why-100-line-coverage-is-lying-to-you-in-ai-generated-code-and-how-we-catch-it-4dka</link>
      <guid>https://dev.to/svspraveen/why-100-line-coverage-is-lying-to-you-in-ai-generated-code-and-how-we-catch-it-4dka</guid>
      <description>&lt;p&gt;If you have spent the last few months building projects with AI coding assistants (Antigravity, Claude Code, Cursor, Copilot), you have likely experienced this specific frustration:&lt;/p&gt;

&lt;p&gt;You prompt an agent to build a feature or fix a bug. The agent writes tests. You run &lt;code&gt;pytest&lt;/code&gt;, and all green checkmarks appear with &lt;strong&gt;100% line coverage&lt;/strong&gt;. You feel confident and push to production — only to discover after deployment that the tests were completely hollow and missed critical edge-case logic.&lt;/p&gt;

&lt;p&gt;Line coverage measures whether a line of code was &lt;strong&gt;executed&lt;/strong&gt;, not whether its logic was actually &lt;strong&gt;asserted&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To solve this, I built and open-sourced &lt;strong&gt;DeployProof&lt;/strong&gt; — a deterministic pre-push verification tool for Python that catches hollow test suites, hallucinated dependencies, and security traps in seconds before code leaves your local machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Illusion of Green Line Coverage
&lt;/h2&gt;

&lt;p&gt;To illustrate the problem clearly, consider this simple discount calculator with a 50% threshold cap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# calculator.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When asked to write unit tests, an LLM might generate this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_calculator.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;calculate_discount&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_calculate_discount_standard&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;calculate_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single test hits every branch of the standard discount and yields &lt;strong&gt;100% line coverage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, if you mutate the logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change &lt;code&gt;rate &amp;gt; 0.5&lt;/code&gt; to &lt;code&gt;rate &amp;gt; 1.5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;return price * 0.5&lt;/code&gt; to &lt;code&gt;return price * 1.5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;*&lt;/code&gt; to &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The test suite still passes 100% green.&lt;/strong&gt; The test never asserted the threshold cap or boundary conditions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Existing Mutation Testing Was Too Slow
&lt;/h2&gt;

&lt;p&gt;Traditional mutation testing tools (like &lt;code&gt;mutmut&lt;/code&gt; or &lt;code&gt;cosmic-ray&lt;/code&gt;) are powerful, but they typically run against the entire codebase. On a project with hundreds of tests, running a full mutation suite can take 5 to 20 minutes — far too slow to run on every &lt;code&gt;git commit&lt;/code&gt; or &lt;code&gt;pre-push&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DeployProof solves this with Diff-Scoped AST Mutation:&lt;/strong&gt;&lt;br&gt;
Instead of mutating the entire repository, DeployProof inspects your active &lt;code&gt;git diff&lt;/code&gt; (or uncommitted session files) and targets AST mutations strictly to the lines you just wrote or modified.&lt;/p&gt;

&lt;p&gt;This drops verification time from minutes down to &lt;strong&gt;2 to 4 seconds&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deployproof check

DeployProof - LOCAL PRE-CHECK
&lt;span class="o"&gt;====================================================================&lt;/span&gt;
Target Scope &lt;span class="o"&gt;(&lt;/span&gt;1 file evaluated&lt;span class="o"&gt;)&lt;/span&gt;:
  &lt;span class="k"&gt;*&lt;/span&gt; calculator.py

Local Pre-Check Mutation Verification:
  Score:  57.1% &lt;span class="o"&gt;(&lt;/span&gt;4/7 mutants killed&lt;span class="o"&gt;)&lt;/span&gt;
  Status: FAILED &lt;span class="o"&gt;(&lt;/span&gt;score 57.1% below 80.0%&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;threshold: 80.0%&lt;span class="o"&gt;)&lt;/span&gt;
  Time:   2.27s

Surviving Mutants &lt;span class="o"&gt;(&lt;/span&gt;3 unverified changes&lt;span class="o"&gt;)&lt;/span&gt;:
  &lt;span class="o"&gt;[&lt;/span&gt;1] calculator.py:2
      Mutation: Replace numeric constant &lt;span class="s1"&gt;'0.5'&lt;/span&gt; with &lt;span class="s1"&gt;'1.5'&lt;/span&gt;
      Original: &lt;span class="k"&gt;if &lt;/span&gt;rate &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 0.5:
      Mutated:  &lt;span class="k"&gt;if &lt;/span&gt;rate &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 1.5:

  &lt;span class="o"&gt;[&lt;/span&gt;2] calculator.py:3
      Mutation: Replace numeric constant &lt;span class="s1"&gt;'0.5'&lt;/span&gt; with &lt;span class="s1"&gt;'1.5'&lt;/span&gt;
      Original: &lt;span class="k"&gt;return &lt;/span&gt;price &lt;span class="k"&gt;*&lt;/span&gt; 0.5
      Mutated:  &lt;span class="k"&gt;return &lt;/span&gt;price &lt;span class="k"&gt;*&lt;/span&gt; 1.5

  &lt;span class="o"&gt;[&lt;/span&gt;3] calculator.py:3
      Mutation: Replace binary operator &lt;span class="s1"&gt;'*'&lt;/span&gt; with &lt;span class="s1"&gt;'/'&lt;/span&gt;
      Original: &lt;span class="k"&gt;return &lt;/span&gt;price &lt;span class="k"&gt;*&lt;/span&gt; 0.5
      Mutated:  &lt;span class="k"&gt;return &lt;/span&gt;price / 0.5
&lt;span class="o"&gt;====================================================================&lt;/span&gt;
Pre-check FAILED: Score 57.1% is below threshold 80.0% &lt;span class="o"&gt;(&lt;/span&gt;3 surviving mutants&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you add tests for the threshold cap (&lt;code&gt;rate = 0.8&lt;/code&gt;) and exact boundary (&lt;code&gt;rate = 0.5&lt;/code&gt;), all mutants are killed and the pre-push gate passes at &lt;strong&gt;100.0%&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5 Additional Verification Passes
&lt;/h2&gt;

&lt;p&gt;Beyond hollow tests, AI codebases frequently introduce adjacent failure modes. DeployProof runs 5 additional static verification passes against your active diff:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;PyPI Dependency &amp;amp; Slopsquatting Defense&lt;/strong&gt;: Queries the live PyPI registry to verify every newly imported module exists, protecting against hallucinated package names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GhostApproval Symlink Traps (CWE-61)&lt;/strong&gt;: Catches symlinks pointing outside the repository root designed to escape developer sandboxes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control Flow &amp;amp; Error Handling&lt;/strong&gt;: Flags empty &lt;code&gt;except Exception: pass&lt;/code&gt; blocks and dead code generated to silence errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mock-Introduction Auditing&lt;/strong&gt;: Flags newly introduced &lt;code&gt;@patch&lt;/code&gt; and &lt;code&gt;unittest.mock&lt;/code&gt; usage that masks broken business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credential Scanner&lt;/strong&gt;: Catches unquoted &lt;code&gt;.env&lt;/code&gt; secrets and hardcoded API keys (OpenAI, Anthropic, AWS, Stripe).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Quickstart
&lt;/h2&gt;

&lt;p&gt;DeployProof is free, open source (MIT), and installs via pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;deployproof
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize it in your repository (creates &lt;code&gt;.deployproof.json&lt;/code&gt; and sets up the &lt;code&gt;.git/hooks/pre-push&lt;/code&gt; gate to block pushes when checks fail):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deployproof init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run on-demand verification anytime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deployproof check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For CI/CD pipelines (GitHub Actions, GitLab CI), it provides structured JSON output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deployproof check &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Links &amp;amp; Contributing
&lt;/h2&gt;

&lt;p&gt;I built DeployProof as an independent solo developer after repeatedly hitting subtle AI test regressions across my own projects.&lt;/p&gt;

&lt;p&gt;If you are using AI coding agents in your daily workflow, I would love for you to try it out, file issues, star the repository, or contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💻 &lt;strong&gt;GitHub (MIT)&lt;/strong&gt;: &lt;a href="https://github.com/SVSPraveen/DeployProof" rel="noopener noreferrer"&gt;https://github.com/SVSPraveen/DeployProof&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;PyPI&lt;/strong&gt;: &lt;a href="https://pypi.org/project/deployproof/" rel="noopener noreferrer"&gt;https://pypi.org/project/deployproof/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧪 &lt;strong&gt;Verified Test Suite&lt;/strong&gt;: 79/79 pytest unit tests and 11/11 stress test fixtures reproducing each planted edge case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;What subtle failure modes or hollow test patterns have you noticed in your AI coding workflows? Let me know in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>ai</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
