
在 .NET runtime 仓库中禁用 CI 测试的完整指南XUnit 特性、项目属性与配置矩阵【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址: https://gitcode.com/GitHub_Trending/runtime6/runtime本指南面向 .NET runtime 仓库的贡献者与 CI 维护者系统讲解如何在持续集成CI测试体系中按需禁用测试。文章以 docs/workflow/ci/disabling-tests.md 为骨架结合仓库中src/tests与src/libraries的真实测试代码与构建配置覆盖为什么禁用、在哪一层禁用、用什么机制禁用三个核心问题。读完本文你将能够针对处理器架构、运行时CoreCLR/Mono、操作系统与特定测试模式GCStress、JIT stress、ReadyToRun 等精确地关闭测试而不影响其他配置下的覆盖。为什么需要禁用测试CI 中禁用测试只有两类动机永久禁用与临时禁用。永久禁用由于测试或产品本身的设计某个测试在特定配置下永远不会被期望运行。例如某个 API 在浏览器Browser平台上根本没有实现该平台的测试就应被永久跳过。临时禁用测试当前处于失败状态为了避免失败测试持续污染测试结果让结果噪声不断需要先将其禁用这类测试预期在 bug 修复或功能实现后重新启用。临时禁用是 CI 日常运维中最常见的操作。无论哪种情况核心原则都是在最精确的失败条件下禁用测试。如果测试只在 arm64 上失败就不要为所有架构禁用如果只在 macOS 上失败就不要同时禁掉 Windows 或 Linux。当失败配置范围尚不明确时有时也需要适当扩大禁用范围这是被接受的折中做法。定位测试归属runtime 测试还是 libraries 测试仓库中存在两套主要的测试体系禁用机制类似但 runtime 测试因构建与执行方式不同拥有更多选项测试集合位置特征runtime 测试src/tests使用 XUnit 模型 源码生成器XUnitWrapperGenerator构造入口禁用手段最丰富libraries 测试分散在src/libraries各库的tests目录标准 XUnit 特性 MSBuild 属性PAL 测试src/coreclr/pal/tests本文不涉及按原文档约定忽略runtime 测试的完整构建/运行约定可参见 docs/workflow/testing/coreclr/test-configuration.mdlibraries 测试的过滤机制详见 docs/workflow/testing/libraries/filtering-tests.md。测试配置矩阵先确定禁用维度动手禁用前必须先确定你要在哪个维度上禁用。仓库 CI 支持按以下维度细分所有配置全局禁用单一处理器架构x86、x64、arm32、arm64单一运行时或其变体coreclr、mono以及 mono 变体monointerpreter、llvmaot、llvmfullaot单一操作系统Windows、Linux、macOS、Android、iOS 等特定运行类型run typeGCStressGC 压力测试JIT stress各类 JIT 压力测试ildasm/ilasm 往返测试ReadyToRunR2R测试实践中应从最具体的失败条件入手仅在 arm64 失败就只禁 arm64仅在 macOS 失败就只禁 macOS。这种精确性保证了其他配置的回归覆盖不被破坏。禁用 runtime 测试src/testsruntime 测试有三种禁用手段XUnit 特性首选、CLRTestTargetUnsupported项目属性、以及项目文件中的测试配置属性。一般优先使用 XUnit 特性只有无法使用时才退而求其次。通过 XUnit 特性禁用runtime 测试基于 XUnit 模型执行仓库提供了一组针对不同测试模式过滤的特性详细清单见 docs/workflow/testing/libraries/filtering-tests.md。常用示例// 禁止在 Mono 上运行 [SkipOnMono] // 禁止在 CoreCLR 上运行 [SkipOnCoreClr] // 禁止在 NativeAOT 上运行用 ConditionalFact 替代 [Fact] [ConditionalFact(, typeof(TestLibrary.Utilities), nameof(Utilities.IsNotNativeAot))] // 禁止在 GCStress 下运行 [SkipOnCoreClr(Reason, RuntimeTestModes.AnyGCStress)] // 禁止在 HeapVerify 下运行 [SkipOnCoreClr(Reason, RuntimeTestModes.HeapVerify)] // 禁止在各类 JIT stress 模式下运行 [SkipOnCoreClr(Reason, RuntimeTestModes.AnyJitStress)]此外ConditionalFact、ConditionalTheory、PlatformSpecific、ActiveIssue等特性也可用于只在特定平台或配置下启用/禁用测试。仓库中大量 GC 测试就是使用SkipOnCoreClrRuntimeTestModes.AnyGCStress的实战范例例如 src/tests/GC/API/GC/GetGCMemoryInfo.cs 中的写法[SkipOnCoreClr(This test is not compatible with GC stress because it captures GC indices and asserts no ephemeral GC occurred between measurements., RuntimeTestModes.AnyGCStress)]又如 src/tests/CoreMangLib/system/span/RefStructWithSpan.cs[SkipOnCoreClr(Incompatible with GC stress, RuntimeTestModes.AnyGCStress)]这些特性参数中的RuntimeTestModes定义了运行模式枚举AnyGCStress、HeapVerify、AnyJitStress、JitMinOpts、JitStressRegs、InterpreterActive等可叠加多个特性表达任一条件满足即跳过的语义。需要注意部分测试模式是在程序集级别处理的。对于这类测试应标记RequiresProcessIsolationtrue/RequiresProcessIsolation并使用下一节的手段禁用。通过 CLRTestTargetUnsupported 属性禁用某些场景下 XUnit 特性无法生效典型情况是测试项目被标记为RequiresProcessIsolationtrue/RequiresProcessIsolation时测试拥有显式Main方法未使用XUnitWrapperGenerator源码生成器此时 XUnit 特性不会生效测试由非 C# 语言通常是 IL编写且因其他原因必须设置RequiresProcessIsolationtrue/RequiresProcessIsolation此时没有生成器可处理特性。此时应在项目文件中通过设置CLRTestTargetUnsupported属性并附带相关条件来禁用同时用注释记录 issue 链接或原因。仓库中的真实示例如 src/tests/GC/API/Frozen/Frozen.csproj!-- Needed for CLRTestTargetUnsupported -- CLRTestTargetUnsupported Condition$(RuntimeFlavor) ! coreclrtrue/CLRTestTargetUnsupportedsrc/tests/GC/API/GC/GetTotalAllocatedBytesServerGC.csproj 展示了多条件组合的用法CLRTestTargetUnsupported Condition$(RuntimeFlavor) ! coreclrtrue/CLRTestTargetUnsupported CLRTestTargetUnsupported Condition$(RuntimeFlavor) coreclr and $(TargetOS) browsertrue/CLRTestTargetUnsupported该属性在构建系统中确实被消费在 src/tests/Directory.Build.targets 中_WillCLRTestProjectBuild的计算逻辑会在CLRTestBuildAllTargets ! allTargets且CLRTestTargetUnsupported true时将该项目排除出构建从而连带跳过其运行。这意味着该属性可以按TargetArchitecture、TargetOS、RuntimeFlavor等标准 MSBuild 条件求值比 XUnit 特性更底层、影响面更彻底直接跳过构建。通过测试配置属性禁用部分测试配置必须通过编辑测试的.csproj或.ilproj文件、在PropertyGroup中插入属性来实现目标场景项目属性禁用在可卸载性unloadability测试中运行UnloadabilityIncompatibletrue/UnloadabilityIncompatible禁用在 ildasm/ilasm 往返测试中运行IlasmRoundTripIncompatibletrue/IlasmRoundTripIncompatible禁止将测试程序集传给 Mono AOT 编译器MonoAotIncompatibletrue/MonoAotIncompatible禁止将测试传给 CrossGen2CrossGenTestfalse/CrossGenTest禁用在 ReadyToRunR2R测试腿中运行R2RIncompatibletrue/R2RIncompatible禁止将测试传给 NativeAOT ILCompiler 并在 NativeAOT 下运行NativeAotIncompatibletrue/NativeAotIncompatible当某个测试已经因其他原因需要设置RequiresProcessIsolationtrue/RequiresProcessIsolation时以下两个属性也可以写在项目文件中替代 XUnit 特性但不能把它们作为设置RequiresProcessIsolation的唯一理由目标场景项目属性禁用在 GCStress 下运行GCStressIncompatibletrue/GCStressIncompatible禁用在 JIT stress 模式下运行JitOptimizationSensitivetrue/JitOptimizationSensitive这些属性同样支持条件化例如原文档给出的经典写法GCStressIncompatible Condition$(TargetArchitecture) arm64 and $(TargetOS) osxtrue/GCStressIncompatible即仅在arm64 macOS组合下禁用 GCStress 运行。仓库实测中这类属性常与注释配合使用如 src/tests/GC/Features/HeapExpansion/bestfit-finalize.csproj 同时设置了GCStressIncompatible与UnloadabilityIncompatible两个属性src/tests/GC/API/GC/GetTotalAllocatedBytesServerGC.csproj 也在同一项目中组合使用CLRTestTargetUnsupported、CLRTestEnvironmentVariable与GCStressIncompatible。从构建系统实现看这些属性在 src/tests/Directory.Build.targets 中被统一纳入_WillCLRTestProjectBuild的判定例如NativeAotIncompatible true且TestBuildMode nativeaot时项目不会构建RuntimeFlavor mono且AlwaysUseCrossgen2 true时同样被排除。也就是说这些属性不是建议性的而是会被构建目标严格执行的开关。禁用 libraries 测试src/librarieslibraries 测试的禁用机制集中在 docs/workflow/testing/libraries/filtering-tests.md 中核心是ActiveIssueAttribute、SkipOnCoreClrAttribute与SkipOnMonoAttribute三个特性。ActiveIssueAttribute跟踪活跃 issue 的临时禁用当测试失败与某个活跃 issue 绑定、需要在修复前跳过时使用。可以作用于测试类禁用类内全部测试或测试方法并允许在同一成员上多次使用。该特性会返回failing类别默认不运行。关键要求是将作用范围严格限定在 issue 实际影响的平台与目标框架上。// 所有平台、所有目标框架禁用 [ActiveIssue(https://github.com/dotnet/runtime/issues/17845)] // 仅特定平台 [ActiveIssue(https://github.com/dotnet/runtime/issues/52072, TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] // 仅特定运行时CoreCLR/Mono [ActiveIssue(https://github.com/dotnet/runtime/issues/2337, TestRuntimes.Mono)] // 仅特定目标框架 [ActiveIssue(https://github.com/dotnet/runtime/issues/26624, TargetFrameworkMonikers.Netcoreapp)] // 平台 目标框架组合 [ActiveIssue(string issue, TestPlatforms platforms, TargetFrameworkMonikers frameworks)] // 使用 PlatformDetection 自定义条件 [ActiveIssue(https://github.com/dotnet/runtimelab/issues/155, typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))]仓库实测如 src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs 中大量使用[ActiveIssue(https://github.com/dotnet/runtime/issues/107981, TestPlatforms.Wasi)]按平台定向跳过src/libraries/Common/tests/System/FunctionPointerCallingConventionTests.cs 使用[ActiveIssue(https://github.com/dotnet/runtime/issues/90308, TestRuntimes.Mono)]仅跳过 Mono 运行时。SkipOnCoreClrAttribute按 CoreCLR 配置精确禁用用于仅在 CoreCLR 运行时不影响 Mono下禁用测试典型场景是 GCStress、JitStress 等特定运行配置下的失败。可作用于测试类或测试方法支持多次使用。支持按平台、测试模式、运行时配置以及它们的组合进行过滤// 所有平台、所有目标框架 [SkipOnCoreClr(CoreCLR does track thread specific JIT information)] // 特定平台 [SkipOnCoreClr(Long running tests: https://github.com/dotnet/runtime/issues/11980, TestPlatforms.Linux)] // 特定测试模式运行配置JitStress、JitStressRegs、JitMinOpts、TailcallStress、GCStress 等 [SkipOnCoreClr(https://github.com/dotnet/runtime/issues/60240, RuntimeTestModes.JitStressRegs)] // 特定运行时配置Debug/Checked/Release [SkipOnCoreClr(https://github.com/dotnet/runtime/issues/45464, ~RuntimeConfiguration.Release)]组合签名要求所有条件同时满足才跳过SkipOnCoreClr(string reason, RuntimeConfiguration runtimeConfigurations, RuntimeTestModes testModes) SkipOnCoreClr(string reason, TestPlatforms testPlatforms, RuntimeConfiguration runtimeConfigurations) SkipOnCoreClr(string reason, TestPlatforms testPlatforms, RuntimeTestModes testMode) SkipOnCoreClr(string reason, TestPlatforms testPlatforms, RuntimeConfiguration runtimeConfigurations, RuntimeTestModes testModes)而多次使用特性则表达任一条件满足即跳过或语义。例如下面的写法表示只有在 Release 且未设置DOTNET_JITMinOpts的构建中才运行该测试[SkipOnCoreClr(https://github.com/dotnet/runtime/issues/67886, ~RuntimeConfiguration.Release)] [SkipOnCoreClr(https://github.com/dotnet/runtime/issues/67886, RuntimeTestModes.JitMinOpts)]注意~RuntimeConfiguration.Release中的取反运算符它表达除 Release 外的所有配置是这类特性常用的精确控制手法。SkipOnMonoAttribute永久性平台/运行时差异禁用用于仅在 Mono 下禁用测试可作用于程序集、类或方法[SkipOnMonoAttribute(string reason, TestPlatforms testPlatforms TestPlatforms.Any)] [SkipOnMono(No SAPI on Mono)]它面向的是API 在该运行时不可用或行为存在有意的平台差异这类永久性跳过场景与ActiveIssue的临时性质互补。其他常用过滤机制libraries 测试体系中还有若干补充手段[OuterLoop()]标记耗时长、覆盖冷路径或需要特殊资源的测试。默认不随dotnet build运行需显式启用build -test -testscope outerloop cd src/System.Text.RegularExpressions/tests dotnet build /t:Test /p:TestScopeouterloop[PlatformSpecific(TestPlatforms platforms)]只在指定平台运行同时为nonwindowstests、nonlinuxtests、nonosxtests等类别打上标签dotnet build csproj_file /t:Test /p:TargetOSlinux dotnet build csproj_file /t:Test /p:TargetOSlinux /p:WithCategoriesfailing[SkipOnPlatform(TestPlatforms platforms, string reason)]永久跳过某平台如 Browser 上不支持凭据若多平台原因不同应在同一测试上使用多个特性分别说明。仓库实例见 src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs。若整个测试程序集都跳过建议同时在.csproj中加入IgnoreForCI Condition$(TargetOS) ...true/IgnoreForCI让 CI 完全不把该程序集发送给 Helix节省流水线资源。[SkipOnTargetFramework(TargetFrameworkMonikers frameworks, string reason)]永久跳过某目标框架如 .NET Framework 下行为不同。[ConditionalFact]/[ConditionalTheory]当上述特性灵活性不足、需要在测试运行时执行自定义逻辑时使用。条件必须是零参数、返回Boolean的静态方法或属性可位于当前类或任何祖先类型上public class TestClass { public static bool ConditionProperty true; [ConditionalFact(nameof(ConditionProperty))] public static void TestMethod() { Assert.True(true); } }ConditionalTheory还需配合[MemberData]、[ClassData]或[InlineData]提供测试数据。[Fact(Skip reason)]xunit 标准特性直接整体跳过测试。若跳过原因是 issue 链接官方推荐改用ActiveIssueAttribute否则Skip可提供更自由的描述文本。[Collection(nameof(DisableParallelization))]标注测试类不可与其他类的测试并发运行适用于占用大量磁盘、内存或独占 CPU 核、容易干扰并发测试的场景。附加建议与最佳实践每条禁用都必须有依据所有上述特性都应附带 issue 链接或紧邻的注释简要说明原因。ActiveIssueAttribute与SkipOnTargetFrameworkAttribute应通过构造函数参数承载该信息其余特性在写法上保持看到即知道为何跳过。组装级跳过时同步优化 CI当整程序集都不需要运行时除特性外还应配合.csproj中的IgnoreForCI条件属性避免 Helix 空跑。精确优先必要时放宽在不确定完整失败配置集时临时放宽禁用范围是允许且常见的但一旦确认具体条件应尽快收窄到最小影响面。文档配套向src/tests添加测试的完整规范CLRTestKind、CLRTestPriority、DisableProjectBuild、AlwaysUseCrossGen2等见 docs/workflow/testing/coreclr/test-configuration.mdlibraries 测试特性全集见 docs/workflow/testing/libraries/filtering-tests.md。【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址: https://gitcode.com/GitHub_Trending/runtime6/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考