官网表单与下载异常怎么排查?五个环节定位故障
官网表单与下载异常,可以按页面、下载、提交、入库和通知五个环节定位。先找出最早不符合预期的一步,再核对相应证据;页面返回 HTTP 200,只能说明本次页面请求得到响应,不能证明文件正确或询盘已保存。
排查记录应把实际结果与业务预期对应起来。下载和询盘可以分别检查;询盘提交失败后,没有继续验证的入库与通知步骤,应标为未验证。
本文使用一个本地演示站说明排查方法:A100 产品提供英文、德语页面,下载 CSV 规格文件,提交测试询盘。全部故障由演示站主动模拟,没有连接客户网站、真实邮件或 CRM。测试在本机 Chromium 中执行,不包含海外节点实测。
可下载完整演示代码与运行说明,并查看8 个场景的原始结果。下文代码是排查片段,运行上下文和完整流程以配套示例为准。
页面、下载、提交、入库和通知分别查什么
页面响应检查回答"网址是否能访问";交互检查回答"浏览器能否完成指定动作";业务结果检查则回答"动作有没有产生预期记录或通知"。
这些结果需要各自的证据。一次 page.goto() 得到正常响应后,可以继续确认产品标题和页面语言;下载要验证实际拿到的文件;询盘则需要能够关联本次请求的标识,向后核对保存与通知。
本文的检查程序把结果拆成 page、download、submit、receipt、notification 五项。当前置环节失败,无法验证后续结果时,后续标记为 not-run,不把"没有继续检查"写成正常或失败。
| 故障现象 | 优先核对的证据 | 本地演示对应结果 |
|---|---|---|
| 文件打不开 | 页面实际链接、最终响应和状态 | missing-file:下载返回 404 |
| 能下载但内容不对 | 文件型号、语言、版本 | wrong-file:200 响应中是错误资料 |
| 点击后提交失败 | 校验反馈、目标请求及业务返回 | api-error:提交接口返回 503 |
| 前台成功但没有记录 | 本次测试编号对应的保存结果 | false-success:未查到对应记录 |
| 有记录但未收到提醒 | 通知任务与受控接收结果 | notification-failed:仅模拟通知状态失败 |

下载有响应,先看返回的究竟是什么
下载排查可以从页面上的实际链接开始,逐步确认目标地址、最终响应和文件内容。不要只拿配置表里的文件地址测试,否则可能漏掉页面仍引用旧地址的问题。
以下片段来自配套检查程序,其中 link 是按当前语言按钮名称定位到的链接,context 是对应浏览器上下文,lang 对应当前场景的 item.lang:
js
const href = await link.getAttribute('href');
const response = await context.request.get(href);
assert.equal(response.status(), 200, 'download HTTP status');
assert.match(response.headers()['content-type'], /^text\/csv/);
assert.equal(
await response.text(),
specification(lang),
'file model / language / revision'
);
本例文件内容很短,因此直接比较预期文本。注入的 wrong-file 场景仍返回 200,也保留 CSV 类型,但内容变成其他型号、其他语言和旧版本。这种错误需要检查内容才能发现。
实际网站如果提供 PDF,检查内容类型和文件头可以作为基础步骤,却不足以证明文件完整、型号正确。应根据可用条件继续解析或核对文件内容;对于经过确认、版本固定的文件,也可以比较校验值。校验依据本身要随批准的资料版本更新。
文件请求正常之后,还应确认客户点击按钮能触发预期动作。配套程序在点击前等待下载事件,保存文件后再次核对内容;这是为了同时覆盖链接检查和浏览器实际下载。Playwright 官方文档说明了下载事件的等待和文件保存方式。下载文档
如果网站采用浏览器内预览 PDF,而非触发附件下载,应当验证预览页面或相应请求,不能机械等待一个本来不会发生的下载事件。
表单无法提交,先确认请求有没有发出去
字段填写不完整、前端校验未通过、按钮不可操作,都可能让请求停留在浏览器内。先观察实际操作和校验反馈,再判断接口是否存在问题。
本地示例按语言定位字段,监听目标接口的 POST 响应,再点击提交。如果请求发出后返回 503,程序把失败记录在 submit,后续步骤标为未执行。下面的 sendText 对应完整示例中的 t.send。
js
const waiting = page.waitForResponse(response =>
new URL(response.url()).pathname === '/api/inquiry' &&
response.request().method() === 'POST'
);
await page.getByRole('button', { name: sendText, exact: true }).click();
const response = await waiting;
assert.equal(response.status(), 200, 'inquiry HTTP status');
const body = await response.json();
assert.equal(body.ok, true);
这里的 200 与 ok: true 来自演示接口约定。真实站点应使用自己的接口契约;201、202 等响应在某些业务设计中也可能合理。状态码、业务返回内容和页面提示需要一起解释,不能只替换成一个通用的"非报错即成功"判断。
如果响应等待超时,要结合网络记录判断是没有发出请求、请求未完成,还是监听条件与实际接口不匹配。仅凭"超时"两个字,还不能定位是哪一层出了问题。
前台成功却收不到询盘,沿唯一标识向后查
程序为每次测试创建一个唯一编号,用它关联前台提交和后台记录。提交检查通过后,再查询演示站的受控记录端点,确认返回的编号、语言与保存状态符合预期。
false-success 场景故意返回前台成功响应,却不保存记录。此时页面看起来正常,submit 通过,receipt 失败。它说明"前台提示"和"已保存"必须分别核对。

查询端点只存在于本机演示站。生产环境的核对方式需要由维护团队提供,可以是受控接口、日志或其他授权查询,不能直接把演示中的无鉴权接口暴露出去。
对于异步保存,可以在明确的时间范围内轮询本次记录,并保留最终观察值。演示用了较短等待时间,适合本地验证;真实阈值应按系统处理方式和正常耗时确定,不能照搬。
入库和通知要分开判断
如果记录存在而通知未到,应继续核对通知任务是否创建、发送服务返回什么,以及预定接收位置是否出现对应内容。
本例的 notification-failed 场景只模拟一个失败状态,没有发送邮件。它用来验证检查程序能把"保存成功、通知失败"记录为不同环节,不能作为真实邮件送达验证。
线上需要核对邮件时,应使用受控测试邮箱,并根据同一测试编号关联消息。排查记录中只保留必要信息,对邮箱地址、提交内容及访问凭据进行适当处理。Playwright trace 可以帮助回查动作、页面和网络信息,但这类证据也需要按其中实际包含的内容控制访问。Trace viewer 文档
多语言与海外访问问题,要保留发生条件
语言版本之间可能有不同的字段名称、按钮文字、附件和成功提示。程序应逐个核对预期,不能把英文检查结果复制成德语结果。
本次演示实际验证了英文、德语桌面场景,以及一个英文 390px 视口场景。它们共用本机网络,桌面和移动视口也都使用 Chromium;后者只是窄屏布局检查,不代表真实手机或移动网络测试。
真实异常记录还应包含检查位置、运行时间、浏览器与语言 URL。只有保留这些条件,才能继续比较"某个位置失败、其他位置正常",或"某个语言版本失败、其他版本正常"的差异。
修复后,复测应回到原来的客户入口。下载问题从原产品页重新点击,询盘问题重新验证本次记录及需要覆盖的接收结果。如果修复的是共用组件,再检查受它影响的其他语言版本。排查的终点,是原来失败的业务步骤在已说明的条件下恢复,而不只是某一个接口重新返回了 200。