<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>测试用例生成 on XLabs</title><link>https://www.xlabs.club/tags/%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E7%94%9F%E6%88%90/</link><description>Recent content in 测试用例生成 on XLabs</description><generator>Hugo</generator><language>zh-CN</language><copyright>Copyright (c) 2020-2025 XLabs Club</copyright><lastBuildDate>Wed, 23 Sep 2026 00:10:25 +0800</lastBuildDate><atom:link href="https://www.xlabs.club/tags/%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E7%94%9F%E6%88%90/index.xml" rel="self" type="application/rss+xml"/><item><title>AI 生成的 E2E 测试能抓到真 bug 吗：5 个模型 41 个用例的变异实测</title><link>https://www.xlabs.club/blog/ai-generated-e2e-tests-mutation-testing/</link><pubDate>Mon, 21 Sep 2026 00:00:00 +0800</pubDate><guid>https://www.xlabs.club/blog/ai-generated-e2e-tests-mutation-testing/</guid><description>&lt;p&gt;让模型写 E2E 用例，跑出来一片绿。问题在于「绿」本身不携带信息。我在一个真实的单页应用上注入了 8 个真缺陷，让 5 个模型各自生成 Playwright 用例，然后用变异检测的方式判断哪些用例真的在防回归。&lt;/p&gt;
&lt;p&gt;结论先放这里：40 个在正确页面上能通过的用例里，&lt;strong&gt;5 个（12%）在整个实验里从未失败过一次&lt;/strong&gt;；8 个缺陷里有 1 个只有 1 家抓到，其余 4 家全漏；用例数最多的模型花了 1.5 倍的输出 token，只多抓到 1 个缺陷。&lt;/p&gt;
&lt;h2 id="环境与实验设计"&gt;环境与实验设计&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;网关：内网 OpenAI 兼容网关 &lt;code&gt;https://aihub.firstshare.cn/v1&lt;/code&gt;，2026-09-21 实测，&lt;code&gt;temperature=0&lt;/code&gt;，每个模型只生成一次。&lt;/li&gt;
&lt;li&gt;运行：Playwright 1.63.0 + 系统自带的 Chromium 152。不下载 Playwright 自带浏览器，直接 &lt;code&gt;launchOptions.executablePath&lt;/code&gt; 指向系统 chromium：&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// playwright.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;testDir&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;./specs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headless&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;launchOptions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;executablePath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/usr/bin/chromium&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;被测页面：单文件 HTML，内联 JS，无框架，5.6 KB。包含登录（空字段时按钮禁用，&lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;secret&lt;/code&gt; 通过）、成员表（12 条数据、每页 5 条、「共 N 条」计数、点姓名表头切换排序、按姓名搜索且大小写不敏感）、添加成员（新增后清空输入框）。&lt;/li&gt;
&lt;li&gt;页面用 &lt;code&gt;file://&lt;/code&gt; 打开，整个实验没有任何常驻进程和监听端口。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;8 个变异体，每个只改一行&lt;/strong&gt;，都是外部可观察行为的改变：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;ID&lt;/th&gt;
					&lt;th&gt;改动&lt;/th&gt;
					&lt;th&gt;可观察差异&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;m1&lt;/td&gt;
					&lt;td&gt;搜索去掉 &lt;code&gt;toLowerCase()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;搜 &lt;code&gt;ALICE&lt;/code&gt; 由 1 条变 0 条&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m2&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PAGE_SIZE = 5&lt;/code&gt; → &lt;code&gt;10&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;每页行数与「第 1 / 3 页」变化&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m3&lt;/td&gt;
					&lt;td&gt;错误提示文案改掉&lt;/td&gt;
					&lt;td&gt;断言固定文案的用例失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m4&lt;/td&gt;
					&lt;td&gt;添加成员后不清空输入框&lt;/td&gt;
					&lt;td&gt;输入框 value 变化&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m5&lt;/td&gt;
					&lt;td&gt;排序开关失效，永远升序&lt;/td&gt;
					&lt;td&gt;首次点击表头不再变降序&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m6&lt;/td&gt;
					&lt;td&gt;登录按钮不再按空字段禁用&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;toBeDisabled()&lt;/code&gt; 失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m7&lt;/td&gt;
					&lt;td&gt;末页「下一页」不再禁用&lt;/td&gt;
					&lt;td&gt;边界态变化&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;m8&lt;/td&gt;
					&lt;td&gt;「共 N 条」改用全量数据&lt;/td&gt;
					&lt;td&gt;搜索后计数不更新&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;变异体和基线页面由脚本从同一份 &lt;code&gt;app.html&lt;/code&gt; 做单点字符串替换生成，每个锚点在基线中唯一，改动内容可复核。&lt;/p&gt;</description></item></channel></rss>