<?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: Ujjwal Kumar Singh</title>
    <description>The latest articles on DEV Community by Ujjwal Kumar Singh (@beinghumantester).</description>
    <link>https://dev.to/beinghumantester</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%2F754236%2F76bdcb36-a466-493b-ace0-97b50a9f1909.png</url>
      <title>DEV Community: Ujjwal Kumar Singh</title>
      <link>https://dev.to/beinghumantester</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/beinghumantester"/>
    <language>en</language>
    <item>
      <title>Stop Asking AI for Test Cases: Building a Gate-Controlled SDET Prompt</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Tue, 28 Jul 2026 06:21:33 +0000</pubDate>
      <link>https://dev.to/beinghumantester/stop-asking-ai-for-test-cases-building-a-gate-controlled-sdet-prompt-2den</link>
      <guid>https://dev.to/beinghumantester/stop-asking-ai-for-test-cases-building-a-gate-controlled-sdet-prompt-2den</guid>
      <description>&lt;p&gt;&lt;strong&gt;How to Get the Maximum Value Out of This Framework&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having built and iterated on this prompt through multiple production edge cases, here are the exact execution strategies I recommend depending on your workflow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Human-in-the-Loop Workflow (Recommended for Chat UI)&lt;/strong&gt;&lt;br&gt;
Run it in two separate chat threads: Don’t let long conversation history degrade your test accuracy. Run Phase 1 in Thread A to get your gap analysis and critical questions. Review the gaps, clarify what you can, and then update your original requirement text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start Thread B for Phase 2:&lt;/strong&gt; Open a fresh conversation, paste the updated requirements + this framework, and jump straight into generation. This completely eliminates context drift and keeps the LLM laser-focused on state mutation rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The 2-Pass Programmatic Auditor (For Automated CI/CD Pipelines)&lt;/strong&gt;&lt;br&gt;
If you’re calling an LLM via API or integrating this into a pre-commit GitHub Action, split the execution into two isolated passes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pass 1: Run Phase 1 &amp;amp; 2 to generate the initial test table.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pass 2 (The Audit Pass):&lt;/strong&gt; Feed the generated table into an isolated, secondary prompt whose only job is to enforce the Verification Check (verifying exact boundary literals, API status codes, and non-mutation assertions). Separation produces drastically higher assertion reliability than asking a model to self-audit in a single turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. How to Live-Demo or Teach This&lt;/strong&gt;&lt;br&gt;
For Live Streams &amp;amp; YouTube: This framework makes for a high-signal live demo. Paste an intentionally ambiguous user story (e.g., a webhook handler or payment endpoint), watch Phase 1 halt at the gate live, discuss the surfaced edge cases on camera, reply PROCEED, and review the generated DEFERRED risk rows. It shifts the content focus from “Look at this cool AI tool” to “This is how Senior SDETs think about systems.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Technical Writing &amp;amp; Post-Mortems:&lt;/strong&gt; The progression from a naive “write me test cases” prompt to a strict 2-phase state-machine framework is a technical narrative in itself. Break down why each gate exists—like forcing non-mutation assertions for negative cases—to show the hidden pitfalls of naive LLM test generation.&lt;/p&gt;

&lt;p&gt;`BEFORE USING THIS PROMPT: Replace [DOMAIN] below with your actual &lt;br&gt;
system context (e.g. "FinTech loan disbursement API" or "B2B SaaS &lt;br&gt;
user management dashboard"). Do not leave it as a placeholder. &lt;br&gt;
The model will not prompt you for this information.&lt;/p&gt;




&lt;p&gt;You are a SDET specialising in [DOMAIN]. You think like both &lt;br&gt;
a tester and a software design engineer. You treat every untested &lt;br&gt;
edge case as a potential production incident. You evaluate not just &lt;br&gt;
the happy path, but database state consistency, side-effects, &lt;br&gt;
idempotency, concurrency, data isolation, performance thresholds, &lt;br&gt;
and cache invalidation on write operations. You do not make &lt;br&gt;
assumptions silently — you surface them explicitly before acting &lt;br&gt;
on them.&lt;/p&gt;

&lt;p&gt;Your goal is to review the provided requirements, identify logical &lt;br&gt;
gaps and ambiguities, and produce a lean, high-coverage test suite &lt;br&gt;
with full traceability back to your analysis.&lt;/p&gt;

&lt;p&gt;You will follow a strict two-phase workflow. Phase 2 does not begin &lt;br&gt;
until I explicitly authorise it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 1: Requirements Analysis and Gap Identification
&lt;/h3&gt;

&lt;p&gt;Thoroughly analyse the requirement text provided below across all &lt;br&gt;
five dimensions before producing a single test case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gap Dimensions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Functional Gaps&lt;/strong&gt;&lt;br&gt;
Unstated behaviour for error states, timeouts, retry logic, or &lt;br&gt;
unexpected user inputs. Missing success and failure definitions. &lt;br&gt;
Undefined default values, fallback behaviour, or missing business &lt;br&gt;
logic branches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;System, Boundary, Observability, and Idempotency Gaps&lt;/strong&gt;&lt;br&gt;
Data volume limits, field length constraints, rate limits, &lt;br&gt;
performance/SLA bounds, concurrency and race conditions, state &lt;br&gt;
transition completeness, missing failure paths, partial failure &lt;br&gt;
rollbacks, missing idempotency and duplicate-request handling, cache &lt;br&gt;
invalidation on write operations, stale read risk after state-changing &lt;br&gt;
calls, undefined TTL or cache invalidation trigger behaviour, and &lt;br&gt;
missing audit, logging, or telemetry requirements. &lt;strong&gt;If the requirement &lt;br&gt;
does not state a response time or throughput SLA, flag this explicitly &lt;br&gt;
as a gap — undefined SLA bounds make performance regression undetectable in CI.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UX and Logic Gaps&lt;/strong&gt;&lt;br&gt;
Inconsistent business rules, missing confirmation steps, undefined &lt;br&gt;
rollback or undo behaviour, unclear sequencing of multi-step flows, &lt;br&gt;
and contradictions between stated rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security, Data Privacy, and Isolation Gaps&lt;/strong&gt;&lt;br&gt;
Authentication and authorisation boundary conditions, privilege &lt;br&gt;
escalation paths, horizontal data isolation (can a user access or &lt;br&gt;
modify records belonging to another user or tenant by manipulating &lt;br&gt;
IDs, tokens, or query parameters — IDOR surface), PII exposure in &lt;br&gt;
logs, responses, or error messages, input injection surface area &lt;br&gt;
(SQL, script, path traversal), and missing session or token &lt;br&gt;
invalidation behaviour.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration and Contract Gaps&lt;/strong&gt;&lt;br&gt;
Assumptions about third-party API behaviour, missing upstream or &lt;br&gt;
downstream error codes, undefined schema validation rules, version &lt;br&gt;
compatibility gaps, and webhook or callback failure and retry &lt;br&gt;
handling.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Phase 1 Output Format:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Critical Questions and Ambiguities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;List your top 5 to 8 gaps as numbered bullet points. Be specific. &lt;br&gt;
Reference the requirement text where possible. Do not be vague.&lt;/p&gt;

&lt;p&gt;Format each gap as:&lt;br&gt;
N. [Gap Dimension] — [Specific question or ambiguity and why it &lt;br&gt;
   matters for test design]&lt;/p&gt;

&lt;p&gt;Coverage rule: Surface significant gaps across these dimensions. &lt;br&gt;
If a dimension genuinely has no critical gap for this requirement, &lt;br&gt;
state: "[Dimension Name]: No critical gaps identified — [one-line &lt;br&gt;
reason]." Do not invent trivial gaps just to fill space, and do &lt;br&gt;
not silently skip a dimension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stated Assumptions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the requirement is incomplete but you can make a reasonable &lt;br&gt;
assumption to unblock analysis, list each assumption with an ID.&lt;/p&gt;

&lt;p&gt;Format:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A-1: [Assumption text and the reason it was needed]&lt;/li&gt;
&lt;li&gt;A-2: [Assumption text and the reason it was needed]&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;STOP HERE.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not generate any test cases yet.&lt;/p&gt;

&lt;p&gt;After completing your gap analysis and assumption list, output &lt;br&gt;
exactly this line and nothing else:&lt;/p&gt;

&lt;p&gt;"Phase 1 complete. Reply PROCEED to generate test cases using &lt;br&gt;
stated assumptions, or provide clarifications and I will revise &lt;br&gt;
my analysis first."&lt;/p&gt;

&lt;p&gt;Wait for my reply before continuing to Phase 2.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 2: Test Case Generation
&lt;/h3&gt;

&lt;p&gt;This phase begins only after I reply with PROCEED or after I &lt;br&gt;
provide clarifications that you have explicitly acknowledged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handling Phase 1 Transition:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If I provide specific clarifications, resolve the corresponding 
gaps or assumptions directly in your test design.&lt;/li&gt;
&lt;li&gt;For any Phase 1 gap that is neither clarified by me nor covered 
by a stated assumption, do NOT generate a test case for that area. 
Instead, add a row at the bottom of the table with:

&lt;ul&gt;
&lt;li&gt;Category: DEFERRED&lt;/li&gt;
&lt;li&gt;Scenario: [Gap ID] — [One-line reason]&lt;/li&gt;
&lt;li&gt;Risk and Priority: Your best assessment of what is at stake if 
this gap is not resolved before release.&lt;/li&gt;
&lt;li&gt;Automation Candidate: N/A&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DEFERRED rows do not count toward the 12 to 20 active case target.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Strict Quality Principles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Coverage Over Quantity:&lt;/strong&gt; Every test case must target a distinct &lt;br&gt;
failure mode, business rule, or boundary condition. No repetitive &lt;br&gt;
variations of the same scenario.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Balanced Distribution:&lt;/strong&gt; Include all three categories. If any &lt;br&gt;
single category represents more than 60% of active cases, this is &lt;br&gt;
flagged in the Coverage Summary as an imbalance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Positive: Confirms valid behavior. Must cover every valid state-machine transition explicitly (e.g., Draft -&amp;gt; Pending, Pending -&amp;gt; Approved), rather than collapsing multi-step workflows into a single generic happy path.&lt;/li&gt;
&lt;li&gt;Negative: Confirms error and invalid state handling. Must also cover every invalid state-machine transition explicitly (e.g., attempting Draft -&amp;gt; Approved while bypassing Pending). Assert the rejection response and confirm the resource state is unchanged.&lt;/li&gt;
&lt;li&gt;Edge or Boundary: Targets limits, state transitions, concurrency, 
idempotency, and unusual-but-valid paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Execution Blueprints for Complex Edge Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Idempotency cases:&lt;/strong&gt; Send the identical request a second time 
with the same idempotency key or payload. Assert that the second 
response returns the same outcome (status code and body) AND no 
duplicate record is created in the DB AND no duplicate event is 
published to the queue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency cases:&lt;/strong&gt; Specify two parallel requests targeting 
the exact same resource state at t=0. Assert that the succeeding 
request returns the expected outcome with full state mutation 
validation AND the failing request returns the conflict response 
(e.g., HTTP 409 Conflict) with full non-mutation validation AND 
the final DB state reflects exactly one completed operation with 
no partial write.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization &amp;amp; Multi-Tenant (IDOR) cases:&lt;/strong&gt; Specify User A's valid 
authentication token in the request headers while supplying User B's 
resource ID in the payload or URI path. Assert an explicit &lt;code&gt;HTTP 403 Forbidden&lt;/code&gt; 
(or &lt;code&gt;404 Not Found&lt;/code&gt; if resource hiding is required) AND zero DB/queue state mutation.
&lt;strong&gt;Teardown:&lt;/strong&gt; Verify User B's resource is in its original pre-test state regardless of whether the IDOR attempt succeeded or failed. Do not assume the system rolled back correctly — assert it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Architectural Assertion Dialect:&lt;/strong&gt; Assertions must match the &lt;br&gt;
target level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API: HTTP status code + exact error or payload keys + relevant 
headers (+ latency SLA threshold if applicable).&lt;/li&gt;
&lt;li&gt;DB: Exact row state, specific field values, and row count delta.&lt;/li&gt;
&lt;li&gt;Queue or Event: Topic or queue name, publish status, partition 
key, and schema field validation.&lt;/li&gt;
&lt;li&gt;UI: Named element visibility, DOM state change, and exact 
user-facing notification text.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deterministic Inputs and Exact Assertions:&lt;/strong&gt; No generic terms. &lt;br&gt;
Use exact boundary values (0, -1, null, 255 chars, empty string), &lt;br&gt;
specific HTTP status codes (422 Unprocessable Entity, 401 &lt;br&gt;
Unauthorized), exact DB field values, or precise error message &lt;br&gt;
strings. If an SLA/timeout exists, specify the latency bound (e.g., &lt;code&gt;&amp;lt; 200ms&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Mutation Validation (Positive Cases):&lt;/strong&gt; For all Positive &lt;br&gt;
cases where the operation creates, updates, or deletes a resource, &lt;br&gt;
the Expected Outcome MUST assert the resulting system state &lt;br&gt;
explicitly. Example: "HTTP 201 Created AND DB record exists with &lt;br&gt;
status='ACTIVE' and created_by='user_id_123' AND audit log entry &lt;br&gt;
written with action='USER_CREATED'."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Non-Mutation Validation (Negative and Boundary Cases):&lt;/strong&gt; &lt;br&gt;
For all Negative and Boundary failure cases, the Expected Outcome &lt;br&gt;
MUST explicitly assert system non-mutation. Example: "HTTP 400 &lt;br&gt;
Bad Request AND no new record written to DB AND no event published &lt;br&gt;
to Kafka AND no audit log entry created."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verification Check:&lt;/strong&gt; Before outputting the table, verify every &lt;br&gt;
row passes all of the following. Rewrite any row that fails.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No generic input or outcome language.&lt;/li&gt;
&lt;li&gt;Every boundary value is a literal.&lt;/li&gt;
&lt;li&gt;Every expected outcome names a specific code, field value, 
element state, or message string.&lt;/li&gt;
&lt;li&gt;Every expected outcome uses the assertion format matching its 
Level column (API: status + payload keys; DB: row state + field 
values + count; Queue: topic + schema + partition key; UI: 
element visibility + DOM state).&lt;/li&gt;
&lt;li&gt;Every Positive write operation row explicitly asserts resulting 
DB or system state.&lt;/li&gt;
&lt;li&gt;Every Negative and Edge row explicitly asserts system 
non-mutation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assumption Traceability:&lt;/strong&gt; Tag any case built on a Phase 1 &lt;br&gt;
assumption with [Assumption: A-N] in the Scenario column.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Suite Scope:&lt;/strong&gt; Target 12 to 20 active test cases. DEFERRED rows &lt;br&gt;
do not count. If the requirements justify more, state the reason &lt;br&gt;
and ask before expanding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clarity and Actionability:&lt;/strong&gt; Every case must be executable by &lt;br&gt;
someone who did not write it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Output Table:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test ID&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Scenario / Intent&lt;/th&gt;
&lt;th&gt;Pre-Conditions, Setup, &amp;amp; Teardown&lt;/th&gt;
&lt;th&gt;Inputs / Test Data&lt;/th&gt;
&lt;th&gt;Expected Outcome and Assertions&lt;/th&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;th&gt;Automation Candidate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TC-01&lt;/td&gt;
&lt;td&gt;Positive&lt;/td&gt;
&lt;td&gt;API+DB&lt;/td&gt;
&lt;td&gt;[Summary. Add [Assumption: A-N] if applicable]&lt;/td&gt;
&lt;td&gt;[Setup: DB seed state, auth token scope, mock states. Teardown: Cleanup user_id_123]&lt;/td&gt;
&lt;td&gt;[Exact payload, headers, query params]&lt;/td&gt;
&lt;td&gt;[HTTP 201 + DB row exists with field='value' + audit log action='X']&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TC-N&lt;/td&gt;
&lt;td&gt;DEFERRED&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;[Gap ID] — [Reason]&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;High / Med / Low&lt;/td&gt;
&lt;td&gt;High / Med / Low&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Column Definitions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Level:&lt;/strong&gt; Primary verification layer. Use API, UI, DB, Queue, 
Contract, or a combination (e.g., API+DB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-Conditions, Setup, &amp;amp; Teardown:&lt;/strong&gt; Exact DB seed data required, auth 
token validity and scope, third-party mock states (e.g., "Payment gateway mock returns HTTP 503 on first call, HTTP 200 on retry"), and explicit post-test cleanup/teardown steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk:&lt;/strong&gt; Production impact severity. Consider data loss, financial 
impact, security exposure, or system crash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Priority:&lt;/strong&gt; Execution urgency. Consider frequency of use, 
regression likelihood, and release blocker status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Candidate:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Yes — deterministic, stable, high regression value.&lt;/li&gt;
&lt;li&gt;No — requires human judgement, visual layout verification, or 
one-time exploratory value only.&lt;/li&gt;
&lt;li&gt;Partial-E — automatable but requires one-time environment or 
test data setup. Note the specific dependency.&lt;/li&gt;
&lt;li&gt;Partial-V — automatable but one or more assertions require 
visual or human judgement. Note the specific assertion blocking 
full automation.&lt;/li&gt;
&lt;li&gt;N/A — DEFERRED rows only.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;After the Table:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provide a Coverage Summary of 5 to 7 lines covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total active cases by category (Positive / Negative / Edge) and 
total DEFERRED count&lt;/li&gt;
&lt;li&gt;Distribution health: flag if any category exceeds 60% of active 
cases and identify which failure modes may be under-tested&lt;/li&gt;
&lt;li&gt;Automation readiness: count of Yes / Partial-E / Partial-V / No, 
and the single biggest blocker to automating the Partial cases&lt;/li&gt;
&lt;li&gt;Highest risk areas identified in the active test cases&lt;/li&gt;
&lt;li&gt;Deferred items listed with their Risk level so the team can 
prioritise which clarification conversations to have first&lt;/li&gt;
&lt;li&gt;Recommended next steps for test automation setup or test data 
provisioning&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Requirements to Analyse:
&lt;/h3&gt;

&lt;p&gt;[PASTE YOUR REQUIREMENTS OR USER STORIES HERE]`&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/beinghumantester/AI-Prompts/blob/main/Test_Case_Prompt.md" rel="noopener noreferrer"&gt;Github Repo Link&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>claude</category>
      <category>ai</category>
      <category>automation</category>
    </item>
    <item>
      <title>Logging Tells You What Happened. Observability Tells You Why.</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Mon, 27 Jul 2026 05:28:59 +0000</pubDate>
      <link>https://dev.to/beinghumantester/logging-tells-you-what-happened-observability-tells-you-why-1hga</link>
      <guid>https://dev.to/beinghumantester/logging-tells-you-what-happened-observability-tells-you-why-1hga</guid>
      <description>&lt;p&gt;Earlier in my career as a tester, I assumed logging and observability were basically the same thing, just different names for checking whether something had broken.&lt;/p&gt;

&lt;p&gt;As I spent more time exploring them I realized they solve different problems. Logging records events that have already happened, while observability helps explain why those events happened and how the system reached that state. That distinction becomes increasingly important as systems grow in complexity.&lt;/p&gt;

&lt;p&gt;A log entry might report a NullPointerException, but it rarely answers the questions that follow. Which release introduced the issue? Which commit caused it? How many users are affected? Which service failed first? What sequence of events led to the failure?&lt;/p&gt;

&lt;p&gt;This is where platforms such as Sentry demonstrate the difference. Similar errors are grouped into a single issue instead of appearing as hundreds of separate alerts. Errors are linked to the relevant commit and source code, while traces, profiling, and session replay provide the context needed to understand what happened before the failure occurred.&lt;/p&gt;

&lt;p&gt;The distinction is simple. Logging answers what happened. Observability helps answer why it happened.&lt;br&gt;
Logs remain an essential part of every system, but logs alone rarely provide enough context for modern distributed applications. As software systems continue to grow, understanding system behavior becomes just as important as collecting data.&lt;/p&gt;

&lt;p&gt;How do you distinguish between logging and observability when investigating production issues?&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>devops</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>The Work Nobody Can See Doesn’t Count Toward Your Career</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Fri, 24 Jul 2026 07:54:43 +0000</pubDate>
      <link>https://dev.to/beinghumantester/the-work-nobody-can-see-doesnt-count-toward-your-career-10m5</link>
      <guid>https://dev.to/beinghumantester/the-work-nobody-can-see-doesnt-count-toward-your-career-10m5</guid>
      <description>&lt;p&gt;Priya found four bugs that mattered. Real ones, the kind that would have hit a payments flow in production: a rounding error in partial refunds, a timeout that left a transaction in limbo, two others that had been sitting in the system for months. She found them by doing one week of deep exploratory testing instead of writing new automation.&lt;/p&gt;

&lt;p&gt;Her manager’s first question in the next 1:1 was not about the bugs. It was whether she was moving away from automation now.&lt;/p&gt;

&lt;p&gt;Those two facts should have had nothing to do with each other. A person found critical defects. A person’s career trajectory came under quiet review. Yet in most testing organizations, those two things are tightly, almost automatically, connected. Why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizations promote what they can see
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiejiff2bgtlss8woiuhw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiejiff2bgtlss8woiuhw.jpeg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Automation leaves evidence behind. A test suite, a pipeline, a framework other people adopt and point to. Someone can look at it in a sprint review, a performance packet, a GitHub profile, and immediately understand what was built.&lt;/p&gt;

&lt;p&gt;Exploratory judgment does not leave the same trail. When it works, what you get is an absence. A bug that never shipped. An incident that never happened. Nobody writes a Jira ticket for the outage that did not occur because someone spent two days poking at an edge case out of a bad feeling. The work is real, the value is real, but it becomes visible mainly in the moment it is missing.&lt;/p&gt;

&lt;p&gt;So when a team has to decide, often without meaning to, what growth looks like, it defaults to the thing it can point at. Not because leadership sat down and decided exploratory testing matters less. Because code is easy to measure and judgment mostly is not, until it fails.&lt;/p&gt;

&lt;p&gt;That same week Priya was hunting timeout bugs, a teammate spent the sprint reducing CI runtime from forty minutes to nine. Nobody asked him where his career was headed. His work was visible by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  One job title, one direction
&lt;/h2&gt;

&lt;p&gt;Here is where it gets structural rather than personal. Most organizations do not actually have four or five distinct testing disciplines with their own ladders. They have one job called tester, sometimes split into junior and senior, and inside that single bucket, progress has to be represented somehow.&lt;/p&gt;

&lt;p&gt;Proximity to code becomes the default measuring stick, not because anyone decided functional testing is worth less, but because a single ladder can only encode one kind of movement clearly.&lt;/p&gt;

&lt;p&gt;Risk analysis, exploratory depth, the instinct for where a system is about to break, none of that fits neatly onto the same axis as commits and pipeline ownership. So it does not show up on the axis at all.&lt;/p&gt;

&lt;p&gt;Priya was not choosing to step backward. She was doing work that had no lane built for it.&lt;/p&gt;

&lt;p&gt;The part that stays invisible even in the roles built to fix this&lt;/p&gt;

&lt;p&gt;A lot of organizations think they have already solved this by creating hybrid roles, people who write automation and also do exploratory testing depending on what the week needs.&lt;/p&gt;

&lt;p&gt;In practice, the hybrid role often does not rebalance anything. It just absorbs the imbalance quietly.&lt;/p&gt;

&lt;p&gt;The person is doing more. They are being recognized for less of it.&lt;/p&gt;

&lt;p&gt;The automation half of their week shows up in the metrics. The exploratory half, the part where they catch the thing the suite would have missed, gets folded into “other duties” or vanishes into general competence. Nothing about the underlying structure changes. The ladder still only rewards the visible half of the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why organizations understand this and still do not fix it
&lt;/h2&gt;

&lt;p&gt;Ask most engineering leaders directly and they will agree the incentive structure is lopsided.&lt;/p&gt;

&lt;p&gt;Very few will actually build a real parallel track for exploratory and risk focused testing, with its own seniority levels and its own comp band.&lt;/p&gt;

&lt;p&gt;Not because they cannot see the problem. Because fixing it costs something specific. It means paying invisible work at parity with visible work, which is a harder argument to win internally than it sounds. It means giving that track real standing on the org chart instead of a consolation title. It means building performance metrics for judgment calls that, by their nature, resist quantification, the same way “prevented an incident” does.&lt;/p&gt;

&lt;p&gt;Avoiding all of that is the easier choice. Most organizations take it. Not out of malice. Out of the ordinary gravity that pulls any system toward what it can already measure.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is bigger than testing
&lt;/h2&gt;

&lt;p&gt;Once you see the pattern, it stops being a testing problem specifically. It shows up anywhere visible output and invisible judgment compete for the same recognition. The engineer who ships a feature gets noticed. The engineer who spent a week arguing the feature was the wrong one to build, and was right, rarely does. The designer who ships a screen is visible. The designer who prevented five bad screens from ever reaching a sprint is not.&lt;/p&gt;

&lt;p&gt;Testing just happens to make the pattern unusually easy to see, because the two kinds of work sit right next to each other on the same team, doing the same job, under the same title.&lt;/p&gt;

&lt;p&gt;Priya did not stop being an automation engineer. She simply did the kind of testing the product needed that particular week. The surprising part was never the work she chose. It was that the work immediately raised a question about her career. That says very little about testing. It says a great deal about how organizations quietly decide what counts as progress.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>automation</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Python for Testers : Validating a JSON API Response Without Any Framework</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Tue, 21 Jul 2026 16:27:25 +0000</pubDate>
      <link>https://dev.to/beinghumantester/python-for-testers-validating-a-json-api-response-without-any-framework-13en</link>
      <guid>https://dev.to/beinghumantester/python-for-testers-validating-a-json-api-response-without-any-framework-13en</guid>
      <description>&lt;p&gt;Most Testers validate API responses inside a test framework. But do we know how to do it with just Python?&lt;/p&gt;

&lt;p&gt;Scenario: Our API returns a JSON response after creating a user. We need to verify the status, the message, and the user details are exactly what we expected.&lt;/p&gt;

&lt;p&gt;Here is the JSON response:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;JSON data: &lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ujjwal"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the Python validation:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Python code: &lt;br&gt;
*&lt;/em&gt;&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&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;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ujjwal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Validation Passed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Validation Failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Validation Passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;****Why this matters as a Tester:&lt;/p&gt;




&lt;p&gt;Before we reach for requests or pytest, understanding how Python reads and validates JSON at the base level makes us a sharper tester. Every API assertion we write in a framework is doing exactly this under the hood.&lt;/p&gt;

&lt;p&gt;Knowing the foundation makes us better at debugging when the framework gives us a result we did not expect.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/beinghumantester/Fundamental-Coding-Programs" rel="noopener noreferrer"&gt;https://github.com/beinghumantester/Fundamental-Coding-Programs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>code</category>
      <category>python</category>
      <category>testing</category>
    </item>
    <item>
      <title>Python for Testers: Finding Unique Status Values from an API Response String</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Mon, 20 Jul 2026 17:47:42 +0000</pubDate>
      <link>https://dev.to/beinghumantester/python-for-testers-finding-unique-status-values-from-an-api-response-string-385b</link>
      <guid>https://dev.to/beinghumantester/python-for-testers-finding-unique-status-values-from-an-api-response-string-385b</guid>
      <description>&lt;p&gt;Ever got a concatenated API response string and needed to know what unique status values were present?&lt;/p&gt;

&lt;p&gt;Scenario: our API returns a long string of status codes like "Automation and Python" and we need to extract every unique status that appeared, in the order it first showed up.&lt;/p&gt;

&lt;p&gt;Here is the Python code:&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="n"&gt;api_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Automation and Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;api_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;api_response&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;ch&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No library. No regex. Just Python iterating through the string and tracking what it has already seen.&lt;/p&gt;

&lt;p&gt;Why this matters as a Tester:&lt;/p&gt;

&lt;p&gt;Not every API response comes in a clean, structured format. Sometimes you are dealing with concatenated strings, log outputs, or raw response bodies. Knowing how to extract unique values from messy string data is a practical skill that shows up more often than we would expect in real test automation work.&lt;/p&gt;

</description>
      <category>python</category>
      <category>testing</category>
      <category>selenium</category>
      <category>automation</category>
    </item>
    <item>
      <title>Today’s Python Challenge for Testers: Deduplicating API Response Values Before Assertion</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Sun, 19 Jul 2026 06:24:33 +0000</pubDate>
      <link>https://dev.to/beinghumantester/todays-python-challenge-for-testers-deduplicating-api-response-values-before-assertion-ko5</link>
      <guid>https://dev.to/beinghumantester/todays-python-challenge-for-testers-deduplicating-api-response-values-before-assertion-ko5</guid>
      <description>&lt;p&gt;Have we ever received an API response with duplicate values and our assertion failed, not because the data was wrong, but because duplicates were messing up our comparison?&lt;/p&gt;

&lt;p&gt;Scenario: our API returns a list of user IDs, but some IDs appear more than once. Before we assert, we need a clean, unique list.&lt;/p&gt;

&lt;p&gt;Here is the Python code :&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="n"&gt;response_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;unique_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response_data&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;data&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;unique_values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;unique_values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output:

[1, 2, 3, 4, 5, 7, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Duplicate data is removed. Now our assertion runs against clean data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters as a Tester:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Asserting against raw API responses without cleaning the data first is a common source of false failures. Understanding how deduplication works at the code level makes us a better judge of when to clean data and when the duplicate itself is the bug.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/beinghumantester/Fundamental-Coding-Programs" rel="noopener noreferrer"&gt;Github Repo Link&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>selenium</category>
      <category>python</category>
      <category>coding</category>
    </item>
    <item>
      <title>Python for SDETs: Comparing Two API Response Arrays</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Sat, 18 Jul 2026 15:42:03 +0000</pubDate>
      <link>https://dev.to/beinghumantester/python-for-sdets-comparing-two-api-response-arrays-lig</link>
      <guid>https://dev.to/beinghumantester/python-for-sdets-comparing-two-api-response-arrays-lig</guid>
      <description>&lt;p&gt;Ever got two API responses and needed to know what matched?&lt;br&gt;
Classic scenario — your API returns a list of user IDs. Your expected list has what should be there. You need to know what actually matched and how many.&lt;br&gt;
Here is the Python pattern I use:&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="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;actual&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;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;matched&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of matching elements:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matched&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;Output *&lt;/em&gt;&lt;br&gt;
Number of matching elements: 2&lt;br&gt;
[14, 16]&lt;/p&gt;

&lt;p&gt;Two values matched. Everything else is either missing or unexpected, both of which are bugs worth reporting.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>testing</category>
      <category>selenium</category>
    </item>
    <item>
      <title>Weekly Challenge-3: Building an AI-Powered Open Source Contribution Assistant with n8n</title>
      <dc:creator>Ujjwal Kumar Singh</dc:creator>
      <pubDate>Mon, 22 Jun 2026 01:45:02 +0000</pubDate>
      <link>https://dev.to/beinghumantester/building-an-ai-powered-open-source-contribution-assistant-with-n8n-1ljn</link>
      <guid>https://dev.to/beinghumantester/building-an-ai-powered-open-source-contribution-assistant-with-n8n-1ljn</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
One challenge in open source is not the lack of opportunities, it’s deciding which opportunity to work on next.&lt;/p&gt;

&lt;p&gt;Many repositories have hundreds of open issues. Some are beginner-friendly, some require deep project knowledge, and others may no longer be relevant. As contributors, we often spend a significant amount of time reviewing issues before making a contribution.&lt;/p&gt;

&lt;p&gt;To explore how automation could help, I built an AI-powered contribution assistant using n8n.&lt;/p&gt;

&lt;p&gt;The goal was to automatically collect issues, evaluate them against predefined criteria, prioritize them, and generate a daily contribution digest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
When reviewing open source repositories, contributors often face questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which issue matches my current skill set?&lt;/li&gt;
&lt;li&gt;Which issue can be worked on within the time I have available?&lt;/li&gt;
&lt;li&gt;Which issue provides the best learning opportunity?&lt;/li&gt;
&lt;li&gt;Which issue has a high probability of resulting in a merged contribution?&lt;/li&gt;
&lt;li&gt;Which issue should I start with today?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Answering these questions manually across multiple repositories can become time-consuming.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;&lt;br&gt;
The workflow automates issue discovery and prioritization.&lt;/p&gt;

&lt;p&gt;It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieves open issues from GitHub repositories&lt;/li&gt;
&lt;li&gt;Filters out pull requests&lt;/li&gt;
&lt;li&gt;Collects issue metadata&lt;/li&gt;
&lt;li&gt;Uses an LLM to analyze and rank opportunities&lt;/li&gt;
&lt;li&gt;Generates a daily digest&lt;/li&gt;
&lt;li&gt;Stores recommendations in Notion for future tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The objective is not to replace contributor judgment, but to reduce the effort required to identify promising contribution opportunities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpdts927321o9ez90ron.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpdts927321o9ez90ron.png" alt=" " width="799" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow Overview&lt;/strong&gt;&lt;br&gt;
The workflow consists of four major stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Issue Collection&lt;/strong&gt;&lt;br&gt;
Issues are fetched from GitHub repositories.&lt;/p&gt;

&lt;p&gt;Relevant information is extracted, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Labels&lt;/li&gt;
&lt;li&gt;Comment count&lt;/li&gt;
&lt;li&gt;Last update time&lt;/li&gt;
&lt;li&gt;Repository source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Issue Evaluation&lt;/strong&gt;&lt;br&gt;
An LLM evaluates issues against predefined criteria such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technology relevance&lt;/li&gt;
&lt;li&gt;Documentation relevance&lt;/li&gt;
&lt;li&gt;Learning value&lt;/li&gt;
&lt;li&gt;Expected effort&lt;/li&gt;
&lt;li&gt;Probability of successful contribution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Recommendation Generation&lt;/strong&gt;&lt;br&gt;
The workflow generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top contribution opportunities&lt;/li&gt;
&lt;li&gt;Quick wins&lt;/li&gt;
&lt;li&gt;Learning-focused opportunities&lt;/li&gt;
&lt;li&gt;A recommended issue to start with&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Knowledge Management&lt;/strong&gt;&lt;br&gt;
Recommendations are stored in Notion and delivered via email.&lt;/p&gt;

&lt;p&gt;This creates a searchable backlog instead of requiring contributors to revisit repositories repeatedly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4wdyqr58fslw75mc3h9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4wdyqr58fslw75mc3h9w.png" alt=" " width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Reduced Decision Fatigue&lt;/strong&gt;&lt;br&gt;
Contributors spend less time searching and more time contributing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent Engagement&lt;/strong&gt;&lt;br&gt;
A daily recommendation can encourage regular participation in open source projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personalized Prioritization&lt;/strong&gt;&lt;br&gt;
Different contributors value different things. The ranking criteria can be adjusted based on individual goals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Visibility&lt;/strong&gt;&lt;br&gt;
Storing recommendations in Notion makes it easier to track contribution opportunities over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges Encountered&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building the workflow surfaced several practical challenges:&lt;/li&gt;
&lt;li&gt;Prompt design significantly impacted recommendation quality.&lt;/li&gt;
&lt;li&gt;Structured JSON outputs were necessary for reliable automation.&lt;/li&gt;
&lt;li&gt;Notion schema mismatches caused workflow failures.&lt;/li&gt;
&lt;li&gt;LLM-generated outputs required validation before downstream processing.&lt;/li&gt;
&lt;li&gt;Integration testing took considerably longer than expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow itself was relatively straightforward. Making the components work reliably together required the most effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Possible Improvements&lt;/strong&gt;&lt;br&gt;
The current workflow works well as a personal assistant, but there are several areas for improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Historical Tracking&lt;/strong&gt;&lt;br&gt;
Track previously recommended issues and avoid recommending the same issue repeatedly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contribution Feedback Loop&lt;/strong&gt;&lt;br&gt;
Record completed contributions and use that information to improve future recommendations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill-Based Profiles&lt;/strong&gt;&lt;br&gt;
Allow contributors to define profiles such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation Contributor&lt;/li&gt;
&lt;li&gt;Automation Engineer&lt;/li&gt;
&lt;li&gt;Backend Developer&lt;/li&gt;
&lt;li&gt;Frontend Developer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and generate recommendations accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Repository Support&lt;/strong&gt;&lt;br&gt;
Expand beyond a single ecosystem and evaluate opportunities across multiple projects.&lt;/p&gt;

&lt;p&gt;**Effort Estimation&lt;br&gt;
**Use issue history and metadata to estimate actual effort more accurately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duplicate Detection&lt;/strong&gt;&lt;br&gt;
Avoid recommending issues that are very similar or represent the same underlying work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly and Monthly Reports&lt;/strong&gt;&lt;br&gt;
Generate summaries that show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Issues reviewed&lt;/li&gt;
&lt;li&gt;Contributions completed&lt;/li&gt;
&lt;li&gt;Skills explored&lt;/li&gt;
&lt;li&gt;Areas of growth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaway&lt;/strong&gt;&lt;br&gt;
The most interesting lesson from this experiment was that the bottleneck was not finding open source work, it was selecting the right work.&lt;/p&gt;

&lt;p&gt;Automating issue discovery and prioritization helped transform a large list of open issues into a smaller set of actionable recommendations.&lt;/p&gt;

&lt;p&gt;While the workflow is still evolving, it demonstrates how automation and AI can be used to reduce overhead and help contributors spend more time learning, building, and contributing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/beinghumantester/n8n_selenium_contribution_agent" rel="noopener noreferrer"&gt;Github Repo Link&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
