<?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: Vladimir Ternovoy</title>
    <description>The latest articles on DEV Community by Vladimir Ternovoy (@terfree).</description>
    <link>https://dev.to/terfree</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%2F3992045%2F3d3ba091-2ef9-471d-8dad-aeb3f0882a41.jpg</url>
      <title>DEV Community: Vladimir Ternovoy</title>
      <link>https://dev.to/terfree</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/terfree"/>
    <language>en</language>
    <item>
      <title>Why toast-only Playwright tests are not enough</title>
      <dc:creator>Vladimir Ternovoy</dc:creator>
      <pubDate>Sat, 20 Jun 2026 11:12:11 +0000</pubDate>
      <link>https://dev.to/terfree/why-toast-only-playwright-tests-are-not-enough-2mb9</link>
      <guid>https://dev.to/terfree/why-toast-only-playwright-tests-are-not-enough-2mb9</guid>
      <description>&lt;p&gt;AI-generated end-to-end tests often look useful at first glance.&lt;/p&gt;

&lt;p&gt;They click through a flow.&lt;/p&gt;

&lt;p&gt;They wait for something visible.&lt;/p&gt;

&lt;p&gt;They pass.&lt;/p&gt;

&lt;p&gt;But sometimes the entire assertion is basically this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.toast-success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is not always wrong.&lt;/p&gt;

&lt;p&gt;A toast assertion can be useful.&lt;/p&gt;

&lt;p&gt;The problem starts when the toast is the only assertion for a critical business flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  A success toast is not a business outcome
&lt;/h2&gt;

&lt;p&gt;Imagine a checkout test.&lt;/p&gt;

&lt;p&gt;The test selects a plan, enters payment details, clicks “Pay”, and then checks that a green success toast appears.&lt;/p&gt;

&lt;p&gt;That proves only one thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The frontend displayed a success message.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does not prove that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the order was actually persisted&lt;/li&gt;
&lt;li&gt;the selected plan was applied&lt;/li&gt;
&lt;li&gt;the final price was correct&lt;/li&gt;
&lt;li&gt;the payment state changed correctly&lt;/li&gt;
&lt;li&gt;the subscription was activated&lt;/li&gt;
&lt;li&gt;a confirmation email or background job was triggered&lt;/li&gt;
&lt;li&gt;the backend accepted the correct request payload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The UI can show a success toast even if the backend state is wrong.&lt;/p&gt;

&lt;p&gt;That is why toast-only tests can create false confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with AI-generated tests
&lt;/h2&gt;

&lt;p&gt;General AI tools often generate tests by looking at the visible UI.&lt;/p&gt;

&lt;p&gt;They are good at producing steps like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pay&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.toast-success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But they may not understand the business rules behind the flow.&lt;/p&gt;

&lt;p&gt;For checkout, the real question is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the user see a green toast?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The real questions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was the correct plan selected?&lt;/li&gt;
&lt;li&gt;Was the price calculated server-side?&lt;/li&gt;
&lt;li&gt;Was the discount validated?&lt;/li&gt;
&lt;li&gt;Was the order created?&lt;/li&gt;
&lt;li&gt;Was the subscription updated?&lt;/li&gt;
&lt;li&gt;Did the system reject manipulated client-side values?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without that context, the test may pass while the product is still broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo PR: a toast-only checkout test
&lt;/h2&gt;

&lt;p&gt;I created a small public demo PR that adds a Playwright checkout test with exactly this problem.&lt;/p&gt;

&lt;p&gt;Public demo PR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TerFree70/qa-boutique-demo-checkout-risk/pull/2" rel="noopener noreferrer"&gt;https://github.com/TerFree70/qa-boutique-demo-checkout-risk/pull/2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test clicks through checkout and checks only this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.toast-success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PR looks reasonable at first glance: it adds a Playwright test, clicks through the checkout flow, and checks a visible success signal.&lt;/p&gt;

&lt;p&gt;But it still does not verify the actual checkout outcome.&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%2Fjiha4xktoi5acf6z0b4u.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%2Fjiha4xktoi5acf6z0b4u.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the PR risk scanner detected
&lt;/h2&gt;

&lt;p&gt;The free QA Boutique PR Risk Scanner flagged this pull request as high risk.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because the PR touched a test for a critical flow — checkout — but the assertion did not prove the business outcome.&lt;/p&gt;

&lt;p&gt;The GitHub Actions summary generated a reviewer checklist with questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the selected plan persisted and used by the backend?&lt;/li&gt;
&lt;li&gt;Is the final price calculated server-side?&lt;/li&gt;
&lt;li&gt;Can checkout be manipulated through URL or query parameters?&lt;/li&gt;
&lt;li&gt;Does the full user flow complete, not only show a success message?&lt;/li&gt;
&lt;li&gt;Does the expected backend state change after the flow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That kind of checklist is useful because it turns a vague review concern into concrete verification steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the AI review found
&lt;/h2&gt;

&lt;p&gt;QA Boutique then analyzed the same PR and found concrete risks.&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%2Fgsoja11w6wurx4zp7ujr.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%2Fgsoja11w6wurx4zp7ujr.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI review identified three issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Missing payment success validation beyond the UI toast.&lt;/li&gt;
&lt;li&gt;No validation of selected plan details in payment.&lt;/li&gt;
&lt;li&gt;No error handling or declined card scenario coverage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key point is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A visible success message is not proof of a completed transaction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A user could see a success toast while:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the payment was not processed&lt;/li&gt;
&lt;li&gt;the subscription was not created&lt;/li&gt;
&lt;li&gt;the wrong plan was selected&lt;/li&gt;
&lt;li&gt;the wrong amount was charged&lt;/li&gt;
&lt;li&gt;the user account state was not updated&lt;/li&gt;
&lt;li&gt;the confirmation flow silently failed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the difference between UI-level confidence and product-level confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the toast assertion, but do not stop there
&lt;/h2&gt;

&lt;p&gt;I would not automatically delete toast assertions.&lt;/p&gt;

&lt;p&gt;They are still useful as UI checks.&lt;/p&gt;

&lt;p&gt;But I would treat them as one layer of validation, not the final proof that the flow works.&lt;/p&gt;

&lt;p&gt;A stronger checkout test might verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;success toast or confirmation UI&lt;/li&gt;
&lt;li&gt;confirmation page or order ID&lt;/li&gt;
&lt;li&gt;selected plan name&lt;/li&gt;
&lt;li&gt;final price&lt;/li&gt;
&lt;li&gt;API response status&lt;/li&gt;
&lt;li&gt;created order state in the test environment&lt;/li&gt;
&lt;li&gt;subscription or billing state&lt;/li&gt;
&lt;li&gt;invalid discount or invalid card behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, instead of only checking this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.toast-success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A stronger test should also check something closer to the actual business outcome:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;order-confirmation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;selected-plan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Startup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final-price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$79.20&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a real test environment, you might also verify backend state directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple review rule
&lt;/h2&gt;

&lt;p&gt;When reviewing AI-generated Playwright tests, I like to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If this test passes, what business fact do we actually know?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A toast appeared.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then the test is probably too weak for regression coverage.&lt;/p&gt;

&lt;p&gt;A better test should prove at least one important business outcome.&lt;/p&gt;

&lt;p&gt;For checkout, that might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the order exists&lt;/li&gt;
&lt;li&gt;the selected plan is correct&lt;/li&gt;
&lt;li&gt;the charged amount is correct&lt;/li&gt;
&lt;li&gt;the subscription is active&lt;/li&gt;
&lt;li&gt;the user can access the paid feature&lt;/li&gt;
&lt;li&gt;the system rejects invalid payment states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For auth, that might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unauthorized users are rejected&lt;/li&gt;
&lt;li&gt;users cannot access another workspace&lt;/li&gt;
&lt;li&gt;role-based permissions are enforced on the backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For billing, that might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;coupons are validated server-side&lt;/li&gt;
&lt;li&gt;subscription status changes correctly&lt;/li&gt;
&lt;li&gt;failed payments do not unlock paid features&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical checklist
&lt;/h2&gt;

&lt;p&gt;For critical flows like checkout, auth, billing, subscriptions, or permissions, I would check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the test verify a real business outcome?&lt;/li&gt;
&lt;li&gt;Does it assert backend state or API result where possible?&lt;/li&gt;
&lt;li&gt;Does it cover at least one negative or error case?&lt;/li&gt;
&lt;li&gt;Does it avoid relying only on generic success messages?&lt;/li&gt;
&lt;li&gt;Does it prove the behavior that would matter in production?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Toast assertions are fine.&lt;/p&gt;

&lt;p&gt;Toast-only regression coverage is the risky part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related tool
&lt;/h2&gt;

&lt;p&gt;I also built a free read-only GitHub Action around this idea:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/marketplace/actions/qa-boutique-pr-risk-scanner" rel="noopener noreferrer"&gt;https://github.com/marketplace/actions/qa-boutique-pr-risk-scanner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It does not use AI, does not upload code, and does not require write access.&lt;/p&gt;

&lt;p&gt;It flags risky PR areas such as checkout, pricing, auth, API changes, and missing test signals before merge.&lt;/p&gt;

&lt;p&gt;Source code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TerFree70/qa-boutique-pr-risk-scanner" rel="noopener noreferrer"&gt;https://github.com/TerFree70/qa-boutique-pr-risk-scanner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For deeper AI PR review:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qaboutique.com/#free-pr-audit" rel="noopener noreferrer"&gt;https://qaboutique.com/#free-pr-audit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d be curious how other teams handle this:&lt;/p&gt;

&lt;p&gt;Do you treat toast-only Playwright tests as useful smoke checks, or do you require business-outcome assertions for critical flows like checkout, auth, and billing?&lt;/p&gt;

</description>
      <category>qa</category>
      <category>githubactions</category>
      <category>playwright</category>
      <category>testing</category>
    </item>
    <item>
      <title>I built a read-only GitHub Action to flag risky PRs before merge</title>
      <dc:creator>Vladimir Ternovoy</dc:creator>
      <pubDate>Fri, 19 Jun 2026 07:25:53 +0000</pubDate>
      <link>https://dev.to/terfree/i-built-a-read-only-github-action-to-flag-risky-prs-before-merge-35d3</link>
      <guid>https://dev.to/terfree/i-built-a-read-only-github-action-to-flag-risky-prs-before-merge-35d3</guid>
      <description>&lt;p&gt;Most CI checks answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the code compile?&lt;/li&gt;
&lt;li&gt;Do the tests pass?&lt;/li&gt;
&lt;li&gt;Does linting pass?&lt;/li&gt;
&lt;li&gt;Is formatting correct?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those checks are useful, but they often miss a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did this pull request touch a risky product area?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That was the reason I built QA Boutique PR Risk Scanner — a free read-only GitHub Action that flags risky PR areas before merge.&lt;/p&gt;

&lt;p&gt;For example, a pull request that changes checkout, pricing, authentication, permissions, API routes, or billing logic probably deserves a different level of review than a small UI copy change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;The action is intentionally simple.&lt;/p&gt;

&lt;p&gt;It does not try to replace code review.&lt;/p&gt;

&lt;p&gt;It does not generate tests.&lt;/p&gt;

&lt;p&gt;It does not use AI.&lt;/p&gt;

&lt;p&gt;It does not upload code anywhere.&lt;/p&gt;

&lt;p&gt;Instead, it looks at the changed files and diff signals in a pull request and writes a lightweight PR risk summary into the GitHub Actions Summary.&lt;/p&gt;

&lt;p&gt;The goal is to give reviewers a useful checklist before merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it checks
&lt;/h2&gt;

&lt;p&gt;The action looks for changes in areas such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;billing&lt;/li&gt;
&lt;li&gt;pricing&lt;/li&gt;
&lt;li&gt;checkout&lt;/li&gt;
&lt;li&gt;subscriptions&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;authorization&lt;/li&gt;
&lt;li&gt;permissions&lt;/li&gt;
&lt;li&gt;API routes&lt;/li&gt;
&lt;li&gt;backend logic&lt;/li&gt;
&lt;li&gt;critical user flows&lt;/li&gt;
&lt;li&gt;test / CI changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also warns when production files changed but no related test files were detected.&lt;/p&gt;

&lt;p&gt;This is not a perfect signal, of course.&lt;/p&gt;

&lt;p&gt;But it is often enough to make reviewers stop and ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Should this PR have regression tests?&lt;br&gt;
Should QA review this flow?&lt;br&gt;
Could this affect billing, auth, or checkout?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why read-only matters
&lt;/h2&gt;

&lt;p&gt;For this kind of tool, I wanted the free GitHub Action to be safe by default.&lt;/p&gt;

&lt;p&gt;So the action is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read-only&lt;/li&gt;
&lt;li&gt;rule-based&lt;/li&gt;
&lt;li&gt;non-AI&lt;/li&gt;
&lt;li&gt;no code upload&lt;/li&gt;
&lt;li&gt;no external API calls&lt;/li&gt;
&lt;li&gt;no write access required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It only reads PR metadata and changed files through GitHub Actions.&lt;/p&gt;

&lt;p&gt;That makes it easier to try in real repositories without giving an external service write access or sending source code outside GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo: risky checkout PR
&lt;/h2&gt;

&lt;p&gt;I created a small public demo repository to show the idea.&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%2Faqezrzwpgygjb20mjn6e.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%2Faqezrzwpgygjb20mjn6e.png" alt=" " width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The demo PR adds a checkout endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/api/checkout/route.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint intentionally contains common business-logic risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hardcoded plan&lt;/li&gt;
&lt;li&gt;hardcoded price&lt;/li&gt;
&lt;li&gt;hardcoded discount&lt;/li&gt;
&lt;li&gt;no request body parsing&lt;/li&gt;
&lt;li&gt;no parameter validation&lt;/li&gt;
&lt;li&gt;no related regression tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The free GitHub Action flags the PR as high risk because it touches checkout, pricing, and API logic.&lt;/p&gt;

&lt;p&gt;It also warns that no related tests were changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the free action stops
&lt;/h2&gt;

&lt;p&gt;The free action is intentionally lightweight.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;This PR touches a risky area.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But it does not deeply understand business logic.&lt;/p&gt;

&lt;p&gt;That is where a deeper AI review can help.&lt;/p&gt;

&lt;p&gt;When I ran the same demo PR through QA Boutique’s AI review, it found concrete issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The checkout endpoint returns a fixed &lt;code&gt;startup&lt;/code&gt; plan, price &lt;code&gt;99&lt;/code&gt;, and discount &lt;code&gt;0.2&lt;/code&gt; regardless of user input.&lt;/li&gt;
&lt;li&gt;The discount is embedded directly in the checkout URL without validation or server-side verification.&lt;/li&gt;
&lt;li&gt;The endpoint ignores the POST request body entirely.&lt;/li&gt;
&lt;li&gt;There is no plan lookup, price calculation, or parameter validation.&lt;/li&gt;
&lt;li&gt;Regression tests should verify different plan selections, discount eligibility, invalid plans, and manipulated checkout URLs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That difference is important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free Action = lightweight PR risk awareness&lt;/li&gt;
&lt;li&gt;QA Boutique AI Review = deeper PR analysis with concrete findings and suggested regression tests&lt;/li&gt;
&lt;/ul&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%2Fg2wwx0gk0eohdcyhfm46.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%2Fg2wwx0gk0eohdcyhfm46.png" alt=" " width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;A pull request can pass normal syntax checks and still break a critical business flow.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;users may be charged the wrong price&lt;/li&gt;
&lt;li&gt;all users may receive the same hardcoded plan&lt;/li&gt;
&lt;li&gt;discount logic may be bypassed&lt;/li&gt;
&lt;li&gt;checkout URLs may be manipulated&lt;/li&gt;
&lt;li&gt;important regression tests may be missing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not always syntax problems.&lt;/p&gt;

&lt;p&gt;They are product and business-logic problems.&lt;/p&gt;

&lt;p&gt;That is why I think PR review tools should not only ask whether code is valid, but also whether the change touches a risky area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The GitHub Action is available on GitHub Marketplace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/marketplace/actions/qa-boutique-pr-risk-scanner" rel="noopener noreferrer"&gt;https://github.com/marketplace/actions/qa-boutique-pr-risk-scanner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TerFree70/qa-boutique-pr-risk-scanner" rel="noopener noreferrer"&gt;https://github.com/TerFree70/qa-boutique-pr-risk-scanner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Public demo repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TerFree70/qa-boutique-demo-checkout-risk" rel="noopener noreferrer"&gt;https://github.com/TerFree70/qa-boutique-demo-checkout-risk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Free AI PR Audit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qaboutique.com/#free-pr-audit" rel="noopener noreferrer"&gt;https://qaboutique.com/#free-pr-audit&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback welcome
&lt;/h2&gt;

&lt;p&gt;I am especially interested in feedback from developers, QA engineers, and engineering managers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Would a lightweight PR risk checklist be useful in your workflow?&lt;/li&gt;
&lt;li&gt;What risky areas should the action detect better?&lt;/li&gt;
&lt;li&gt;Would you prefer this as a GitHub Action, a PR comment, or both?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>testing</category>
      <category>devops</category>
      <category>qa</category>
    </item>
  </channel>
</rss>
