SuperAPI AI 工具集

igniteui-blazor-lite-testing

测试与质量

查看项目

更新于 10-15 22:17

技能介绍

用途

这是 IgniteUI Blazor(Lite)仓库内部的测试说明,面向需要为该仓库组件编写或维护测试的开发者。仓库 tests/ 下有三个测试项目,构成两套测试:单元测试与集成测试。

两套测试的分工

单元测试(tests/IgniteUI.Blazor.Tests):xUnit + bUnit,多目标框架 net8.0/net9.0/net10.0;使用记录型 JS 运行时在进程内渲染组件,不需要浏览器。覆盖属性到渲染属性(直接渲染组件用 bUnit fact,如 cut.Find(...).GetAttribute(...))、标记与子内容渲染、消息状态序列化形状(PropertySerializationTests、EnumSerializationTests、RenderingSerializationTests)、互操作线上行为(方法标识符、参数序列化与类型标签、返回解码、事件处理器注册/移除传输与 JS→.NET 事件分发)、以及 <Member>Script 参数(由 ScriptPropTests 自动扫描)。

集成测试(tests/IgniteUI.Blazor.Lite.IntegrationTests):NUnit + Playwright,每个组件一个生成的测试夹具;另有集成宿主 IgniteUI.Blazor.Lite.TestBed,每次运行渲染一个组件并扫描其接口表面。集成测试验证真实浏览器中针对真实 Web Component 的端到端属性、事件与方法行为;视觉输出和客户端组件逻辑只属集成/e2e,绝不放单元测试。

关键基类

BlazorComponentTestBase:bUnit 的 BunitContext,装配 IIgniteUIBlazor 服务、记录型 JS 运行时(JSRuntimeMode.Loose,记录每次调用)与 Interop harness(通过 InteropFor<TComponent>() 按组件类型解析)。

ComponentWithContractTestBase<TComponent>:增加声明式 ComponentContract<TComponent>、以单行 [Fact] 暴露的 runner(VerifyMethodContract/VerifyPropContract/VerifyEventContract),以及继承的 Contract_SectionsHaveFacts 守卫。每个组件只有一个套件带契约;同步/异步方法对由 twin 重载一并声明。

运行命令

单元测试:dotnet test tests/IgniteUI.Blazor.Tests -f net10.0 --nologo --filter "FullyQualifiedName~<Name>Tests",迭代时只跑单一 TFM(-f net10.0),最终在所有 TFM 上完整跑一遍(去掉 -f)。

集成测试:首次需先构建再安装浏览器,命令为 pwsh tests/IgniteUI.Blazor.Lite.IntegrationTests/bin/Debug/net<version>/playwright.ps1 install chromium;随后 dotnet test tests/IgniteUI.Blazor.Lite.IntegrationTests(或在 Test Explorer 中按组件运行,夹具以组件命名)。.runsettings 可配置本地调试时关闭 headless,或将 useInMemoryClient 设为 false 以对准自己 dotnet run 起的 TestBed 实例。完整设置见 tests/IgniteUI.Blazor.Lite.IntegrationTests/README.md。

约定与限制

一般每个组件一个文件:<Name>Tests.cs 放 <Name>Tests;子组件可与父组件共用一个文件(如 SelectTests.cs 也含 SelectItemTests/SelectGroupTests/SelectHeaderTests;Card、List、Dropdown、NavDrawer、Tabs、Stepper、TileManager、Tree、Rating、Slider 同理),这是唯一允许的多类文件情形。横切套件(BaseControlTests、SerializationTests、ScriptPropTests、InteropTests)按类/行为而非组件归置,各自保留文件。新 fact 放入既有 <Name>Tests 类;若该类带契约,普通 bUnit fact 与契约 runner 同处一类。共享测试辅助位于 ElementAssertionExtensions.cs。

跳过需给出机制层面的理由,缺陷跟踪单或 componentsConfig.json 条目不算跳过理由。若某成员解码碰到非本次改动所属的共享基础设施空白,应钉住当前行为并把正确断言以注释形式写在 // TODO: 下,待修复后取消注释;在建组件中的空白是待修 bug,不是要钉住的行为,详见互操作参考中的两种编写模式。

组件是 partial 的:生成的 src/components/Blazor/<Name>.cs 不是完整类,下结论前务必查看 src/componentsBase/WebInputs/<Name>.cs 中手写的扩展。

格式:本仓库中只有 dotnet format whitespace --folder 是安全的;完整 dotnet format 会向多目标源写入冲突标记。

集成扫描与 componentsConfig.json

每个组件一个通用 NUnit 测试(ComponentTest,夹具来自 TestBed 组件列表):启动 TestBed 应用(默认内存中),调用浏览器端 renderComponent('<IgbName>'),断言 getErrors() 无输出。真正的扫描在 TestBed(Components/Pages/Home.razor)中由反射驱动:TestProps 用生成的示例值在服务端设置每个 [Parameter] 并与浏览器中活 Web Component 的 DOM 属性比较(TestUtil.PropertyValuesAreEqual);TestEvents 对 Web Component 派发合成事件并验证绑定的 .NET 回调触发;方法 spy(wwwroot/app.js 的 spyOnMethod/checkOnSpy)验证调用 .NET API 会以正确的参数/结果调用匹配的 Web Component 方法。仅限异步方法——扫描只筛 Async 并排除 GetAsync getter;同步变体无法在 Server 托管的 TestBed 上运行(无进程内 JS 运行时),因此同步变体、getter 与 <Member>Script 参数没有集成覆盖,单元测试是它们唯一的保障。

componentsConfig.json 按组件控制扫描:ExcludedProps、ExcludedEvents、DependantProps/DependantMethods,每个条通常注明 BUG 编号或通用扫描无法建模的形状。被排除成员完全没有集成覆盖,应视为单元互操作契约的更高优先级,而不是在单元侧也跳过。

新增组件覆盖清单

单元:为渲染属性/标记写 bUnit fact;若组件有互操作表面(发送互操作调用或注册 JS 发起的事件处理器),按 references/interop-contracts.md 添加 ComponentContract;新组件可 TDD 式先写契约,契约同时充当 API 设计记录。集成:扫描会自动纳入组件;仅对通用扫描确实无法建模的成员添加 componentsConfig.json 条目(注明原因),并为每个排除项在单元契约中镜像覆盖。验证:在所有 TFM 上跑单元全套,外加该组件的集成夹具。