关于 qa-testing-nunit
用于设计、实现和排查 NUnit API、组件及集成测试套件的技能,重点涵盖夹具边界、生命周期与并行安全、依赖配置、可靠断言和基于证据的验证。
主要功能
- 01API、组件和集成测试结构
- 02夹具组合与生命周期指导
- 03并行安全的测试配置
- 04WireMock 与 Testcontainers 模式
- 05异步可靠性与诊断
- 06运行器和环境验证
适用场景
- 01构建按控制器划分的 API 测试套件
- 02隔离并行测试中的共享夹具状态
- 03使用容器测试数据库迁移
- 04调查不稳定测试和基础设施故障
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ vasilyu1983/ ai-agents-public --skill qa-testing-nunit安装后在 Claude Code 中输入/qa-testing-nunit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
learnings.consolidated.mdlearnings.mdagents/openai.yamlassets/nunit-api-fixture-template.csnunit-api-request-builder-template.csnunit-api-test-case-sources-template.csnunit-api-tests-template.csnunit-database-launcher-template.csnunit-handler-fixture-template.csnunit-handler-tests-template.csnunit-wiremock-template.csdata/sources.jsonreferences/api-testing-nunit.mdassertions-and-diagnostics.mdci-parallelism-sharding.mdfixture-pattern.mdinfrastructure-troubleshooting.mdnunit-structure.mdreliability-and-dependencies.mdtest-platform-modes.mdtestcontainers-setup.mdtesting-templates.mdwiremock-setup.md详细介绍
QA 测试(NUnit)
快速参考
- 首先判断测试范围:API、组件或集成。
- 执行前明确运行时约束:Docker 是否可用、目标框架,以及明确排除的测试套件。
- 如果任务提到
dotnet test、Microsoft.Testing.Platform、global.json、适配器或覆盖率/日志开关,请先确认仓库当前的运行器模式,并使用data/sources.json中的最新一手资料。 - 此技能适用于测试套件架构和夹具行为,不适用于通用服务实现或 CI 图重构。
- 当设置并非简单操作时,将设置与测试方法分开:夹具类负责依赖项装配和
Given...辅助方法;测试类负责 NUnit 生命周期和断言。 - 按控制器或端点系列对完整流程的 API 测试分组。避免使用一个全局共享设置夹具;每个系列的夹具都负责自己的数据库容器和迁移、HTTP 存根、
WebApplicationFactory和客户端。 - 确保 API 夹具共享的运行时可安全并行:夹具级并行没问题,但当 WireMock 存根、客户端或可变运行时状态是共享的,不要启用子测试并行。
- 为什么
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]要与[Parallelizable]搭配使用:NUnit 默认的SingleInstance生命周期会让所有测试方法共享同一个夹具对象,因此,一旦其中两个测试并发运行,实例字段就会产生竞态条件。InstancePerTestCase会为每个测试创建独立实例,从而隔离实例字段状态;但它不会隔离static字段或外部共享资源(容器、WireMock 服务),这就是为什么在此生命周期下[OneTimeSetUp]/[OneTimeTearDown]必须保持为static,并且仍需在[SetUp]中按自己的方式重置共享运行时。 - 在
[SetUp]中重置可变状态;在[OneTimeTearDown]中释放所有自有基础设施。 - 引导数据库时,启动数据库容器,将每组迁移作为一次性容器运行,并确保其退出代码为
0,然后检查必需的表(起点参考:assets/nunit-database-launcher-template.cs)。如果仓库已有启动器或迁移辅助工具,请复用,而不是另起一套。 - 使用仓库的迁移镜像已有文档说明的命令运行迁移;通过容器等待策略判断就绪情况,不要在测试中使用自定义就绪检查参数。
- 明确迁移器的顺序(先依赖项迁移器,最后领域迁移器),并支持夹具级可选迁移器开关,以便某些套件无需使用所有数据库。
- 添加明确的迁移器验证测试,断言启动器已启动、迁移器已完成且顺序正确,并验证必需的表。
- 对于健康检查端点,使用
[Test] + [TestCase] + [CancelAfter(...)],方法签名为(string url, CancellationToken cancellationToken);将[Test]与[TestCase]放在一起,避免 NUnit 分析器问题。 - 优先采用符合分析器要求的 NUnit 用法,并提供更充分的诊断信息:对相关断言使用
Assert.Multiple或Assert.EnterMultipleScope;失败需要更多上下文时,使用TestContext.Progress或夹具诊断信息。 - 如果用户排除了依赖基础设施的测试套件(例如需要 Docker 的组件测试),先运行可执行的类别,并准确报告仍有哪些内容未验证。
- 如果任务转向服务设计或后端重构,请切换到
$software-csharp-backend。 - 如果任务转向
nuke/Build.cs、测试运行器选择、类别目标配置或 CI 工件发布,请切换到$ops-nuke-cicd。
当前事实协议
- 将运行器模式、软件包版本、分析器行为、适配器要求以及 CLI/覆盖率开关视为易变的当前状态事实。
- 在建议更改软件包或命令行标志前,根据
data/sources.json核实对版本敏感的指导。 - 将整个仓库的
dotnet test、MTP、覆盖率和 CI 接线工作保留在$ops-nuke-cicd;本技能专注于测试夹具设计和测试套件结构。 - 软件包、适配器、运行器模式和覆盖率事实位于
references/test-platform-modes.md;断言库许可信息位于references/assertions-and-diagnostics.md。固定版本前,请在 NuGet 上查询当前版本。
工作流
- 定义边界、依赖项、预期断言深度和环境约束。
加载
references/nunit-structure.md。如果请求涉及dotnet test、运行器模式、适配器或 CLI 标志,也加载references/test-platform-modes.md。 - 选择测试夹具的组合方式和生命周期。
加载
references/fixture-pattern.md和references/testing-templates.md。 - 为目标层实现场景测试。
加载
references/api-testing-nunit.md;对于组件测试,还要加载references/reliability-and-dependencies.md中的边界部分。 - 选择使用测试替身还是实际依赖项的策略,以及容器拓扑。
加载
references/reliability-and-dependencies.md,然后加载references/wiremock-setup.md或references/testcontainers-setup.md。 - 添加可靠的异步和最终一致性断言,并增强测试以防止不稳定。
加载
references/reliability-and-dependencies.md和references/assertions-and-diagnostics.md。 - 保持模板一致。
将 API 资源文件集作为一个整体复制(参见
references/testing-templates.md中的模板映射)。 - 调整 CI 中的执行方式。
加载
references/ci-parallelism-sharding.md和references/infrastructure-troubleshooting.md。 - 通过构建测试反馈目标验证已更改的测试套件。
记录 SDK、运行器模式、目标框架、筛选器、发现/执行/跳过的测试数量、结果路径,以及容器或存根诊断信息。构建或
--list-tests只能证明测试已被发现;筛选后的绿色运行只能证明对应类别和目标框架通过。对于基于 NUKE 的仓库,运行仓库的构建目标,以及覆盖此次更改的类别测试目标;管道目标变更请使用$ops-nuke-cicd。
如果 Testcontainers 或 WireMock 是判定依据的一部分,则必须提供证据,证明预期依赖项已启动并就绪、已收到预期交互,且已完成清理。请明确列出排除的测试套件,不要声称 NUnit 运行已完整。
资源
- NUnit 结构:项目布局、命名、类别和生命周期约定。
- Fixture 模式:Fixture 边界、共享设置、拆卸和组合。
- 测试模板:模板索引、并行执行约定和健康检查模板。
- 使用 NUnit 进行 API 测试:使用 HTTP 断言和契约检查进行端点级测试。
- 测试平台模式:针对
dotnet test、MTP、适配器和仓库级 CLI 差异的运行器模式检查。 - 可靠性与依赖项:WireMock 与 Testcontainers、容器拓扑、组件边界、最终状态断言、确定性和不稳定测试规则。
- WireMock 设置:确定性桩、请求验证和故障模拟。
- Testcontainers 设置:容器生命周期、就绪状态和测试隔离。
- 断言与诊断:分组断言、兼容分析器的模式和更丰富的失败输出。
- CI 并行执行与分片:安全、高效地拆分测试执行。
- 基础设施故障排查:诊断启动失败、端口冲突和就绪状态问题。
- 技能来源:用于当前状态检查的精选 NUnit、.NET 运行器、Testcontainers、WireMock.Net 和软件包参考资料。
模板
- NUnit Handler Fixture 模板:用于设置连接和确定性场景配置的基础 Fixture。
- NUnit Handler 测试模板:使用 Fixture 并遵循 Arrange/Act/Assert 流程的基础测试类。
- NUnit API Fixture 模板:用于以控制器为重点的 API 到数据库全周期测试的 API Fixture。
- NUnit API 测试模板:具有 Fixture 隔离和安全并行生命周期的基础 API 测试类。
- NUnit API 请求构建器模板:用于场景设置的确定性请求构建器。
- NUnit API TestCaseSources 模板:可复用的
TestCaseData来源方法。 - NUnit WireMock 模板:
WireMockServerWrapper和按依赖项划分的*WiremockServer辅助模式。 - NUnit 数据库启动器模板:数据库容器、按顺序运行的一次性迁移容器、可选的迁移开关和表检查。
导航
- 从
## Workflow开始;根据症状进行调试时使用## Failure Triage,交接时使用## Related Skills。
何时不应使用此 Skill(判断事项)
- 如果问题是“我们是否真的需要这个测试”(基于风险确定覆盖优先级、判断要测试什么)——先使用
$qa-testing-strategy,然后再回到这里了解如何构建测试。 - 如果失败原因是
dotnet test/MTP/VSTest 运行器模式不匹配、覆盖率收集器配置,或 CI 目标图,而非 fixture/测试代码——使用$ops-nuke-cicd;不要尝试通过编辑测试文件来修复运行器模式偏差。 - 如果任务是实现或修复失败测试所暴露的生产/服务代码——切换到
$software-csharp-backend;围绕 Bug 编写测试属于此 Skill 的职责,修复 Bug 则不属于。 - 如果相关套件是浏览器/E2E(Playwright、Selenium),而不是进程内 API/组件/集成测试或由 Testcontainers 支持的测试——使用
$qa-testing-playwright或相关的移动端/UI Skill。 - 如果查阅一次
references/reliability-and-dependencies.md后仍不清楚 flaky 测试的根本原因——不要继续猜测修复方案;先添加诊断信息(关联 ID、容器/WireMock 日志、计时信息),确定性地复现问题,然后再修补。悄悄添加[Retry]来掩盖原因不明的 flaky 测试,这是回归,不是修复。
故障分类(症状 → 可能原因 → 首要处理步骤)
| 症状 | 可能的原因类别 | 首要处理步骤 |
|---|---|---|
| 单独运行时测试通过,完整运行时失败 | 共享可变状态或 fixture 生命周期不匹配 | 检查 [FixtureLifeCycle]/[Parallelizable] 的组合;确认 [SetUp] 确实重置了失败测试读取的所有内容 |
| 本地测试通过,仅在 CI 中失败 | 端口冲突、Docker 主机假设(localhost 与远程 Docker 主机)或 CI 并行运行时的资源竞争 | 检查是否硬编码了端口/主机(references/reliability-and-dependencies.md、references/testcontainers-setup.md);将失败类别的并行度降低以进行诊断,而非作为永久修复 |
| 最终一致性断言间歇性超时 | 使用固定休眠而非轮询,或超时时间对 CI 高负载环境而言过短 | 替换为 references/reliability-and-dependencies.md 中的 Eventually 辅助方法;只有确认条件正确后才延长超时时间,不要用它掩盖竞态 |
升级后 dotnet test 静默地发现 0 个测试 | Adapter 主版本与 MTP 版本不匹配,或同一解决方案中混用了 VSTest/MTP | 修改测试代码前,检查 references/test-platform-modes.md 中的 Adapter ↔ MTP ↔ TFM 矩阵;在 MTP 下添加 --minimum-expected-tests,这样测试数不足时运行会失败,而不是显示绿色通过 |
| 启用 MTP 后覆盖率报告为空或缺失 | 仍保留了仅适用于 VSTest 的覆盖率收集器;它在 MTP 下会静默地不起作用 | 替换为 MTP 原生覆盖率扩展:在 references/test-platform-modes.md 中查找当前的软件包搭配,并在软件包自身文档中确认 |
| 依赖 Migrator 的测试因缺少表而失败 | Migrator 顺序问题,而非测试 Bug | 添加重试或延长超时时间前,先查看 references/infrastructure-troubleshooting.md 中的 Migrator 顺序部分 |
相关 Skills
| Skill | 用途 |
|---|---|
| software-csharp-backend | 后端服务实现 |
| ops-nuke-cicd | NUKE 流水线目标和 CI 配置 |
dev-structured-logs | 结构化日志迁移 |
| qa-testing-strategy | 基于风险的测试策略 |
| qa-testing-playwright | 浏览器/E2E 套件(不在此处讨论范围内) |
经验循环
如果之前的决策或注意事项与当前任务相关,请查阅 learnings.consolidated.md(如果存在);仅在需要查看历史记录或没有其他文件可用时,才查阅 learnings.md。否则,请跳过这两个文件。
应用相关经验后,如果你遇到了值得记住的模式、值得避免的错误,或令人意外的领域事实,请通过 agents-skills-feedback-loop/scripts/append_learning.py 向 learnings.md 追加一条带日期的条目。不要修改 SKILL.md 本身。
评论
支持 Markdown