<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>User Acceptance Testing · Jared Lynskey</title>
    <link>https://jared.lynskey.co.nz/en/tags/user-acceptance-testing/</link>
    <description>Short stories of value on software engineering and engineering leadership — performance reviews, hiring and scaling teams, CI/CD, DevOps monitoring and agentic AI. Written from Seoul.</description>
    <generator>Hugo</generator>
    <language>en</language>
    <copyright>© 2026 Jared Lynskey</copyright>
    <lastBuildDate>Fri, 23 Oct 2026 00:00:00 +1300</lastBuildDate>
    <atom:link href="https://jared.lynskey.co.nz/en/tags/user-acceptance-testing/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>User Acceptance Testing (UAT): How I Run It and Handle the Feedback</title>
      <link>https://jared.lynskey.co.nz/en/posts/2023/2023-08-27-user-acceptance-testing/</link>
      <guid isPermaLink="true">https://jared.lynskey.co.nz/en/posts/2023/2023-08-27-user-acceptance-testing/</guid>
      <pubDate>Sun, 27 Aug 2023 11:30:03 +0000</pubDate>
      <dc:creator>Jared Lynskey</dc:creator>
      <category>User Acceptance Testing</category>
      <category>UAT</category>
      <category>Software Solutions</category>
      <description>User acceptance testing (UAT) is the last check before launch, where real users try the software on everyday tasks. How I run a round: who to invite, how to write scenarios, how to log and triage UAT feedback, and when to sign off.</description>
      <content:encoded><![CDATA[<p>User acceptance testing (UAT) is the last stage of testing before a release, where the people who will actually use the software try it on their everyday tasks and confirm it does what they need. Unit tests and QA check that the software works as specified. UAT checks that the specification was right. A round ends with a sign-off against criteria agreed at the start, and anything that doesn&rsquo;t match what users expected, whether or not it&rsquo;s technically a bug, gets logged, triaged and either fixed or deliberately deferred.</p>
<p>The most embarrassing bugs I&rsquo;ve shipped all had one thing in common: the test suite was green. The code did exactly what the spec said. The spec just didn&rsquo;t match what people actually needed. UAT exists for that gap.</p>

<h4 class="relative group">Why I can&rsquo;t test my own features
    <div id="why-i-cant-test-my-own-features" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-i-cant-test-my-own-features" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>By the time a feature is ready, I&rsquo;ve walked its happy path a few hundred times. I know which button to press because I built the button. That familiarity makes me the worst possible test user, and it makes QA only half a solution, because QA still tests against the spec. UAT is the one stage where the question changes from &ldquo;does it work as designed?&rdquo; to &ldquo;was it designed right?&rdquo;</p>

<h4 class="relative group">UAT, QA and beta testing aren&rsquo;t the same thing
    <div id="uat-qa-and-beta-testing-arent-the-same-thing" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#uat-qa-and-beta-testing-arent-the-same-thing" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>People use these interchangeably, and it causes real confusion about who&rsquo;s meant to be doing what.</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left"></th>
					<th style="text-align: left">QA</th>
					<th style="text-align: left">UAT</th>
					<th style="text-align: left">Beta</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">Question</td>
					<td style="text-align: left">Does it work as specified?</td>
					<td style="text-align: left">Does it work for the people who&rsquo;ll use it?</td>
					<td style="text-align: left">How does it hold up in the wild?</td>
			</tr>
			<tr>
					<td style="text-align: left">Who</td>
					<td style="text-align: left">Testers, developers</td>
					<td style="text-align: left">Real or representative users, the business owner</td>
					<td style="text-align: left">A slice of real customers</td>
			</tr>
			<tr>
					<td style="text-align: left">Where</td>
					<td style="text-align: left">Test environment</td>
					<td style="text-align: left">Staging, with realistic data</td>
					<td style="text-align: left">Production</td>
			</tr>
			<tr>
					<td style="text-align: left">Finds</td>
					<td style="text-align: left">Defects against the spec</td>
					<td style="text-align: left">Gaps between the spec and real work</td>
					<td style="text-align: left">Scale, device and data surprises</td>
			</tr>
			<tr>
					<td style="text-align: left">Ends with</td>
					<td style="text-align: left">A pass on the test cases</td>
					<td style="text-align: left">A sign-off</td>
					<td style="text-align: left">A decision to roll out wider</td>
			</tr>
	</tbody>
</table>
<p>UAT sits between the other two. If QA is still finding crashes, it&rsquo;s too early for UAT. Users will spend the whole round tripping over bugs and never get to the question you actually wanted answered.</p>

<h4 class="relative group">Before the round starts
    <div id="before-the-round-starts" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#before-the-round-starts" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>Plan first: scope, timeline, who&rsquo;s taking part, and what &ldquo;pass&rdquo; means. Vague success criteria are how UAT rounds drag on for weeks.</p>
<p>I also set entry criteria, which is a grand name for a short checklist. QA has passed with no open critical bugs. The staging environment has data that looks like the real thing, not &ldquo;test test 123&rdquo; accounts. The people taking part have time blocked out for it, not &ldquo;whenever you get a chance&rdquo;. That last one matters most. UAT squeezed in around someone&rsquo;s real job gets about ten minutes of real attention.</p>
<p>Then pick people who resemble your real users. Colleagues who had nothing to do with the build work well; a small group of friendly external stakeholders who understand what the product is for works even better. Five to eight people is plenty for most features. Past that you mostly get the same feedback again.</p>

<h4 class="relative group">Writing scenarios people can actually follow
    <div id="writing-scenarios-people-can-actually-follow" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#writing-scenarios-people-can-actually-follow" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>Write the scenarios around daily routines rather than edge cases. QA has already hammered the edges. A good UAT scenario reads like a normal Tuesday, not a stress test.</p>
<p>Each scenario has a goal and a starting point, and deliberately leaves out the steps. If you write &ldquo;click New Invoice, then click Add Client&rdquo;, you&rsquo;re testing whether people can follow instructions, not whether the product makes sense. For an invoicing feature, a scenario might look like this:</p>
<blockquote><p><strong>Scenario 4: Bill a new client for part of a job</strong></p>
<p>You&rsquo;ve just finished the first half of a fit-out for a new client, Harbour Café. Invoice them for 50% of the agreed $12,000, due in 14 days, and send it to their accounts email.</p>
<p><strong>Expected:</strong> the client gets an invoice for $6,000 with the right due date, and it shows as outstanding on your dashboard.</p>
</blockquote><p>Ten to fifteen scenarios like that usually cover a feature. I sit in on the first couple of sessions, say as little as possible, and watch where people hesitate. A pause before a button tells you more than anything written in the feedback form.</p>

<h4 class="relative group">Logging UAT feedback
    <div id="logging-uat-feedback" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#logging-uat-feedback" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>During the round, anything that doesn&rsquo;t match what users expected gets logged, including things that are technically &ldquo;working as intended&rdquo;. If someone expected one thing and got another, that&rsquo;s information whatever the spec says.</p>
<p>The log doesn&rsquo;t need a special tool. A shared sheet or a dedicated board in whatever issue tracker you already use is enough, as long as every entry has the same few fields:</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Field</th>
					<th style="text-align: left">Example</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">Scenario</td>
					<td style="text-align: left">4: Bill a new client for part of a job</td>
			</tr>
			<tr>
					<td style="text-align: left">What I expected</td>
					<td style="text-align: left">To enter 50% and have it work out the amount</td>
			</tr>
			<tr>
					<td style="text-align: left">What happened</td>
					<td style="text-align: left">Had to calculate $6,000 by hand; no percentage option</td>
			</tr>
			<tr>
					<td style="text-align: left">Severity (as the tester sees it)</td>
					<td style="text-align: left">Annoying, not blocking</td>
			</tr>
			<tr>
					<td style="text-align: left">Screenshot or recording</td>
					<td style="text-align: left">Attached</td>
			</tr>
	</tbody>
</table>
<p>&ldquo;What I expected&rdquo; is the field that does the work. Without it you get &ldquo;the invoice screen is confusing&rdquo;, which nobody can act on.</p>

<h4 class="relative group">Triaging the feedback
    <div id="triaging-the-feedback" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#triaging-the-feedback" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>At the end of each day, or each round for a small one, I go through the log with the product owner and sort every item into one of four piles.</p>
<p>A bug is something broken, like a wrong total or an error page. It gets fixed before sign-off if it&rsquo;s serious, otherwise scheduled.</p>
<p>A change request means it works as specified but the specification was wrong, as with the missing percentage option above. This is the feedback UAT exists to find, and the hardest to handle, because fixing it means more scope. The product owner decides: fix now, or accept and schedule it.</p>
<p>A copy or training issue means the feature is fine but people didn&rsquo;t understand it. Often a label, a hint or one line in the help docs fixes it. Cheap, and worth doing.</p>
<p>Won&rsquo;t fix covers out-of-scope ideas and one person&rsquo;s preference against everyone else&rsquo;s. Write down why, and tell the person who raised it. Testers who never hear back stop giving feedback in the next round.</p>
<p>The thing I try hardest to avoid is treating every item as a bug to be fixed before launch. That&rsquo;s how a two-week round turns into two months. The goal of UAT feedback isn&rsquo;t zero items. It&rsquo;s that every item has a decision attached.</p>

<h4 class="relative group">Sign-off
    <div id="sign-off" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sign-off" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>Afterwards, fix what needs fixing, and if the changes were substantial, run another short round rather than assuming they landed well. Then get a real sign-off against the criteria you agreed at the start. That means a named person saying &ldquo;yes, ship it&rdquo;, with any deferred items listed alongside, not a thumbs-up emoji in a group chat.</p>

<h4 class="relative group">Mistakes I&rsquo;ve made running UAT
    <div id="mistakes-ive-made-running-uat" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#mistakes-ive-made-running-uat" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>Running it too late. If UAT starts two days before a fixed launch date, every change request becomes an argument about whether to delay, and the answer is always no. Leave room to act on what you find.</p>
<p>Testing with the wrong people. Internal staff who know the product too well behave like the developers did. They know where everything is.</p>
<p>Treating silence as approval. If a tester logs nothing, they probably didn&rsquo;t really test. Check in before counting them as a pass.</p>
<p>And letting UAT become a checkbox at the end of a sprint. It&rsquo;s better treated as the last gate: the final moment before launch where someone who isn&rsquo;t you tries to use the thing.</p>

<h4 class="relative group">What it buys you
    <div id="what-it-buys-you" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-it-buys-you" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>Mostly, it catches problems while they&rsquo;re still cheap: before launch, instead of a patch and an apology after. There are quieter wins too. Training and support get easier, because the flows match how people actually work. And stakeholders who took part in the testing sign off faster, because by that point it&rsquo;s partly their product. The releases I&rsquo;ve seen get a proper UAT round tend to be the calm ones.</p>

<h4 class="relative group">In short
    <div id="in-short" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#in-short" aria-label="Anchor">#</a>
    </span>
    
</h4>
<p>UAT is where real users check the software does what they need before it ships. Start it once QA is clean. Invite five to eight people who look like your users, write scenarios as everyday goals rather than steps, and log every gap between what they expected and what happened. Sort each piece of feedback into bug, change request, copy issue or won&rsquo;t fix, make a decision on every one, and finish with a named sign-off.</p>
]]></content:encoded>
      <media:content url="https://jared.lynskey.co.nz/en/posts/2023/2023-08-27-user-acceptance-testing/featured.jpeg" medium="image" type="image/jpeg" />
    </item>
  </channel>
</rss>
