<?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: Aleksandr Singer</title>
    <description>The latest articles on DEV Community by Aleksandr Singer (@aleksandr_singer_e51bc835).</description>
    <link>https://dev.to/aleksandr_singer_e51bc835</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%2F4024603%2Fb79ed132-82c6-458b-a2aa-cbe247d7c39d.png</url>
      <title>DEV Community: Aleksandr Singer</title>
      <link>https://dev.to/aleksandr_singer_e51bc835</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aleksandr_singer_e51bc835"/>
    <language>en</language>
    <item>
      <title>How QA Testers Are Actually Using AI in 2026 (Prompts Included)</title>
      <dc:creator>Aleksandr Singer</dc:creator>
      <pubDate>Fri, 17 Jul 2026 00:55:09 +0000</pubDate>
      <link>https://dev.to/aleksandr_singer_e51bc835/how-qa-testers-are-actually-using-ai-in-2026-prompts-included-5568</link>
      <guid>https://dev.to/aleksandr_singer_e51bc835/how-qa-testers-are-actually-using-ai-in-2026-prompts-included-5568</guid>
      <description>&lt;h2&gt;
  
  
  How QA Testers Are Actually Using AI in 2026 (Prompts Included)
&lt;/h2&gt;

&lt;p&gt;Every few months a new wave of "AI will replace testers" takes shows up in my feed, followed by an equal and opposite wave of "AI can't understand testing at all." Both miss what's actually happening on the ground.&lt;/p&gt;

&lt;p&gt;Here's the real shift: testers who write clear, specific prompts are getting noticeably more done in the same hours. Testers who type "write me some test cases" and expect magic are getting the same generic, useless output everyone else gets from lazy prompting.&lt;/p&gt;

&lt;p&gt;The gap isn't the AI. It's the prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why generic AI advice doesn't work for QA
&lt;/h3&gt;

&lt;p&gt;Most "prompt engineering" content out there is written for marketers and content creators. It teaches you to get better blog outlines and better ad copy. None of it teaches you how to get an AI to think about boundary values, race conditions, or regression risk — because none of it was written by someone who does this job.&lt;/p&gt;

&lt;p&gt;Ask an AI assistant to "write test cases for the login feature" and you'll get five happy-path cases and maybe one password-mismatch case. Technically test cases. Practically useless.&lt;/p&gt;

&lt;h3&gt;
  
  
  What a genuinely useful QA prompt looks like
&lt;/h3&gt;

&lt;p&gt;Compare that to something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"List test cases for [FEATURE] specifically covering concurrency and race conditions where multiple users act on the same resource."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That one prompt forces the AI out of happy-path mode and into the territory that actually breaks production — two users editing the same record, a double-submit on a slow connection, a webhook firing twice. It's not a smarter AI. It's a smarter question.&lt;/p&gt;

&lt;p&gt;The pattern holds everywhere in QA: the more your prompt encodes an actual testing concept (boundary values, negative space, regression blast radius), the more useful the output. Generic prompts get generic test cases. Specific prompts get the kind of test cases a senior tester would actually write.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bigger shift
&lt;/h3&gt;

&lt;p&gt;This mirrors what's happening industry-wide. AI is increasingly handling the repetitive execution layer of QA — drafting the first pass of test cases, structuring a messy bug report, generating boilerplate test data — while the tester's job shifts toward two things: asking for the right thing, and critically reviewing what comes back before trusting it. Neither of those is optional. An AI-drafted test plan that nobody checks against the actual system is just a faster way to miss things.&lt;/p&gt;

&lt;p&gt;That second part matters as much as the first. Treat AI output here the way you'd treat a junior tester's first draft — a useful starting point, never the final answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you want the full set
&lt;/h3&gt;

&lt;p&gt;I put together a toolkit of 40 of these — organized into test case generation, edge-case brainstorming, bug report drafting, regression/risk analysis, test data generation, and exploratory testing charters — plus a couple of tools that make the difference between "AI slop" and something you'd actually ship: a checklist for verifying AI output before you trust it, and a context primer that sharpens every prompt's results by giving the AI your actual project details up front.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://singeraleksandr.gumroad.com/l/ai-prompts-qa-testers?utm_source=devto&amp;amp;utm_campaign=launch&amp;amp;utm_medium=organic" rel="noopener noreferrer"&gt;Check out the AI Prompt Toolkit for QA Testers &amp;amp; SDETs →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>qa</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Breaking Into Software QA</title>
      <dc:creator>Aleksandr Singer</dc:creator>
      <pubDate>Fri, 10 Jul 2026 23:46:04 +0000</pubDate>
      <link>https://dev.to/aleksandr_singer_e51bc835/breaking-into-software-qa-4cmp</link>
      <guid>https://dev.to/aleksandr_singer_e51bc835/breaking-into-software-qa-4cmp</guid>
      <description>&lt;h1&gt;
  
  
  Testing a Login Feature the Way You'd Actually Do It on the Job
&lt;/h1&gt;

&lt;p&gt;A lot of QA content teaches testing techniques in isolation — here's equivalence partitioning, here's boundary value analysis, here's how to write a bug report. All useful, but it rarely shows how those pieces come together on a single, real feature.&lt;/p&gt;

&lt;p&gt;So here's one walkthrough, start to finish: testing a login feature manually, at the API level, and with automation — the way you'd actually approach it with a sprint deadline, not in a vacuum.&lt;/p&gt;

&lt;h2&gt;
  
  
  The feature
&lt;/h2&gt;

&lt;p&gt;A web and mobile app lets a user log in with an email and password. On success, they land on a dashboard. After 5 failed attempts within 10 minutes, the account locks for 15 minutes.&lt;/p&gt;

&lt;p&gt;Simple on the surface. There's more here than "type password, click button."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Manual test design
&lt;/h2&gt;

&lt;p&gt;Before touching a keyboard, map out what actually needs checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Happy path&lt;/strong&gt;: valid email + valid password logs in successfully&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boundary&lt;/strong&gt;: exactly 5 failed attempts triggers lockout; 4 attempts does not&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Negative&lt;/strong&gt;: wrong password, non-existent email, empty fields, SQL-injection-style input in the email field&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session&lt;/strong&gt;: does refreshing the page keep the user logged in? Does logging out on web also affect the mobile session?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile-specific&lt;/strong&gt;: biometric login after the first successful password login, app backgrounded mid-login&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That boundary case — exactly 5 attempts vs. 4 — is the kind of thing that's easy to skip if you're only thinking in terms of "test the lockout feature" rather than testing the &lt;em&gt;number&lt;/em&gt; itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: API-level tests
&lt;/h2&gt;

&lt;p&gt;UI tests are slow and brittle compared to hitting the API directly. Before automating anything visual, these are worth locking down at the API layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /login&lt;/code&gt; with valid credentials returns &lt;code&gt;200&lt;/code&gt; and a token&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /login&lt;/code&gt; with invalid credentials returns &lt;code&gt;401&lt;/code&gt;, not &lt;code&gt;500&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /login&lt;/code&gt; six times in a row returns &lt;code&gt;423&lt;/code&gt; (locked) on the 6th attempt&lt;/li&gt;
&lt;li&gt;A request with an expired token returns &lt;code&gt;401&lt;/code&gt;, not a silent failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That third one matters more than it looks. A refactor that accidentally changes the lockout threshold, or breaks it entirely, is exactly the kind of regression that a UI-only test suite tends to miss — because the UI still &lt;em&gt;looks&lt;/em&gt; fine right up until someone tries to actually break in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: What to automate vs. keep manual
&lt;/h2&gt;

&lt;p&gt;Not everything here deserves the same treatment.&lt;/p&gt;

&lt;p&gt;The happy path and the lockout boundary are stable, high-value, and get exercised on every release — strong candidates for automation at both the API and UI level. A minimal Page Object for this might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pages/login_page.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pages.base_page&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BasePage&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasePage&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;EMAIL_INPUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;PASSWORD_INPUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;LOGIN_BUTTON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CSS_SELECTOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;button[type=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;submit&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="n"&gt;ERROR_MESSAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLASS_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error-message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EMAIL_INPUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PASSWORD_INPUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LOGIN_BUTTON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_error_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ERROR_MESSAGE&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_login.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_account_locks_after_5_attempts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;login_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoginPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/login&lt;/span&gt;&lt;span class="sh"&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;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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="n"&gt;login_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&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@example.com&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;wrong-password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;login_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&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@example.com&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;correct-password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;locked&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;login_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_error_text&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meanwhile, usability observations — is the lockout message actually clear to a first-time user? — and one-off exploratory checks are better left manual. They rely on human judgment, not a pass/fail assertion, and automating them just gives you a brittle test that doesn't actually check the thing you care about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Prioritizing under time pressure
&lt;/h2&gt;

&lt;p&gt;If a release is tomorrow and there's only time for a fraction of this list, the lockout boundary and the API-level auth checks go first. They protect account security, and they're exactly the kind of thing that quietly breaks when someone refactors the login service — and exactly the kind of bug that reaches production unnoticed if the only thing being checked is the UI happy path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern, generalized
&lt;/h2&gt;

&lt;p&gt;Strip away the login specifics and the shape underneath is reusable for almost any feature:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Design test cases across happy path, boundaries, and negative cases&lt;/li&gt;
&lt;li&gt;Identify what can be verified faster and more reliably at the API layer&lt;/li&gt;
&lt;li&gt;Decide what's actually worth automating vs. what needs a human's judgment&lt;/li&gt;
&lt;li&gt;When time is short, prioritize by what protects the business most, not what's easiest to test&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the difference between "I know some testing techniques" and "I can design a test strategy for a real feature" — and it's the second one that actually gets asked about in interviews.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This walkthrough is adapted from a chapter in &lt;a href="https://singeraleksandr.gumroad.com/l/breaking-into-software-qa?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;Breaking Into Software QA&lt;/a&gt;, a complete guide to breaking into software QA — manual and automated testing, API testing, mobile/Appium, real working automation code, and a full job search roadmap.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
