<?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: Ali Eissa</title>
    <description>The latest articles on DEV Community by Ali Eissa (@spospider).</description>
    <link>https://dev.to/spospider</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3956262%2F8fb26d42-294f-4094-9780-eb1d718959de.jpeg</url>
      <title>DEV Community: Ali Eissa</title>
      <link>https://dev.to/spospider</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/spospider"/>
    <language>en</language>
    <item>
      <title>What if UI tests validated user experience instead of selectors?</title>
      <dc:creator>Ali Eissa</dc:creator>
      <pubDate>Thu, 28 May 2026 12:01:30 +0000</pubDate>
      <link>https://dev.to/spospider/what-if-ui-tests-validated-user-experience-instead-of-selectors-54if</link>
      <guid>https://dev.to/spospider/what-if-ui-tests-validated-user-experience-instead-of-selectors-54if</guid>
      <description>&lt;p&gt;Most UI testing today focuses on validating implementation details, whether DOM structure, selectors, or UI hooks.&lt;/p&gt;

&lt;p&gt;But teams don’t ship implementations. They ship user experiences.&lt;/p&gt;

&lt;p&gt;That gap is what I started building VizQA for.&lt;/p&gt;

&lt;p&gt;It’s a lightweight UI testing framework that evaluates applications through visual perception and behavioral expectations. It runs fully locally, without runtime LLM calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is simple:&lt;/strong&gt;&lt;br&gt;
Validate whether the product behaves the way it was intended to be experienced.&lt;/p&gt;
&lt;h3&gt;
  
  
  What this actually means
&lt;/h3&gt;

&lt;p&gt;Instead of testing how the UI is built, VizQA focuses on how it is perceived and used.&lt;/p&gt;

&lt;p&gt;That includes things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expected flows completing end-to-end&lt;/li&gt;
&lt;li&gt;visibility of key elements during flows&lt;/li&gt;
&lt;li&gt;layout correctness across screen sizes&lt;/li&gt;
&lt;li&gt;alignment between intended and actual UX behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a traditional E2E test may pass because a button exists in the DOM. VizQA can fail the test if the button is visually obscured, off-screen, or appears in the wrong context.&lt;/p&gt;

&lt;p&gt;Test sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dependency&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Checkout"&lt;/span&gt;
&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://site.com/"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Creates&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;an&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;downstream&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;return&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;consume."&lt;/span&gt;

&lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dependency_login_mfa&lt;/span&gt;

&lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;item_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Widget&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pro&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Secure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Key"&lt;/span&gt;

&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Catalog&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Checkout'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;navigation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;button"&lt;/span&gt;
    &lt;span class="na"&gt;expect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Catalog&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Checkout'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;view&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;should&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;load"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Add&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Widget&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pro&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Secure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Key&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Cart'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;button"&lt;/span&gt;
    &lt;span class="na"&gt;expect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;banner&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;should&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;confirm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{item_name}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;added&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cart"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Complete&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Checkout'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;button"&lt;/span&gt;
    &lt;span class="na"&gt;expect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Orders&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Returns'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;view&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;should&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;load&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;show&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;new&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{item_name}"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  👥 Designed for more than just developers
&lt;/h3&gt;

&lt;p&gt;Because tests are behavioral, not implementation-specific, they can be authored or derived from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;product specs&lt;/li&gt;
&lt;li&gt;UX flows&lt;/li&gt;
&lt;li&gt;QA scenarios&lt;/li&gt;
&lt;li&gt;acceptance criteria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduces the translation layer between:&lt;br&gt;
“what was designed” → “what gets tested”&lt;/p&gt;

&lt;p&gt;And because the same behavioral definitions are used for execution, VizQA allows them to remain stable across runs, being:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fully local&lt;/li&gt;
&lt;li&gt;deterministic (no runtime LLM calls or random AI seeds)&lt;/li&gt;
&lt;li&gt;repeatable in CI and local environments&lt;/li&gt;
&lt;li&gt;lightweight and fast&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  👁️ Visual execution
&lt;/h3&gt;

&lt;p&gt;VizQA relies on UI-Atlas, a local CPU-based perception engine that evaluates what is actually rendered on screen rather than relying only on selectors or DOM structure.&lt;/p&gt;

&lt;p&gt;Under the hood, VizQA evaluates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rendered UI visibility&lt;/li&gt;
&lt;li&gt;flow correctness&lt;/li&gt;
&lt;li&gt;viewport-specific layout behavior&lt;/li&gt;
&lt;li&gt;alignment between expected and actual UI state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows it to detect issues like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;elements not visible in context&lt;/li&gt;
&lt;li&gt;broken flows that still technically “work”&lt;/li&gt;
&lt;li&gt;layout issues across different viewports&lt;/li&gt;
&lt;li&gt;mismatches between expected and actual UI state&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧪 Additional capabilities
&lt;/h3&gt;

&lt;p&gt;Beyond core execution, VizQA also supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-viewport regression testing&lt;/li&gt;
&lt;li&gt;Test prerequisites: flow sections as reusable blocks to build maintainable test suites.&lt;/li&gt;
&lt;li&gt;Library API for embedding into Playwright-based tests, or general automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8228:8000 &lt;span class="nt"&gt;--name&lt;/span&gt; ui-atlas tinyreasonlabs/ui-atlas:latest
pip &lt;span class="nb"&gt;install &lt;/span&gt;vizqa
vizqa &lt;span class="nb"&gt;install
&lt;/span&gt;vizqa run tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/TinyReasonLabs/vizQA#vizqa-vision-driven-web-ui-testing-framework" rel="noopener noreferrer"&gt;VizQA on Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://hub.docker.com/r/tinyreasonlabs/ui-atlas" rel="noopener noreferrer"&gt;UI Atlas on Dockerhub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you try it out, I’d genuinely love feedback. Curious what people think about this approach to UI testing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>playwright</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
