<?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 · 仁才德</title>
    <link>https://jared.lynskey.co.nz/zh-cn/tags/user-acceptance-testing/</link>
    <description>关于软件工程与研发团队领导力的短文——绩效评估、招聘与团队扩张、CI/CD、DevOps 监控、智能体 AI。写于首尔。</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <copyright>© 2026 仁才德</copyright>
    <lastBuildDate>Fri, 23 Oct 2026 00:00:00 +1300</lastBuildDate>
    <atom:link href="https://jared.lynskey.co.nz/zh-cn/tags/user-acceptance-testing/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>用户验收测试（UAT）怎么做：我的流程和反馈处理方法</title>
      <link>https://jared.lynskey.co.nz/zh-cn/posts/2023/2023-08-27-user-acceptance-testing/</link>
      <guid isPermaLink="true">https://jared.lynskey.co.nz/zh-cn/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>用户验收测试（UAT）是上线前的最后一道检查，让真实用户拿软件做日常工作。我是怎么跑一轮 UAT 的：请谁来测、场景怎么写、UAT 反馈怎么记录和分类，以及什么时候签字验收。</description>
      <content:encoded><![CDATA[<p>用户验收测试（UAT）是发布前的最后一个测试阶段：让真正要用这个软件的人拿它做日常工作，确认它能满足需求。单元测试和 QA 检查的是软件有没有按规格运行，UAT 检查的是规格本身对不对。一轮 UAT 以签字验收收尾，依据是一开始就商定好的标准。凡是和用户预期不符的地方，不管技术上算不算 bug，都要记下来、分好类，然后要么修掉，要么有意识地往后放。</p>
<p>我发布过的最丢人的几个 bug 有一个共同点：测试全是绿的。代码完全按规格在跑，只是规格本身和大家真正需要的东西对不上。UAT 就是为这道缝存在的。</p>

<h4 class="relative group">为什么我没法测自己做的功能
    <div id="为什么我没法测自己做的功能" 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="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%88%91%e6%b2%a1%e6%b3%95%e6%b5%8b%e8%87%aa%e5%b7%b1%e5%81%9a%e7%9a%84%e5%8a%9f%e8%83%bd" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>功能做完的时候，主流程我已经走过几百遍了。该点哪个按钮我一清二楚，毕竟按钮是我做的。这种熟悉感让我成了最差劲的测试用户，也让 QA 只能解决一半问题，因为 QA 仍然是照着规格测。只有到了 UAT，问题才会从“是否按设计运行”变成“设计本身对不对”。</p>

<h4 class="relative group">UAT、QA 和 Beta 测试不是一回事
    <div id="uatqa-和-beta-测试不是一回事" 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="#uatqa-%e5%92%8c-beta-%e6%b5%8b%e8%af%95%e4%b8%8d%e6%98%af%e4%b8%80%e5%9b%9e%e4%ba%8b" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>很多人把这几个词混着用，结果真的会搞不清谁该干什么。</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">要回答的问题</td>
					<td style="text-align: left">是否按规格运行？</td>
					<td style="text-align: left">对真正要用的人来说好不好用？</td>
					<td style="text-align: left">放到真实环境里扛不扛得住？</td>
			</tr>
			<tr>
					<td style="text-align: left">谁来测</td>
					<td style="text-align: left">测试人员、开发者</td>
					<td style="text-align: left">真实用户或有代表性的用户、业务负责人</td>
					<td style="text-align: left">一部分真实客户</td>
			</tr>
			<tr>
					<td style="text-align: left">在哪测</td>
					<td style="text-align: left">测试环境</td>
					<td style="text-align: left">预发布环境，用接近真实的数据</td>
					<td style="text-align: left">生产环境</td>
			</tr>
			<tr>
					<td style="text-align: left">能发现什么</td>
					<td style="text-align: left">不符合规格的缺陷</td>
					<td style="text-align: left">规格和实际工作之间的差距</td>
					<td style="text-align: left">规模、设备和数据上的意外</td>
			</tr>
			<tr>
					<td style="text-align: left">以什么收尾</td>
					<td style="text-align: left">测试用例全部通过</td>
					<td style="text-align: left">签字验收</td>
					<td style="text-align: left">决定是否扩大发布范围</td>
			</tr>
	</tbody>
</table>
<p>UAT 夹在另外两者中间。如果 QA 还在不断发现崩溃，现在做 UAT 就太早了。用户整轮都会被 bug 绊倒，根本走不到你真正想问的那个问题。</p>

<h4 class="relative group">开始之前
    <div id="开始之前" 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="#%e5%bc%80%e5%a7%8b%e4%b9%8b%e5%89%8d" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>先做计划：范围、时间表、参与者，以及“通过”是什么意思。成功标准一含糊，UAT 就能拖上好几周。</p>
<p>我还会定准入标准，名字听着挺唬人，其实就是一张短清单。QA 已经通过，没有未解决的严重 bug。预发布环境里的数据看起来像真的，而不是一堆“test test 123”账号。参与的人专门空出了时间，而不是“有空的时候看看”。最后这条最要紧。挤在本职工作缝隙里的 UAT，大概只能分到十分钟真正的注意力。</p>
<p>然后挑和真实用户相像的人。没参与开发的同事就不错；如果能找到几位理解产品是干什么用的、态度友好的外部干系人，更好。大多数功能，五到八个人就够了。再多，收到的基本都是重复的反馈。</p>

<h4 class="relative group">写出别人真能照着走的场景
    <div id="写出别人真能照着走的场景" 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="#%e5%86%99%e5%87%ba%e5%88%ab%e4%ba%ba%e7%9c%9f%e8%83%bd%e7%85%a7%e7%9d%80%e8%b5%b0%e7%9a%84%e5%9c%ba%e6%99%af" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>场景要围绕日常操作来写，别写边界情况，边界 QA 早就轰炸过了。一个好的 UAT 场景读起来应该像一个平平常常的星期二，而不是压力测试。</p>
<p>每个场景有一个目标和一个起点，并且故意不写步骤。如果你写“点击‘新建发票’，再点击‘添加客户’”，测的就是大家会不会照着指令操作，而不是产品本身讲不讲得通。拿一个开发票的功能来说，场景大概是这样：</p>
<blockquote><p><strong>场景 4：给新客户开一张部分款项的发票</strong></p>
<p>你刚给一位新客户“港湾咖啡馆”做完店面装修的前一半。按商定总价 $12,000 的 50% 给他们开发票，14 天内付款，发到他们的财务邮箱。</p>
<p><strong>预期结果</strong>：客户收到一张 $6,000 的发票，到期日正确，并且在你的仪表盘上显示为未付款。</p>
</blockquote><p>一个功能，像这样的场景通常写十到十五个就够了。头一两场我会在旁边坐着，尽量少说话，看大家在哪里犹豫。有人在某个按钮前停顿一下，比反馈表上写的任何东西都更能说明问题。</p>

<h4 class="relative group">记录 UAT 反馈
    <div id="记录-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="#%e8%ae%b0%e5%bd%95-uat-%e5%8f%8d%e9%a6%88" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>测试期间，凡是和用户预期不符的都要记下来，包括那些技术上“符合设计”的。有人预期的是一样东西，拿到的却是另一样，不管规格怎么写，这本身就是信息。</p>
<p>记录不需要什么专门的工具。一张共享表格，或者在你们现有的问题跟踪工具里单开一个看板就够了，只要每一条都有同样几个字段：</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">字段</th>
					<th style="text-align: left">示例</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">场景</td>
					<td style="text-align: left">4：给新客户开一张部分款项的发票</td>
			</tr>
			<tr>
					<td style="text-align: left">我预期的是</td>
					<td style="text-align: left">输入 50%，系统自动算出金额</td>
			</tr>
			<tr>
					<td style="text-align: left">实际发生的是</td>
					<td style="text-align: left">只能自己手算出 $6,000，没有按百分比开票的选项</td>
			</tr>
			<tr>
					<td style="text-align: left">严重程度（测试者自己的判断）</td>
					<td style="text-align: left">有点烦人，但不影响继续</td>
			</tr>
			<tr>
					<td style="text-align: left">截图或录屏</td>
					<td style="text-align: left">已附上</td>
			</tr>
	</tbody>
</table>
<p>真正起作用的是“我预期的是”这一栏。没有它，你收到的就是“发票页面看不懂”，谁也没法据此动手。</p>

<h4 class="relative group">给反馈分类
    <div id="给反馈分类" 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="#%e7%bb%99%e5%8f%8d%e9%a6%88%e5%88%86%e7%b1%bb" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>每天结束时（规模小的话就每轮结束时），我会和产品负责人一起过一遍记录，把每一条归进下面四类之一。</p>
<p>Bug，就是东西坏了，比如总额算错、跳出报错页面。严重的在签字验收前修掉，不严重的排进计划。</p>
<p>变更请求，指的是功能按规格做了，但规格本身错了，比如上面那个缺少的百分比选项。UAT 存在的意义就是找出这类反馈，而它也最难处理，因为修它就意味着范围变大。由产品负责人拍板：现在修，还是先接受、排到以后。</p>
<p>文案或培训问题，指的是功能本身没毛病，只是大家没看懂。往往改个标签、加句提示，或者在帮助文档里补一行就解决了。成本低，值得做。</p>
<p>不修，包括超出范围的想法，以及某一个人的偏好和其他所有人都相反的情况。写下原因，并告诉提出的人。从来收不到回音的测试者，下一轮就不会再给反馈了。</p>
<p>我最想避免的，就是把每一条都当成上线前必须修掉的 bug。两周的一轮 UAT 就是这么拖成两个月的。UAT 反馈的目标不是清零，而是每一条都有一个明确的决定。</p>

<h4 class="relative group">签字验收
    <div id="签字验收" 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="#%e7%ad%be%e5%ad%97%e9%aa%8c%e6%94%b6" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>测完之后，该修的修掉；如果改动比较大，就再跑一轮短的，别想当然地以为改好了。然后按开始时商定的标准，拿到真正的签字验收。也就是由一个有名有姓的人说“可以，发吧”，同时把延后处理的事项一并列出来，而不是群聊里一个点赞表情。</p>

<h4 class="relative group">我跑 UAT 时犯过的错
    <div id="我跑-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="#%e6%88%91%e8%b7%91-uat-%e6%97%b6%e7%8a%af%e8%bf%87%e7%9a%84%e9%94%99" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>开始得太晚。如果 UAT 在一个定死的上线日期前两天才开始，每个变更请求都会变成一场要不要延期的争论，而答案永远是不延。要给自己留出空间，能根据测出来的东西采取行动。</p>
<p>找错了人。太熟悉产品的内部员工，表现和开发者差不多。他们知道每样东西在哪。</p>
<p>把沉默当成认可。如果一位测试者什么都没记，多半是没认真测。在把他算作“通过”之前，先去问一问。</p>
<p>还有，让 UAT 沦为 Sprint 末尾的一个勾选框。它更该被当成最后一道关：发布前最后一次，由一个不是你的人来试着用这个东西。</p>

<h4 class="relative group">它能换来什么
    <div id="它能换来什么" 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="#%e5%ae%83%e8%83%bd%e6%8d%a2%e6%9d%a5%e4%bb%80%e4%b9%88" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>最大的收益是趁问题还便宜的时候抓住它：在发布前，而不是发布后打补丁加道歉。还有些不那么显眼的好处。流程贴合大家实际的工作方式，培训和支持都更省事。参与过测试的干系人签字也更快，因为到那时，产品已经有一部分算是他们的了。我见过的认真跑过一轮 UAT 的版本，上线往往都很平静。</p>

<h4 class="relative group">简单来说
    <div id="简单来说" 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="#%e7%ae%80%e5%8d%95%e6%9d%a5%e8%af%b4" aria-label="锚点">#</a>
    </span>
    
</h4>
<p>UAT 就是在软件上线前，让真实用户确认它能满足需求。等 QA 干净了再开始。请五到八个像你的用户的人，把场景写成日常目标而不是操作步骤，把他们预期的和实际发生的之间的每一处差距都记下来。把每条反馈归为 bug、变更请求、文案问题或不修，每一条都做出决定，最后由一个具体的人签字验收。</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>
