<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Quality Engineering with Siddhartha]]></title><description><![CDATA[Quality Engineering with Siddhartha]]></description><link>https://siddhartha-quality-engineering.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 12 Nov 2026 08:19:05 GMT</lastBuildDate><atom:link href="https://siddhartha-quality-engineering.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Presentation: One Failed Test, Five Possible Causes]]></title><description><![CDATA[This self-authored, eight-slide technical presentation explains a practical approach to automation failure investigation. Scroll through the slides below…]]></description><link>https://siddhartha-quality-engineering.hashnode.dev/presentation-one-failed-test-five-possible-causes</link><guid isPermaLink="true">https://siddhartha-quality-engineering.hashnode.dev/presentation-one-failed-test-five-possible-causes</guid><dc:creator><![CDATA[Siddhartha Mukherjee]]></dc:creator><pubDate>Wed, 11 Nov 2026 19:54:01 GMT</pubDate><content:encoded><![CDATA[<p>This self-authored, eight-slide technical presentation explains a practical approach to automation failure investigation. Scroll through the slides below. All examples and timings are fictional teaching material.</p>
<h2>Slide 1: One failed test. Five possible causes.</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/3fcf2fd6-8c35-422a-8c84-bac9853954fe.png" alt="One failed test. Five possible causes." /></p>
<p>A practical guide to automation failure analysis by Siddhartha Mukherjee, Principal Quality Engineer.</p>
<h2>Slide 2: A failure is the start of an investigation</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/9be59e5d-10c9-4042-9d96-030caa099633.png" alt="A failure is the start of an investigation" /></p>
<p>A missing invoice after 30 seconds is an observation. Investigate whether processing failed, remains pending, or used the wrong record.</p>
<h2>Slide 3: Five possible causes</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/4fd3c809-25ad-4cbb-b1b3-c2e2b8ee250d.png" alt="Five possible causes" /></p>
<p>Consider product behaviour, testware, data, setup and environment. Classifications may overlap and must follow evidence.</p>
<h2>Slide 4: Evidence that makes a failure reproducible</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/1f36c50b-9092-4d7a-a735-f3487fa493eb.png" alt="Evidence that makes a failure reproducible" /></p>
<p>Preserve execution context, unique record identity, failure timestamps, expected behaviour and actual results.</p>
<h2>Slide 5: A fictional import failure</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/333a2635-e7c4-47f4-9cca-a7a850e2ac5a.png" alt="A fictional import failure" /></p>
<p>In this fictional asynchronous import, the job remains RUNNING at 30 seconds and reports SUCCEEDED at 42 seconds. The evidence supports an early validation hypothesis. Check the documented processing contract before concluding.</p>
<h2>Slide 6: AI assistance and human verification</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/8c39e330-dbdd-4a17-8db8-e80c4b811285.png" alt="AI assistance and human verification" /></p>
<p>AI can assemble timelines and suggest hypotheses. People verify source accuracy, record identity, requirements, business impact and fix results.</p>
<h2>Slide 7: Correction and validation</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/40fe85ac-c573-4160-964c-d589c1e7141e.png" alt="Correction and validation" /></p>
<p>Poll the exact job with a bounded deadline, handle terminal rejection, respect idempotency, and verify the intended business result.</p>
<h2>Slide 8: A reusable investigation checklist</h2>
<p><img src="https://cdn.hashnode.com/uploads/covers/6af4b07d1c2e477534b47422/5e694bba-91ec-4b30-bd09-fe6af4bc849e.png" alt="A reusable investigation checklist" /></p>
<p>Preserve the first result, identify the earliest deviation, test hypotheses, choose a focused correction, and verify affected regression paths.</p>
<h2>Further reading</h2>
<p><a href="https://siddhartha-quality-engineering.hashnode.dev/one-failed-test-five-possible-causes-a-practical-guide-to-automation-failure-analysis">Read the companion article: One Failed Test, Five Possible Causes</a>.</p>
<p>Author: Siddhartha Mukherjee. This presentation expresses general quality engineering practices and does not imply employer endorsement.</p>
]]></content:encoded></item><item><title><![CDATA[What Should We Test First? A Practical Guide to Risk-Based Regression]]></title><description><![CDATA[Plan risk-based regression with a fictional two-hour window, critical journeys, changed dependencies, and an explicit record of coverage gaps.]]></description><link>https://siddhartha-quality-engineering.hashnode.dev/what-should-we-test-first-a-practical-guide-to-risk-based-regression</link><guid isPermaLink="true">https://siddhartha-quality-engineering.hashnode.dev/what-should-we-test-first-a-practical-guide-to-risk-based-regression</guid><category><![CDATA[Software Testing]]></category><dc:creator><![CDATA[Siddhartha Mukherjee]]></dc:creator><pubDate>Wed, 11 Nov 2026 18:55:47 GMT</pubDate><content:encoded><![CDATA[<p>The release candidate arrives late. There are two hours left for regression, and the full suite takes much longer. What should run first?</p>
<p>The fastest tests are not automatically the most valuable. The newest feature is not the only risk. Running everything labelled “smoke” may leave a changed dependency untested.</p>
<p><strong>Risk-based regression is the practice of choosing and ordering checks according to the failures that matter most for this release.</strong> It makes the reasoning behind reduced coverage explicit.</p>
<p>This article uses a fictional release and illustrative time estimates. It is a planning example, not an account of an employer's delivery process.</p>
<h2>1. Start with the change, then follow its reach</h2>
<p>Imagine a customer-management application with three changes:</p>
<ul>
<li>A payment-calculation update.</li>
<li>A change to a shared role-permission helper.</li>
<li>A new optional field in a bulk import.</li>
</ul>
<p>Testing only those screens would miss their connections. Payment calculations affect invoices and balances. A shared permission helper may affect unchanged pages. An import change may affect existing layouts or child-record mapping.</p>
<p>Build a small impact map from the changed components to business journeys, roles, integrations, and data. Ask developers and feature owners to challenge it. Label uncertain dependencies as questions to resolve, rather than silently treating them as unaffected.</p>
<h2>2. Describe risks as failures with consequences</h2>
<p>“Test payments” is a scope label. “An incorrect rounding change produces the wrong amount due” is a risk statement that helps select checks.</p>
<p>For each candidate risk, record:</p>
<table>
<thead>
<tr>
<th>Factor</th>
<th>Question</th>
</tr>
</thead>
<tbody><tr>
<td>Business impact</td>
<td>What happens if this behaviour is wrong?</td>
</tr>
<tr>
<td>Likelihood</td>
<td>What evidence suggests the change could introduce this failure?</td>
</tr>
<tr>
<td>Exposure</td>
<td>Which users, volumes, roles, or records are affected?</td>
</tr>
<tr>
<td>Existing evidence</td>
<td>What relevant checks have already passed on the candidate build?</td>
</tr>
<tr>
<td>Uncertainty</td>
<td>Which assumptions or dependencies remain unverified?</td>
</tr>
</tbody></table>
<p>Use qualitative priorities or a simple scoring scheme consistently. A numerical score can structure discussion, but it does not make subjective estimates precise. Do not let a low total score hide a non-negotiable security, regulatory, or data-integrity requirement.</p>
<h2>3. Select checks that challenge each risk</h2>
<p>A fictional selection might look like this:</p>
<table>
<thead>
<tr>
<th>Risk</th>
<th>Selected checks</th>
<th>Why they matter</th>
</tr>
</thead>
<tbody><tr>
<td>Payment amount is calculated incorrectly</td>
<td>Representative amounts, rounding boundaries, supported adjustments, persisted invoice values</td>
<td>Challenges the changed calculation and its business result</td>
</tr>
<tr>
<td>Shared permission change exposes restricted actions</td>
<td>Supported allowed and denied operations for affected roles</td>
<td>Covers the shared dependency beyond one screen</td>
</tr>
<tr>
<td>Import change breaks existing layouts</td>
<td>Old layout without the optional field; new layout with valid, blank, and invalid values</td>
<td>Checks compatibility and new validation</td>
</tr>
<tr>
<td>Child records attach to the wrong parent</td>
<td>Verify identities and parent-child relationships after import</td>
<td>Detects a mapping failure that counts alone could miss</td>
</tr>
<tr>
<td>Existing state affects a core journey</td>
<td>One focused end-to-end flow using a known baseline</td>
<td>Challenges interactions across components</td>
</tr>
</tbody></table>
<p>These are examples, not a universal minimum suite. Actual cases must follow the application's requirements and supported configurations.</p>
<p>As discussed in <a href="https://siddhartha-quality-engineering.hashnode.dev/a-test-passed-but-did-it-actually-verify-anything">A Test Passed—But Did It Actually Verify Anything?</a>, every selected check needs assertions that support its claim. Coverage by name alone is weak evidence.</p>
<h2>4. Budget for usable evidence, not just execution</h2>
<p>Two hours of execution followed by no time to investigate results is not a complete review window.</p>
<p>An illustrative plan for our release is:</p>
<table>
<thead>
<tr>
<th>Activity</th>
<th align="right">Budget</th>
</tr>
</thead>
<tbody><tr>
<td>Build, environment, access, and fixture readiness checks</td>
<td align="right">10 minutes</td>
</tr>
<tr>
<td>Changed payment calculations and affected critical journey</td>
<td align="right">30 minutes</td>
</tr>
<tr>
<td>Permission checks across impacted roles and operations</td>
<td align="right">25 minutes</td>
</tr>
<tr>
<td>Import compatibility, validation, and relationship checks</td>
<td align="right">20 minutes</td>
</tr>
<tr>
<td>Focused investigation or retest reserve</td>
<td align="right">15 minutes</td>
</tr>
<tr>
<td>Reconcile evidence, gaps, and release recommendation</td>
<td align="right">20 minutes</td>
</tr>
<tr>
<td>Total</td>
<td align="right">120 minutes</td>
</tr>
</tbody></table>
<p>Validate estimates against actual run history, setup costs, and available people. Parallel execution helps only when resources and data are independent; otherwise, it can introduce collisions and reduce the credibility of results.</p>
<p>If essential checks cannot fit, escalate the constraint. Options include delaying the decision, reducing release scope, or obtaining additional capacity. Compressing the plan does not reduce the underlying risk.</p>
<h2>5. Order checks to reveal important problems early</h2>
<p>First establish that the candidate build, environment, and prerequisites are suitable. Then run the highest-impact checks with a realistic chance of exposing release-blocking problems.</p>
<p>A failure in a critical shared permission path may change the value of continuing broad UI regression. An unavailable prerequisite may invalidate dependent tests until restored.</p>
<p>This does not mean stopping all independent testing after the first failure. Separate blocked journeys from checks that can still provide valid evidence, and communicate any replanning.</p>
<p>Retain a small, justified set of checks for important unchanged behaviour and unexpected interactions. Change-impact analysis can be incomplete; focused regression is a conscious selection, not proof that everything else is unaffected.</p>
<h2>6. Respond to failure without abandoning the risk model</h2>
<p>Suppose the payment checks expose an incorrect invoice total. Diagnose the failure, establish the affected scope, and involve the responsible owner.</p>
<p>Do not spend the remaining window rerunning the same case until it passes. Preserve the first result and use the <a href="https://siddhartha-quality-engineering.hashnode.dev/one-failed-test-five-possible-causes-a-practical-guide-to-automation-failure-analysis">failure-analysis approach</a> to distinguish product behaviour from test, data, and environment causes.</p>
<p>If a correction arrives, verify its deployment, retest the defect, and assess related regression needs. The earlier estimate may no longer hold. A fix that changes another shared component should trigger a revised impact assessment.</p>
<p>The principle from <a href="https://siddhartha-quality-engineering.hashnode.dev/it-passed-on-rerun-is-the-problem-really-fixed">It Passed on Rerun—Is the Problem Really Fixed?</a> also applies: retry recovery is not a substitute for understanding the original result.</p>
<h2>7. State what the reduced suite did not establish</h2>
<p>A useful final report distinguishes <strong>verified</strong>, <strong>failed</strong>, <strong>blocked</strong>, <strong>not selected</strong>, and <strong>not completed</strong> work.</p>
<p>For every significant gap, name the affected risk, available alternative evidence, owner, and next action. Do not report “all regression passed” when only the selected subset passed.</p>
<p>A defensible recommendation could say:</p>
<blockquote>
<p>Selected checks verified the changed calculation and specified role restrictions on the candidate build. The legacy import layout remains blocked by unavailable reference data. Its compatibility is unverified; resolve the gap or explicitly decide how to handle that residual risk before releasing the affected scope.</p>
</blockquote>
<p>The appropriate release authority makes the decision. QA supplies traceable evidence, an assessment, and a recommendation, consistent with the approach in <a href="https://siddhartha-quality-engineering.hashnode.dev/beyond-pass-rates-how-to-assess-whether-a-release-is-ready">Beyond Pass Rates</a>.</p>
<h2>8. A reusable prioritisation checklist</h2>
<ul>
<li><input disabled type="checkbox" /> Confirm the candidate changes, build, and environment.</li>
<li><input disabled type="checkbox" /> Map direct and shared dependencies to business journeys.</li>
<li><input disabled type="checkbox" /> Describe failure consequences, exposure, and uncertainty.</li>
<li><input disabled type="checkbox" /> Retain mandatory coverage and critical existing journeys.</li>
<li><input disabled type="checkbox" /> Choose checks with meaningful, independent expected results.</li>
<li><input disabled type="checkbox" /> Budget setup, execution, investigation, and review time.</li>
<li><input disabled type="checkbox" /> Replan when a blocker or late fix changes the assumptions.</li>
<li><input disabled type="checkbox" /> Report omitted scope and residual risks explicitly.</li>
</ul>
<p><strong>The goal is to obtain the most useful evidence about important release risks within the available time—and be clear about the evidence still missing.</strong></p>
<p>What would you protect first if your next regression window were cut to two hours?</p>
]]></content:encoded></item><item><title><![CDATA[It Passed on Rerun—Is the Problem Really Fixed?]]></title><description><![CDATA[Investigate flaky tests through first-attempt evidence, readiness checks, isolated data, focused reruns, and accountable quarantine.]]></description><link>https://siddhartha-quality-engineering.hashnode.dev/it-passed-on-rerun-is-the-problem-really-fixed</link><guid isPermaLink="true">https://siddhartha-quality-engineering.hashnode.dev/it-passed-on-rerun-is-the-problem-really-fixed</guid><category><![CDATA[test-automation]]></category><dc:creator><![CDATA[Siddhartha Mukherjee]]></dc:creator><pubDate>Wed, 11 Nov 2026 18:53:04 GMT</pubDate><content:encoded><![CDATA[<p>A search test fails on the first attempt and passes on the second. The dashboard is green again. Is the problem fixed?</p>
<p><strong>A rerun changes the evidence available; it does not automatically explain the original failure.</strong></p>
<p>For a Principal Quality Engineer, intermittent results raise two questions: can we trust this test, and could the same condition affect a user?</p>
<p>This article uses a fictional search workflow to examine those questions. The timings and outcomes below are illustrative, not measurements from an employer's system.</p>
<h2>1. What does “flaky” actually tell us?</h2>
<p>A test that alternates between passing and failing under apparently equivalent conditions is a candidate for a flakiness investigation. “Apparently” matters: inputs, data, order, environment load, and deployed components may differ without appearing in the summary report.</p>
<p>Do not assume every intermittent failure is a defective test. A product race condition or an intermittently unavailable dependency can also produce variable outcomes.</p>
<p>In my post on <a href="https://siddhartha-quality-engineering.hashnode.dev/one-failed-test-five-possible-causes-a-practical-guide-to-automation-failure-analysis">five possible causes of automation failures</a>, I used categories to guide investigation. Those categories remain hypotheses until supported by evidence.</p>
<h2>2. Preserve both attempts</h2>
<p>Consider this invented sequence for a test that creates a customer and searches for the new record:</p>
<table>
<thead>
<tr>
<th>Attempt</th>
<th>Observation</th>
<th>What remains unknown</th>
</tr>
</thead>
<tbody><tr>
<td>First</td>
<td>Creation accepted; search returns no matching record within ten seconds</td>
<td>Whether processing completed, the search query was correct, or the test searched the expected scope</td>
</tr>
<tr>
<td>Rerun</td>
<td>Search finds the record</td>
<td>Whether the record came from the first attempt or the second, and why visibility changed</td>
</tr>
</tbody></table>
<p>A rerun that reuses the same identity can accidentally find a record left by the previous attempt. That is not evidence that a fresh creation-to-search journey succeeded.</p>
<p>Retain both logs, timestamps, identifiers, build details, and outcomes. Record whether a rerun started from a clean baseline. Never replace the first failure with the final pass in your investigation history.</p>
<h2>3. Ask focused questions before changing waits</h2>
<p>For the fictional search failure, I would investigate:</p>
<ul>
<li><strong>Processing:</strong> Was creation merely accepted, or was completion confirmed?</li>
<li><strong>Search readiness:</strong> Does the documented workflow include an indexing or visibility delay?</li>
<li><strong>Locator behaviour:</strong> Did the test read the correct results container and clear old filters?</li>
<li><strong>Identity:</strong> Did it search by a unique identifier for this attempt?</li>
<li><strong>Shared data:</strong> Could another test update, delete, or claim that record?</li>
<li><strong>Order and load:</strong> Does the failure correlate with parallel execution or an earlier test?</li>
</ul>
<p>Collect request-specific evidence. A general “service healthy” signal does not prove this request completed correctly.</p>
<p>If the documented workflow allows asynchronous visibility, the test needs bounded polling for the relevant state. If the product exceeds an agreed response-time requirement, extending the test timeout may conceal a performance defect.</p>
<h2>4. Replace guesses with observable conditions</h2>
<p>A fixed sleep assumes the system will be ready when time expires. A meaningful wait checks the state needed for the next action.</p>
<p>Conceptually:</p>
<pre><code class="language-text">create a uniquely identified record
verify the documented acceptance response
observe processing completion where the contract requires it
poll for the exact record within the agreed visibility window
verify record identity and relevant values
on timeout, report the last observed state and supporting evidence
</code></pre>
<p>Polling must not repeat a non-idempotent create operation. Retry observation separately from mutation, and distinguish request errors from valid “not available yet” responses.</p>
<p>The same principle applies to UI waits: an element being visible may not mean that business processing completed. Choose the condition that supports the test's actual claim, as discussed in <a href="https://siddhartha-quality-engineering.hashnode.dev/a-test-passed-but-did-it-actually-verify-anything">meaningful passing tests</a>.</p>
<h2>5. Use reruns as an investigation tool</h2>
<p>Reruns are useful when they test a hypothesis. Change one relevant condition where practical, and record it.</p>
<table>
<thead>
<tr>
<th>Hypothesis</th>
<th>Focused experiment</th>
</tr>
</thead>
<tbody><tr>
<td>Parallel tests share a fixture</td>
<td>Repeat with isolated data; compare with the original concurrency</td>
</tr>
<tr>
<td>An earlier test leaves filters or session state</td>
<td>Start from an explicitly reset state and compare execution order</td>
</tr>
<tr>
<td>Visibility is asynchronous</td>
<td>Observe acceptance, completion, and first visibility timestamps</td>
</tr>
<tr>
<td>A locator selects an unrelated row</td>
<td>Inspect matches and verify the selected record identity</td>
</tr>
</tbody></table>
<p>A pass after several simultaneous changes does not identify which change mattered. Repeating the same run until it turns green is especially weak evidence when baseline state changes between attempts.</p>
<h2>6. Measure reliability without hiding the first result</h2>
<p>Track first-attempt outcomes separately from results after retry. Also record the number of eligible attempts, environment, and observation period.</p>
<p>For example, if eight of twenty comparable first attempts fail, the observed first-attempt failure rate is 40%. If all eight reruns pass, that does not make the first-attempt rate zero.</p>
<p>Twenty observations are still a limited sample. The rate may change with data, concurrency, build, and environment conditions. Avoid treating one observed percentage as a permanent property of the test.</p>
<p>Useful measures include investigation effort, repeat failure patterns, and the number of tests with unconfirmed causes. A high retry-recovery count can indicate hidden work rather than healthy automation.</p>
<h2>7. Quarantine with accountability</h2>
<p>Temporarily removing an unreliable test from a release gate may be reasonable when its noise makes the gate unusable. It also removes evidence.</p>
<p>A quarantine record should include the affected requirement, tracking item, owner, review date, and alternative coverage. Set an exit condition that demonstrates the intended behaviour under representative conditions.</p>
<p>Quarantine must not become silent deletion. A critical journey still needs credible verification, and residual risk should remain visible in the <a href="https://siddhartha-quality-engineering.hashnode.dev/beyond-pass-rates-how-to-assess-whether-a-release-is-ready">release-readiness assessment</a>.</p>
<h2>8. Before calling the issue fixed</h2>
<ul>
<li><input disabled type="checkbox" /> Preserve the original failure and rerun evidence.</li>
<li><input disabled type="checkbox" /> Confirm the cause or clearly retain an unconfirmed classification.</li>
<li><input disabled type="checkbox" /> Verify record identity, starting state, and test independence.</li>
<li><input disabled type="checkbox" /> Check readiness against documented behaviour and timing expectations.</li>
<li><input disabled type="checkbox" /> Apply the correction to the relevant test, fixture, product, or environment.</li>
<li><input disabled type="checkbox" /> Exercise the condition that previously exposed the problem.</li>
<li><input disabled type="checkbox" /> Check representative order, concurrency, and related journeys.</li>
<li><input disabled type="checkbox" /> Report the observation window and remaining limitations.</li>
</ul>
<p>No finite set of passes proves a test can never fail again. A defensible conclusion explains what was corrected, why the correction addresses the evidence, and how it was verified.</p>
<p><strong>“Passed on rerun” is an observation. “Fixed” is a conclusion that needs a cause, a correction, and verification.</strong></p>
<p>What evidence do you require before closing an intermittent test issue?</p>
]]></content:encoded></item><item><title><![CDATA[A Test Passed—But Did It Actually Verify Anything?]]></title><description><![CDATA[Make passing tests meaningful with stronger UI, API, and import assertions, fresh reads, sound test oracles, and an assertion-review checklist.]]></description><link>https://siddhartha-quality-engineering.hashnode.dev/a-test-passed-but-did-it-actually-verify-anything</link><guid isPermaLink="true">https://siddhartha-quality-engineering.hashnode.dev/a-test-passed-but-did-it-actually-verify-anything</guid><category><![CDATA[Software Testing]]></category><category><![CDATA[test-automation]]></category><dc:creator><![CDATA[Siddhartha Mukherjee]]></dc:creator><pubDate>Wed, 11 Nov 2026 18:43:34 GMT</pubDate><content:encoded><![CDATA[<p>A test clicks Save. No exception is raised. The report turns green.</p>
<p>But did the record save? Was it saved for the correct account? Did the requested value persist after reopening the page?</p>
<p>The result depends on what the test actually checked. A green status can be valid for a narrow technical check while being insufficient evidence for the business behaviour described in the test title.</p>
<p>For a Principal Quality Engineer, that gap deserves as much attention as an obvious failure.</p>
<h2>1. Start with the claim behind the test name</h2>
<p>Consider a fictional test named <strong>“Update a customer's contact preference.”</strong> Its steps open a profile, select Email, click Save, and return to the list.</p>
<p>If those actions complete without an exception, the test demonstrates that those interactions completed. It has not necessarily established that the intended customer's preference was persisted.</p>
<p>A useful review question is:</p>
<blockquote>
<p>What incorrect behaviour would make this test fail?</p>
</blockquote>
<p>If the application silently ignores the change and the test stays green, it cannot support the claim in its title.</p>
<p>This connects to my earlier posts on <a href="https://siddhartha-quality-engineering.hashnode.dev/beyond-pass-rates-how-to-assess-whether-a-release-is-ready">release readiness beyond pass rates</a> and <a href="https://siddhartha-quality-engineering.hashnode.dev/one-failed-test-five-possible-causes-a-practical-guide-to-automation-failure-analysis">investigating automation failures</a>. Reliable release evidence requires both meaningful passes and well-understood failures.</p>
<p>All examples here are illustrative and use fictional data.</p>
<h2>2. Move from an action to an observable outcome</h2>
<p>For the contact-preference example, a stronger test would:</p>
<ol>
<li>Identify the intended customer using a stable test identifier.</li>
<li>Establish the starting preference and choose a different permitted value.</li>
<li>Change the preference and save.</li>
<li>Check the documented success or processing outcome.</li>
<li>Reopen the record, or read it through an appropriate independent interface.</li>
<li>Confirm the customer identity and persisted preference.</li>
<li>Restore the fixture when the test's cleanup design requires it.</li>
</ol>
<p>The baseline matters. If the preference was already Email, a broken Save operation might leave the expected value unchanged and escape detection.</p>
<p>Re-reading through the same stale client cache may also be weak evidence. Choose an observation point that can genuinely reveal a failure to persist, with any documented consistency delay accounted for.</p>
<h2>3. Match each assertion to the requirement</h2>
<p>An assertion needs a test oracle: a justified basis for deciding what the result should be. This might be an agreed requirement, a known fixture, a calculation, or a documented API contract.</p>
<table>
<thead>
<tr>
<th>Test claim</th>
<th>Insufficient evidence for that claim</th>
<th>Stronger evidence</th>
</tr>
</thead>
<tbody><tr>
<td>Contact preference was saved</td>
<td>Save button was clicked</td>
<td>Correct customer's changed preference survives a fresh read</td>
</tr>
<tr>
<td>User details are correct</td>
<td>Response status is 200</td>
<td>Returned identity, required fields, types, and expected values match the contract</td>
</tr>
<tr>
<td>Import loaded all expected records</td>
<td>Job status is Completed</td>
<td>Expected records and relationships reconcile with persisted data</td>
</tr>
<tr>
<td>Unauthorised update is prevented</td>
<td>Edit button is hidden</td>
<td>Required UI restrictions and protected-operation rejection are verified in their respective tests</td>
</tr>
<tr>
<td>Duplicate submission is rejected</td>
<td>An error message appears</td>
<td>Intended duplicate rule is reported and no unintended duplicate is created</td>
</tr>
</tbody></table>
<p>Stronger does not mean checking every possible field in every test. Select assertions that support the specific requirement and expose realistic incorrect outcomes.</p>
<h2>4. An API response can be correct at one layer and incomplete at another</h2>
<p>Suppose a GET test checks only HTTP 200. That may be entirely appropriate for an availability check. It is inadequate if the title claims that a particular user's details are correct.</p>
<p>Conceptually, a functional check might look like this:</p>
<pre><code class="language-text">GET /users/&lt;known-test-user-id&gt;
assert status matches the contract
assert returned id equals the requested id
assert required fields have the documented types
assert relevant values match the known fixture
</code></pre>
<p>For a create or update journey, a subsequent read can test what another request observes. Use the identifier returned by creation, verify the intended values, and follow the documented consistency model.</p>
<p>Do not derive every expected value from the response being tested. A response compared only with itself provides little protection against incorrect behaviour.</p>
<p>Also distinguish <strong>request accepted</strong>, <strong>processing completed</strong>, and <strong>data persisted</strong>. Which state is promised depends on the endpoint's contract.</p>
<h2>5. Imports need reconciliation at the right level</h2>
<p>A completed job is evidence about the job's reported state. It is not automatically evidence that every intended business record was loaded correctly.</p>
<p>For a fictional import of ten parent records, each with two child rows, checking only that ten parents exist could miss all twenty child relationships.</p>
<p>Verify the scope relevant to the case:</p>
<ul>
<li>Expected record identities, not just aggregate counts.</li>
<li>Important field values, effective dates, and ownership.</li>
<li>Parent-child relationships and required child values.</li>
<li>Per-row rejection or warning outcomes where applicable.</li>
<li>Unexpected inserts or updates in the affected scope.</li>
</ul>
<p>Reconcile against the before-state when records may already exist. A total count of ten is not proof that this run created the intended ten records.</p>
<p>For deliberate negative imports, an unrelated staging error does not prove the intended business validation works. Check the expected rejection condition and required absence of unintended changes.</p>
<h2>6. Make sure the assertion controls the result</h2>
<p>A correct assertion can become ineffective when exception handling prevents its failure from reaching the test runner.</p>
<p>For example, this conceptual pattern hides an unsuccessful verification:</p>
<pre><code class="language-text">try:
    verify_saved_value()
catch verification_error:
    log("Verification failed")
continue_to_end_of_test()
</code></pre>
<p>The desired behaviour is to preserve useful diagnostics and ensure the runner records the required verification as failed. Framework-specific syntax varies, but the principle does not: logging a failure is not the same as failing a test.</p>
<p>If using soft assertions, ensure their failures are collected and reported at the appropriate boundary. Cleanup should run as designed without erasing the original failure or silently converting it into a pass.</p>
<h2>7. Check whether your test detects an intentional fault</h2>
<p>In an isolated practice environment, deliberately introduce a small fault: make the saved value wrong, return the wrong identity, or remove an expected child relationship.</p>
<p>Then ask:</p>
<ul>
<li>Does the relevant test fail?</li>
<li>Does it fail at the intended assertion?</li>
<li>Does the message identify the missing or incorrect behaviour?</li>
<li>Would a missing prerequisite cause a different, clearly explained result?</li>
</ul>
<p>This is a focused way to challenge an assertion. Broader mutation testing can systematise similar checks, but one controlled exercise already reveals useful gaps. Do not introduce faults into shared or production environments without an explicitly approved test arrangement.</p>
<h2>8. A short assertion-review checklist</h2>
<p>Before accepting a passing functional test as evidence, review:</p>
<ul>
<li><input disabled type="checkbox" /> The title states a specific, verifiable claim.</li>
<li><input disabled type="checkbox" /> Expected results come from a justified oracle.</li>
<li><input disabled type="checkbox" /> The fixture exercises the intended change or condition.</li>
<li><input disabled type="checkbox" /> The assertion checks the correct record, user, and relationship.</li>
<li><input disabled type="checkbox" /> Observation timing matches documented processing behaviour.</li>
<li><input disabled type="checkbox" /> Incorrect outcomes would make the test fail.</li>
<li><input disabled type="checkbox" /> Exceptions and soft assertions reach the test result correctly.</li>
<li><input disabled type="checkbox" /> Execution evidence supports the scope of the conclusion.</li>
</ul>
<p><strong>A passing test is useful when we can explain what it proves, how it could fail, and what it leaves unverified.</strong></p>
<p>That makes green results more credible inputs to a release decision.</p>
<p>Which assertion have you added that caught a defect your earlier test missed?</p>
]]></content:encoded></item><item><title><![CDATA[One Failed Test, Five Possible Causes: A Practical Guide to Automation Failure Analysis]]></title><description><![CDATA[Investigate failed tests with a fictional timeline, five cause categories, evidence checks, and a reusable failure-triage template.]]></description><link>https://siddhartha-quality-engineering.hashnode.dev/one-failed-test-five-possible-causes-a-practical-guide-to-automation-failure-analysis</link><guid isPermaLink="true">https://siddhartha-quality-engineering.hashnode.dev/one-failed-test-five-possible-causes-a-practical-guide-to-automation-failure-analysis</guid><category><![CDATA[Software Testing]]></category><category><![CDATA[test-automation]]></category><dc:creator><![CDATA[Siddhartha Mukherjee]]></dc:creator><pubDate>Wed, 11 Nov 2026 18:33:47 GMT</pubDate><content:encoded><![CDATA[<p>A UI test fails with a timeout while searching for an invoice. The immediate reaction is familiar: increase the wait, rerun the test, or raise a product bug.</p>
<p>Before choosing any of those actions, I would ask: <strong>Was an invoice ever created?</strong></p>
<p>The last error in a report often describes where execution stopped, not where the problem started. A useful investigation connects the visible failure to the earlier events that made it possible.</p>
<p>In <a href="https://siddhartha-quality-engineering.hashnode.dev/beyond-pass-rates-how-to-assess-whether-a-release-is-ready">Beyond Pass Rates: How to Assess Whether a Release Is Ready</a>, I discussed why release decisions need more than a green dashboard. This follow-up focuses on the evidence behind each red result.</p>
<p>The example below is fictional. Its timestamps, records, and messages are illustrative, not production logs.</p>
<h2>1. Five possible causes of the same visible failure</h2>
<p>Suppose an automated test expects a submitted charge to produce an invoice. It later times out searching for that invoice. Several explanations remain possible:</p>
<table>
<thead>
<tr>
<th>Possible cause</th>
<th>Example</th>
<th>Evidence to seek</th>
</tr>
</thead>
<tbody><tr>
<td>Product defect</td>
<td>Valid input is accepted, but invoice creation fails</td>
<td>Contract, accepted request, processing outcome, persisted state</td>
</tr>
<tr>
<td>Test automation issue</td>
<td>Search uses the wrong reference or an outdated locator</td>
<td>Actual request, DOM state, locator matches, assertion logic</td>
</tr>
<tr>
<td>Environment issue</td>
<td>A required processing service is unavailable</td>
<td>Service health and request-specific processing evidence</td>
</tr>
<tr>
<td>Test-data or setup issue</td>
<td>A required reference record is inactive</td>
<td>Fixture values, effective dates, validation response</td>
</tr>
<tr>
<td>Reporting issue</td>
<td>The transaction succeeds, but attaching evidence fails</td>
<td>Independent transaction verification and reporter error</td>
</tr>
</tbody></table>
<p>These are working categories, not mutually exclusive verdicts. One run can expose several issues. <strong>Undetermined</strong> is a valid classification until the evidence supports something more specific.</p>
<h2>2. Reconstruct the sequence before assigning a cause</h2>
<p>Consider this invented timeline:</p>
<table>
<thead>
<tr>
<th>Time (UTC)</th>
<th>Recorded event</th>
<th>What it establishes</th>
</tr>
</thead>
<tbody><tr>
<td>10:00:01</td>
<td>Charge form submitted with reference DEMO-104</td>
<td>A submission was attempted</td>
</tr>
<tr>
<td>10:00:02</td>
<td>Validation response: required reference is inactive</td>
<td>The application rejected this submission</td>
</tr>
<tr>
<td>10:00:03</td>
<td>Test helper records “submission successful”</td>
<td>The helper reported success; acceptance is not established</td>
</tr>
<tr>
<td>10:00:04</td>
<td>Screenshot attachment raises a reporting error</td>
<td>Evidence attachment failed</td>
</tr>
<tr>
<td>10:00:05</td>
<td>Invoice search begins for DEMO-104</td>
<td>Execution continued into a dependent step</td>
</tr>
<tr>
<td>10:02:05</td>
<td>Invoice search times out</td>
<td>The expected invoice was not found within the search window</td>
</tr>
</tbody></table>
<p>The timeout is real, but it is not enough to conclude that invoice creation is defective.</p>
<p>The earlier rejection changes the investigation. First verify that the validation response belongs to this submission, then check the referenced fixture and the helper's success condition. Preserve timestamps and identifiers that connect those events.</p>
<h2>3. Separate observations from hypotheses</h2>
<p>For this example, the evidence supports these observations:</p>
<ul>
<li>The submission was rejected with a specific validation message.</li>
<li>The helper nevertheless reported success.</li>
<li>The test continued to search for an invoice.</li>
<li>A report attachment failed independently.</li>
<li>The subsequent search timed out.</li>
</ul>
<p>Possible explanations still require checks:</p>
<ul>
<li>Is the reference genuinely inactive in the target environment?</li>
<li>Does the requirement correctly reject that condition?</li>
<li>Did the helper mistake completion of a click or request for business acceptance?</li>
<li>Could the invoice search also have a separate locator or filter problem?</li>
</ul>
<p>A useful record keeps <strong>confirmed findings</strong>, <strong>working hypotheses</strong>, and <strong>missing evidence</strong> separate. A plausible story is not a completed RCA.</p>
<h2>4. Verify the suspected cause with focused checks</h2>
<p>Assume a follow-up check confirms that the reference is inactive and that the documented rule requires an active reference. Reviewing the helper also confirms that it labels any completed submission as successful without examining the business outcome.</p>
<p>We can now describe two established problems: an invalid fixture for this positive case, and a test helper that incorrectly continues after rejection.</p>
<p>The reporting attachment error is a third issue. It should be repaired, but it did not turn the rejected charge into an accepted one.</p>
<p>After correcting the fixture and helper in the practice environment, repeat the relevant flow. Verify acceptance, retrieve the resulting invoice, and compare its reference, account, amount, and expected status.</p>
<p>If that succeeds, it supports the corrected path. It does not prove that invoice creation can never fail, or that every historic timeout had this cause.</p>
<h2>5. Improve the test's decision points</h2>
<p>The test should check the business outcome before entering dependent steps. Conceptually:</p>
<pre><code class="language-text">submit charge
inspect the business outcome
if rejected:
    record the rejection evidence
    fail this positive case
    do not run dependent invoice assertions
if accepted:
    wait for documented processing conditions
    retrieve the invoice using the expected identifier
    verify persisted business values
</code></pre>
<p>For a negative test, rejection may be the expected outcome. It passes only when the intended validation occurs and the required absence of unintended side effects is verified.</p>
<p>For asynchronous processing, acceptance and completion are separate states. A timeout should record the last observed state and relevant processing evidence. Increasing the wait is justified only when it addresses an understood timing requirement; it cannot repair invalid data or incorrect control flow.</p>
<h2>6. Record downstream outcomes explicitly</h2>
<p>Avoid an RCA that says only “invoice timeout.” Describe the causal chain and distinguish what each step actually did.</p>
<p>For this fictional case:</p>
<blockquote>
<p>The positive charge submission was rejected because its required reference was inactive. The helper incorrectly reported success and continued to a dependent invoice search, which timed out. A separate screenshot-attachment error reduced report completeness. No successful charge acceptance was established in the original attempt.</p>
</blockquote>
<p>For later steps, use precise outcomes: <strong>succeeded</strong>, <strong>failed</strong>, <strong>continued without verification</strong>, or <strong>not recorded</strong>. A log line saying “navigating” is not evidence that navigation completed successfully.</p>
<h2>7. A reusable failure-triage template</h2>
<p>Use this template for a reviewable investigation:</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>What to record</th>
</tr>
</thead>
<tbody><tr>
<td>Context</td>
<td>Test, build, environment, role, run ID, and time window</td>
</tr>
<tr>
<td>Failed step</td>
<td>Exact operation and assertion</td>
</tr>
<tr>
<td>Expected result</td>
<td>Requirement or test contract</td>
</tr>
<tr>
<td>Actual result</td>
<td>Observed behaviour, without interpretation</td>
</tr>
<tr>
<td>Evidence</td>
<td>Relevant log lines, response, screenshot, or state check</td>
</tr>
<tr>
<td>Earliest relevant failure</td>
<td>First event that may explain dependent failures</td>
</tr>
<tr>
<td>Classification</td>
<td>Product, testware, environment, data/setup, reporting, or undetermined</td>
</tr>
<tr>
<td>Cause and confidence</td>
<td>Confirmed cause or hypothesis, with supporting checks</td>
</tr>
<tr>
<td>Downstream impact</td>
<td>Later steps and their recorded outcomes</td>
</tr>
<tr>
<td>Next action</td>
<td>Specific investigation or correction and accountable owner</td>
</tr>
<tr>
<td>Verification</td>
<td>How the correction will be checked and what remains untested</td>
</tr>
</tbody></table>
<p>Different causes may need separate tracking items. Repeated symptoms with the same confirmed cause may share one primary item. Keep the mapping between runs, evidence, and tracking items explicit.</p>
<p><strong>The aim of triage is to explain what the test actually proves, identify what remains unknown, and make the next action defensible.</strong></p>
<p>What do you check first when a failed test ends with a timeout?</p>
]]></content:encoded></item><item><title><![CDATA[Beyond Pass Rates: How to Assess Whether a Release Is Ready]]></title><description><![CDATA[Assess release readiness through failure analysis, critical journeys, coverage gaps, verified fixes, and explicit risk decisions.]]></description><link>https://siddhartha-quality-engineering.hashnode.dev/beyond-pass-rates-how-to-assess-whether-a-release-is-ready</link><guid isPermaLink="true">https://siddhartha-quality-engineering.hashnode.dev/beyond-pass-rates-how-to-assess-whether-a-release-is-ready</guid><category><![CDATA[Software Testing]]></category><category><![CDATA[Quality Assurance]]></category><category><![CDATA[test-automation]]></category><dc:creator><![CDATA[Siddhartha Mukherjee]]></dc:creator><pubDate>Wed, 11 Nov 2026 18:20:49 GMT</pubDate><content:encoded><![CDATA[<p>A regression dashboard shows 95% passed. The release meeting starts in ten minutes. Is the build ready?</p>
<p>My answer would start with another question: <strong>What does that percentage leave out?</strong></p>
<p>A pass rate is useful evidence, but a release decision needs context: the business journeys affected, the credibility of the tests, the scope not exercised, and the consequences of being wrong.</p>
<p>This article uses a fictional release to show a practical way to make that assessment. It does not describe any employer's internal systems or release process.</p>
<h2>1. Start by checking what the number means</h2>
<p>Suppose a planned regression suite contains 1,000 tests:</p>
<table>
<thead>
<tr>
<th>Outcome</th>
<th align="right">Count</th>
</tr>
</thead>
<tbody><tr>
<td>Passed</td>
<td align="right">950</td>
</tr>
<tr>
<td>Failed</td>
<td align="right">20</td>
</tr>
<tr>
<td>Not executed: pending, skipped, or blocked</td>
<td align="right">30</td>
</tr>
<tr>
<td>Total planned</td>
<td align="right">1,000</td>
</tr>
</tbody></table>
<p>The suite has a <strong>95% pass rate against planned tests</strong>: 950 / 1,000.</p>
<p>If the dashboard calculates pass rate using only executed tests, it reports <strong>97.9%</strong>: 950 / 970.</p>
<p>Both calculations are arithmetically correct. They answer different questions. The second excludes 30 tests whose results are unknown.</p>
<p>Before interpreting a dashboard, confirm its denominator, the meaning of each status, the build and environment tested, and whether retries replaced first-attempt results. Keep pending, skipped, and blocked counts visible separately; grouping them here is only a simplified example.</p>
<h2>2. Investigate the first meaningful failure</h2>
<p>Twenty failed tests do not necessarily represent twenty independent product defects. A single setup failure can prevent several later checks from reaching the behaviour they were intended to verify.</p>
<p>For each failure, capture:</p>
<ul>
<li>The exact step, expected behaviour, and observed result.</li>
<li>The earliest relevant error and its timestamp.</li>
<li>The record, user role, build, and environment involved.</li>
<li>Whether subsequent steps succeeded, failed, or were never reached.</li>
<li>The evidence supporting the proposed cause and what remains uncertain.</li>
</ul>
<p>A useful working classification is <strong>product, testware, environment, test data/setup, reporting, or undetermined</strong>.</p>
<p>For example, a rejected transaction followed by an invoice-search timeout should first be investigated at the rejection. The timeout may be a downstream symptom. Conversely, an exception in a screenshot attachment does not automatically mean the business transaction failed.</p>
<p>These classifications are investigation aids. Calling something an environment issue does not establish that the affected business journey works.</p>
<h2>3. Map failures to business consequences</h2>
<p>Consider two possible outcomes from the same 95% dashboard:</p>
<p><strong>Release A:</strong> A critical payment journey fails for a supported user role. The failure is reproducible, and no acceptable workaround has been demonstrated.</p>
<p><strong>Release B:</strong> The failed checks concern lower-impact presentation behaviour. Critical journeys have passed on the candidate build, and the remaining issues have documented workarounds and accountable owners.</p>
<p>The percentages are identical. The release risks differ.</p>
<p>For each affected journey, ask who is impacted, how often the condition occurs, whether data integrity or access controls are involved, and whether users can complete the task another way.</p>
<p>Keep <strong>severity, likelihood, exposure, and evidence confidence</strong> explicit. One label rarely communicates all four.</p>
<h2>4. Treat missing coverage as uncertainty</h2>
<p>A test that did not run supplies no evidence that its requirement passed. A test that passed with the wrong fixture may supply little useful evidence either.</p>
<p>Review the 30 unexecuted tests in our example:</p>
<ul>
<li>Which requirements and user roles do they cover?</li>
<li>Are they blocked by missing data, an unavailable environment, or unfinished automation?</li>
<li>Is there independent API, manual, or integration evidence for the same behaviour?</li>
<li>Does that alternative evidence apply to the candidate build and relevant configuration?</li>
</ul>
<p>Alternative evidence can reduce uncertainty, but it should be traceable and genuinely test the requirement. A mocked success response is not equivalent to checking that a real record persisted correctly.</p>
<p>A simple coverage matrix connecting critical journeys to requirements, roles, test results, and evidence gaps is often more useful than a larger aggregate percentage.</p>
<h2>5. Evaluate retries and fixes honestly</h2>
<p>A successful rerun is evidence that a test passed on that attempt. It does not, by itself, explain why the earlier run failed.</p>
<p>Retain first-attempt outcomes and investigate repeated intermittency. Otherwise, repeatedly retrying until green can hide reliability problems.</p>
<p>Similarly, keep these states distinct:</p>
<p><strong>Fix proposed → fix merged → fix deployed → targeted verification passed → affected regression checked.</strong></p>
<p>A merged change is not evidence that the candidate environment contains it. A targeted test passing does not automatically establish that related journeys remain unaffected.</p>
<p>The investigation should show which state has actually been reached, with supporting build or deployment information where available.</p>
<h2>6. Make the recommendation actionable</h2>
<p>A Principal Quality Engineer should translate technical findings into a decision others can assess.</p>
<p>A fictional release review might contain:</p>
<table>
<thead>
<tr>
<th>Finding</th>
<th>Evidence state</th>
<th>Recommended action</th>
</tr>
</thead>
<tbody><tr>
<td>Payment submission fails for a supported role</td>
<td>Reproduced on the candidate build</td>
<td>Resolve and verify before releasing the affected scope</td>
</tr>
<tr>
<td>Account-update checks blocked by a missing fixture</td>
<td>Behaviour remains unverified</td>
<td>Restore the fixture or obtain equivalent evidence</td>
</tr>
<tr>
<td>Intermittent search timeout</td>
<td>Rerun passed; cause unconfirmed</td>
<td>Investigate frequency, impact, and release exposure</td>
</tr>
<tr>
<td>Report attachment error</td>
<td>Transaction independently verified</td>
<td>Repair reporting and preserve verification evidence</td>
</tr>
</tbody></table>
<p>Possible recommendations include holding the release, reducing scope, or proceeding with explicitly accepted residual risk. The appropriate release authority owns the final decision; QA provides the evidence, recommendation, and unresolved questions.</p>
<p>Avoid broad statements such as “safe to release” when the evidence only supports a narrower conclusion.</p>
<h2>7. A checklist for the next release review</h2>
<p>Before recommending a release, check:</p>
<ul>
<li><input disabled type="checkbox" /> The pass-rate denominator and status definitions are understood.</li>
<li><input disabled type="checkbox" /> The evidence applies to the candidate build and relevant environment.</li>
<li><input disabled type="checkbox" /> Critical business journeys and supported roles have credible coverage.</li>
<li><input disabled type="checkbox" /> Failures are investigated, with primary causes separated from downstream symptoms.</li>
<li><input disabled type="checkbox" /> Pending, skipped, and blocked work is visible, with its impact explained.</li>
<li><input disabled type="checkbox" /> Reruns and intermittent failures remain traceable.</li>
<li><input disabled type="checkbox" /> Required fixes are deployed and verified, with appropriate regression evidence.</li>
<li><input disabled type="checkbox" /> Residual risks have owners, mitigation, and explicit acceptance where required.</li>
<li><input disabled type="checkbox" /> Monitoring and rollback arrangements are understood for the affected scope.</li>
</ul>
<p><strong>The question I want a release review to answer is: What can we confidently say works, what remains uncertain, and who is accepting the remaining risk?</strong></p>
<p>That gives a pass rate its proper context and makes the recommendation useful.</p>
<p>What evidence has changed your release recommendation even when the dashboard looked green?</p>
]]></content:encoded></item></channel></rss>