<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Testing on Daffa Abhipraya</title><link>https://blog.abhipraya.dev/tags/testing/</link><description>Recent content in Testing on Daffa Abhipraya</description><generator>Hugo</generator><language>en-us</language><copyright>© Daffa Abhipraya</copyright><lastBuildDate>Wed, 15 Apr 2026 00:00:00 +0700</lastBuildDate><atom:link href="https://blog.abhipraya.dev/tags/testing/index.xml" rel="self" type="application/rss+xml"/><item><title>PPL: Mutation Testing, From Setup to Score [Sprint 2, Week 3]</title><link>https://blog.abhipraya.dev/ppl/part-b/s2w3-tdd/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-b/s2w3-tdd/</guid><description>&lt;h2 id="what-i-worked-on">
 &lt;a class="anchor" href="#what-i-worked-on" data-anchor="what-i-worked-on" aria-hidden="true">#&lt;/a>
 What I Worked On
&lt;/h2>
&lt;p>Two weeks on mutation testing across the SIRA codebase. The first week wired &lt;a href="https://github.com/boxed/mutmut">mutmut&lt;/a> (Python) and &lt;a href="https://stryker-mutator.io/">Stryker&lt;/a> (TypeScript) into the pipeline and uncovered the uncomfortable truth: 91% line coverage on the services layer translated to a mutation score just above zero in places. The second week closed that gap by writing 400+ targeted tests across two rounds, driving the API mutation score from ~66% to 80.3%. This blog tells the full arc.&lt;/p></description></item><item><title>PPL: When 91% Test Coverage Means Nothing</title><link>https://blog.abhipraya.dev/ppl/part-a/tdd/</link><pubDate>Thu, 09 Apr 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-a/tdd/</guid><description>&lt;p>We had 91% line coverage and felt good about it. Then we ran mutation testing and scored 0%. Every line of our service layer was executed by tests, but almost nothing was actually verified. This is the story of how we discovered the gap between &amp;ldquo;code was run&amp;rdquo; and &amp;ldquo;code was checked,&amp;rdquo; and what we changed to close it.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note:&lt;/strong> Our project is hosted on an internal GitLab instance, so we use the term &lt;strong>MR (Merge Request)&lt;/strong> throughout this blog. If you&amp;rsquo;re coming from GitHub, MRs are the equivalent of &lt;strong>Pull Requests (PRs)&lt;/strong>.&lt;/p></description></item><item><title>PPL: TDD [Sprint 2, Week 2]</title><link>https://blog.abhipraya.dev/ppl/part-b/s2w2-tdd/</link><pubDate>Mon, 30 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-b/s2w2-tdd/</guid><description>&lt;h2 id="what-i-worked-on">
 &lt;a class="anchor" href="#what-i-worked-on" data-anchor="what-i-worked-on" aria-hidden="true">#&lt;/a>
 What I Worked On
&lt;/h2>
&lt;p>Three new features landed this week that each required TDD from scratch: multi-device session management (SIRA-214), invoice cancellation (SIRA-125), and blocking inactive accounts (SIRA-215). All three followed the red-green cycle and included mock isolation for external dependencies.&lt;/p>
&lt;hr>
&lt;h2 id="session-management-testing-stateful-logic-with-mocks">
 &lt;a class="anchor" href="#session-management-testing-stateful-logic-with-mocks" data-anchor="session-management-testing-stateful-logic-with-mocks" aria-hidden="true">#&lt;/a>
 Session Management: Testing Stateful Logic with Mocks
&lt;/h2>
&lt;p>SIRA-214 (MR !120) introduced &lt;code>SessionService&lt;/code>, which manages active sessions per user with a device limit. The service has non-trivial state: upsert if session already exists, kick oldest if at capacity, validate ownership before revoking.&lt;/p></description></item><item><title>PPL: Beyond Unit Tests [Sprint 2, Week 1]</title><link>https://blog.abhipraya.dev/ppl/part-b/s2w1-tdd/</link><pubDate>Mon, 23 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-b/s2w1-tdd/</guid><description>&lt;h2 id="what-i-worked-on">
 &lt;a class="anchor" href="#what-i-worked-on" data-anchor="what-i-worked-on" aria-hidden="true">#&lt;/a>
 What I Worked On
&lt;/h2>
&lt;p>This week I pushed our testing strategy well beyond standard unit tests. The project already had 433 backend and 200 frontend tests with 91% line coverage, but I wanted to answer a harder question: &lt;strong>do our tests actually catch bugs, or do they just execute code?&lt;/strong>&lt;/p>
&lt;p>I added four advanced testing approaches: property-based testing (Hypothesis + fast-check), behavioral testing (pytest-bdd with Gherkin), mutation testing (mutmut + Stryker), and test isolation verification (pytest-randomly). The results were eye-opening.&lt;/p></description></item><item><title>PPL: When 91% Test Coverage Means Nothing</title><link>https://blog.abhipraya.dev/ppl/part-a/tdd-and-qa/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-a/tdd-and-qa/</guid><description>&lt;p>We had 91% line coverage and felt good about it. Then we ran mutation testing and scored 0%. Every line of our service layer was executed by tests; almost nothing was actually verified. This is the story of how six advanced testing tools exposed the gap between &amp;ldquo;code was run&amp;rdquo; and &amp;ldquo;code was checked,&amp;rdquo; and what that means for any team relying on coverage as a quality signal.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note:&lt;/strong> Our project is hosted on an internal GitLab instance, so we use the term &lt;strong>MR (Merge Request)&lt;/strong> throughout this blog. If you&amp;rsquo;re coming from GitHub, MRs are the equivalent of &lt;strong>Pull Requests (PRs)&lt;/strong>.&lt;/p></description></item><item><title>PPL: Test-Driven Development [Sprint 1, Week 3]</title><link>https://blog.abhipraya.dev/ppl/part-b/s1w3-tdd/</link><pubDate>Fri, 13 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-b/s1w3-tdd/</guid><description>&lt;h2 id="what-i-worked-on">
 &lt;a class="anchor" href="#what-i-worked-on" data-anchor="what-i-worked-on" aria-hidden="true">#&lt;/a>
 What I Worked On
&lt;/h2>
&lt;p>This week shipped three full-stack features using strict TDD discipline: invoice management (CRUD + filtering), layout/dashboard (sidebar, header, dashboard with role-based navigation), and a payments sidebar navigation link. Each feature followed red-green-refactor with tagged commits.&lt;/p>
&lt;p>The project now has &lt;strong>392 backend tests&lt;/strong> and &lt;strong>195 frontend tests&lt;/strong> (587 total), up from 51 last week.&lt;/p>
&lt;h2 id="red-green-refactor-commit-discipline">
 &lt;a class="anchor" href="#red-green-refactor-commit-discipline" data-anchor="red-green-refactor-commit-discipline" aria-hidden="true">#&lt;/a>
 Red-Green-Refactor Commit Discipline
&lt;/h2>
&lt;p>Every feature branch this week followed tagged commits so the TDD flow is auditable from the git history alone.&lt;/p></description></item><item><title>PPL: Test-Driven Development in a FastAPI Project [Sprint 1, Week 2]</title><link>https://blog.abhipraya.dev/ppl/part-b/s1w2-tdd/</link><pubDate>Wed, 04 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-b/s1w2-tdd/</guid><description>&lt;p>TDD forces you to think about the interface before the implementation. This post covers how it was applied in the Smart Invoice Reminder AI (SIRA) backend for Sprint 1.&lt;/p>
&lt;h2 id="test-distribution">
 &lt;a class="anchor" href="#test-distribution" data-anchor="test-distribution" aria-hidden="true">#&lt;/a>
 Test Distribution
&lt;/h2>
&lt;p>The API currently has 51 test functions across 4 files:&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>File&lt;/th>
 &lt;th>Tests&lt;/th>
 &lt;th>Scope&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>tests/test_auth.py&lt;/code>&lt;/td>
 &lt;td>14&lt;/td>
 &lt;td>JWT validation, RBAC, DB queries&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>tests/test_payments.py&lt;/code>&lt;/td>
 &lt;td>24&lt;/td>
 &lt;td>Payment CRUD, business logic, edge cases&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>tests/test_db_schema_and_seed.py&lt;/code>&lt;/td>
 &lt;td>6&lt;/td>
 &lt;td>Migration integrity, seed validation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>tests/test_logging_middleware.py&lt;/code>&lt;/td>
 &lt;td>7&lt;/td>
 &lt;td>HTTP access logging, request/response capture&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="red-green-refactor">
 &lt;a class="anchor" href="#red-green-refactor" data-anchor="red-green-refactor" aria-hidden="true">#&lt;/a>
 Red-Green-Refactor
&lt;/h2>
&lt;p>The authentication feature (&lt;a href="https://linear.app/ppl-sira/issue/SIRA-26">SIRA-26&lt;/a>) followed strict TDD commit discipline. Each backend function got its own RED commit (failing test) followed by a GREEN commit (passing implementation) before any cleanup.&lt;/p></description></item></channel></rss>