test-tagging

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Test Trait Tagging

测试特性标记

Analyze an existing test suite and apply a standardized set of trait tags to each test method, giving teams visibility into their test distribution (positive vs. negative, critical-path coverage, smoke tests, etc.).
分析现有测试套件,并为每个测试方法应用一套标准化的特性标签,帮助团队了解其测试分布情况(正向测试 vs 负向测试、核心路径覆盖情况、冒烟测试等)。

When to Use

适用场景

  • Auditing a test project to understand the mix of test types
  • Adding trait attributes to untagged tests
  • Generating a summary report of trait distribution across a test suite
  • Reviewing whether critical paths have sufficient coverage
  • 审计测试项目,了解测试类型的构成
  • 为未标记的测试添加特性属性
  • 生成测试套件的特性分布汇总报告
  • 检查核心路径是否有足够的覆盖

When Not to Use

不适用场景

  • Writing new tests from scratch (use
    writing-mstest-tests
    )
  • Running or filtering tests (use
    run-tests
    )
  • Migrating between test frameworks
  • 从零开始编写新测试(使用
    writing-mstest-tests
  • 运行或筛选测试(使用
    run-tests
  • 在测试框架之间迁移

Inputs

输入项

InputRequiredDescription
Test project or filesYesPath to the test project, folder, or specific test files to analyze
ScopeNo
tag
(apply attributes),
audit
(report only), or
both
(default:
both
)
FrameworkNoAuto-detected. Override with
mstest
,
xunit
, or
nunit
if detection fails
输入项是否必填说明
测试项目或文件要分析的测试项目、文件夹或特定测试文件的路径
范围
tag
(添加属性)、
audit
(仅生成报告)或
both
(默认值:
both
框架自动检测。若检测失败,可手动指定为
mstest
xunit
nunit

Trait Taxonomy

特性分类体系

Use exactly these trait names and values. Do not invent new trait values outside this table.
Trait ValueMeaningHeuristics
positive
Verifies expected behavior under normal/valid conditionsAsserts success, valid output, expected state, no exceptions for valid input
negative
Verifies correct handling of invalid input, errors, or edge casesAsserts exceptions, error codes, validation failures, rejects bad input
boundary
Tests limits, thresholds, empty/null inputs, min/max valuesOperates on
0
,
-1
,
int.MaxValue
, empty string, null, empty collection, boundary of valid range
critical-path
Core workflow that must never break; breakage blocks usersTests the primary success scenario of a key public API or user-facing feature
smoke
Quick sanity check that the system is operationalFast, no complex setup, verifies basic wiring (e.g., service resolves, endpoint returns 200)
regression
Reproduces a specific previously-reported bugReferences a bug ID, issue number, or describes a fix in its name or comments
integration
Crosses process, network, or persistence boundariesUses real database, HTTP client, file system, external service, or multi-component setup
end-to-end
Full user workflow spanning the entire application stackExercises a complete scenario from entry point to final result, distinct from single-boundary
integration
performance
Validates timing, throughput, or resource consumptionAsserts on elapsed time, memory, allocations, or uses benchmark harness
security
Verifies authentication, authorization, input sanitization, or secrets handlingTests for SQL injection, XSS, CSRF, unauthorized access, token validation, permission checks
concurrency
Validates thread safety, parallelism, or async correctnessUses
Task.WhenAll
, locks,
Parallel.ForEach
,
SemaphoreSlim
, reproduces race conditions
resilience
Tests retry logic, timeouts, circuit breakers, or graceful degradationAsserts behavior under transient failures, network drops, or service unavailability (e.g., Polly policies)
destructive
Mutates shared or external state that is hard to roll backDeletes records, drops resources, modifies global config -- useful for CI isolation decisions
configuration
Verifies settings loading, defaults, environment behaviorTests missing config keys, invalid values, environment variable fallbacks, options validation
flaky
Known to intermittently fail (meta-tag for test health tracking)Mark tests the team knows are unreliable; used to quarantine or prioritize stabilization
A single test may have multiple traits (e.g., both
negative
and
boundary
). At minimum, every test should receive one of
positive
or
negative
.
请严格使用以下特性名称和取值,请勿使用此表格以外的特性取值。
特性取值含义判断依据
positive
验证正常/有效条件下的预期行为断言成功、有效输出、预期状态,有效输入无异常
negative
验证对无效输入、错误或边缘情况的正确处理断言异常、错误码、验证失败、拒绝不良输入
boundary
测试限制、阈值、空/Null输入、最小/最大值操作
0
-1
int.MaxValue
、空字符串、null、空集合、有效范围的边界值
critical-path
绝对不能中断的核心工作流;中断会阻碍用户操作测试关键公共API或用户面向功能的主要成功场景
smoke
快速 sanity 检查,验证系统是否可正常运行执行速度快,无复杂配置,验证基础连接(如:服务可解析、端点返回200)
regression
复现特定的已报告Bug名称或注释中引用Bug ID、问题编号,或描述修复内容
integration
跨进程、网络或持久化边界使用真实数据库、HTTP客户端、文件系统、外部服务,或多组件配置
end-to-end
跨越整个应用栈的完整用户工作流执行从入口点到最终结果的完整场景,区别于单一边界的
integration
测试
performance
验证时序、吞吐量或资源消耗断言耗时、内存、内存分配,或使用基准测试工具
security
验证认证、授权、输入清理或密钥处理测试SQL注入、XSS、CSRF、未授权访问、令牌验证、权限检查
concurrency
验证线程安全、并行性或异步正确性使用
Task.WhenAll
、锁、
Parallel.ForEach
SemaphoreSlim
,复现竞态条件
resilience
测试重试逻辑、超时、熔断或优雅降级断言瞬态故障、网络中断或服务不可用时的行为(如:Polly策略)
destructive
修改难以回滚的共享或外部状态删除记录、销毁资源、修改全局配置——有助于CI隔离决策
configuration
验证配置加载、默认值、环境行为测试缺失的配置键、无效值、环境变量回退、选项验证
flaky
已知会间歇性失败(用于测试健康跟踪的元标签)标记团队已知不可靠的测试;用于隔离或优先稳定处理
单个测试可拥有多个特性(例如:同时标记
negative
boundary
)。每个测试至少应标记
positive
negative
中的一个。

Workflow

工作流程

Step 1: Detect the test framework

步骤1:检测测试框架

Examine project files and source code to determine the framework — see the
dotnet-test-frameworks
skill for the complete detection table (package references, test markers, assertion APIs, and skip annotations).
检查项目文件和源代码以确定框架——完整的检测规则请参考
dotnet-test-frameworks
技能(包引用、测试标记、断言API和跳过注解)。

Step 2: Scan existing traits

步骤2:扫描现有特性

Check which tests already have trait attributes:
FrameworkExisting AttributeExample
MSTest
[TestCategory("...")]
[TestCategory("positive")]
xUnit
[Trait("Category", "...")]
[Trait("Category", "positive")]
NUnit
[Category("...")]
[Category("positive")]
Record which tests already have tags to avoid duplication.
检查哪些测试已拥有特性属性:
框架现有属性示例
MSTest
[TestCategory("...")]
[TestCategory("positive")]
xUnit
[Trait("Category", "...")]
[Trait("Category", "positive")]
NUnit
[Category("...")]
[Category("positive")]
记录已标记的测试,避免重复添加。

Step 3: Classify each test method

步骤3:对每个测试方法分类

For each test method without traits, analyze:
  1. Method name -- names containing
    Invalid
    ,
    Fail
    ,
    Error
    ,
    Throw
    ,
    Reject
    ,
    BadInput
    ,
    Null
    ,
    Negative
    suggest
    negative
  2. Assertion type --
    Assert.ThrowsException
    ,
    Assert.Throws
    ,
    Should().Throw()
    suggest
    negative
  3. Input values --
    null
    ,
    ""
    ,
    0
    ,
    -1
    ,
    int.MaxValue
    ,
    int.MinValue
    , empty collections suggest
    boundary
  4. Setup complexity -- minimal setup with basic assertions suggests
    smoke
    ; external dependencies suggest
    integration
  5. Comments and names -- references to issue numbers or "regression" / "bug" / "fix for #..." suggest
    regression
  6. Timing assertions --
    Stopwatch
    ,
    BenchmarkDotNet
    , elapsed-time checks suggest
    performance
  7. Feature centrality -- tests on primary public API entry points or critical user workflows suggest
    critical-path
  8. Security patterns -- validates auth, checks permissions, sanitizes input, tests for injection, handles tokens/secrets suggest
    security
  9. Parallel/async constructs --
    Task.WhenAll
    ,
    Parallel.ForEach
    , locks,
    SemaphoreSlim
    ,
    ConcurrentDictionary
    , race condition names suggest
    concurrency
  10. Fault injection -- simulates failures, tests retries, timeouts, or circuit breakers suggest
    resilience
  11. State mutation -- deletes external records, drops resources, modifies shared/global state suggest
    destructive
  12. Full-stack flow -- test spans entry point through data layer to final response, covering a complete user scenario suggest
    end-to-end
  13. Config/settings -- loads configuration, tests missing keys, validates options, checks environment variables suggest
    configuration
  14. Known instability -- test has
    [Ignore]
    /
    [Skip]
    comments about flakiness, or names contain "flaky"/"intermittent" suggest
    flaky
  15. Default -- if the test verifies a normal success path, tag
    positive
When in doubt between
positive
and
negative
, read the assertion: if it asserts success ->
positive
; if it asserts failure ->
negative
.
对于每个未标记特性的测试方法,分析以下内容:
  1. 方法名称——包含
    Invalid
    Fail
    Error
    Throw
    Reject
    BadInput
    Null
    Negative
    的名称表明是
    negative
    测试
  2. 断言类型——
    Assert.ThrowsException
    Assert.Throws
    Should().Throw()
    表明是
    negative
    测试
  3. 输入值——
    null
    ""
    0
    -1
    int.MaxValue
    int.MinValue
    、空集合表明是
    boundary
    测试
  4. 配置复杂度——最小配置+基础断言表明是
    smoke
    测试;依赖外部服务表明是
    integration
    测试
  5. 注释和名称——引用问题编号或包含"regression"/"bug"/"fix for #..."表明是
    regression
    测试
  6. 时序断言——
    Stopwatch
    BenchmarkDotNet
    、耗时检查表明是
    performance
    测试
  7. 核心特性——测试主要公共API入口点或关键用户工作流表明是
    critical-path
    测试
  8. 安全模式——验证认证、检查权限、清理输入、测试注入、处理令牌/密钥表明是
    security
    测试
  9. 并行/异步结构——
    Task.WhenAll
    Parallel.ForEach
    、锁、
    SemaphoreSlim
    ConcurrentDictionary
    、竞态条件名称表明是
    concurrency
    测试
  10. 故障注入——模拟故障、测试重试、超时或熔断表明是
    resilience
    测试
  11. 状态修改——删除外部记录、销毁资源、修改共享/全局状态表明是
    destructive
    测试
  12. 全栈流程——测试从入口点到数据层再到最终响应的完整用户场景表明是
    end-to-end
    测试
  13. 配置/设置——加载配置、测试缺失键、验证选项、检查环境变量表明是
    configuration
    测试
  14. 已知不稳定性——测试带有
    [Ignore]
    /
    [Skip]
    注释说明不稳定,或名称包含"flaky"/"intermittent"表明是
    flaky
    测试
  15. 默认值——若测试验证正常成功路径,标记为
    positive
若无法确定是
positive
还是
negative
,查看断言内容:断言成功则标记
positive
;断言失败则标记
negative

Step 4: Apply trait attributes

步骤4:应用特性属性

Add the appropriate attribute to each test method. Place trait attributes on the line directly above or below the existing test attribute.
MSTest:
csharp
[TestMethod]
[TestCategory("negative")]
[TestCategory("boundary")]
public void Parse_NullInput_ThrowsArgumentNullException() { ... }
xUnit:
csharp
[Fact]
[Trait("Category", "positive")]
[Trait("Category", "critical-path")]
public void CreateOrder_ValidItems_ReturnsConfirmation() { ... }
NUnit:
csharp
[Test]
[Category("regression")]
[Category("negative")]
public void Calculate_OverflowInput_ReturnsError() // Fix for #1234
{ ... }
为每个测试方法添加适当的属性。将特性属性放在现有测试属性的上一行或下一行。
MSTest:
csharp
[TestMethod]
[TestCategory("negative")]
[TestCategory("boundary")]
public void Parse_NullInput_ThrowsArgumentNullException() { ... }
xUnit:
csharp
[Fact]
[Trait("Category", "positive")]
[Trait("Category", "critical-path")]
public void CreateOrder_ValidItems_ReturnsConfirmation() { ... }
NUnit:
csharp
[Test]
[Category("regression")]
[Category("negative")]
public void Calculate_OverflowInput_ReturnsError() // Fix for #1234
{ ... }

Step 5: Generate trait summary

步骤5:生成特性汇总

After tagging, produce a summary table:
undefined
标记完成后,生成汇总表格:
undefined

Trait Distribution

特性分布

TraitCount% of Total
positive4253.8%
negative2228.2%
boundary810.3%
critical-path1215.4%
smoke33.8%
regression56.4%
integration45.1%
end-to-end22.6%
performance11.3%
security33.8%
concurrency22.6%
resilience11.3%
destructive11.3%
configuration22.6%
flaky11.3%
Total tests78--
Note: Percentages exceed 100% because tests can have multiple traits.

Include observations such as:
- Ratio of positive to negative tests
- Whether critical-path tests exist for key public APIs
- Any tests that could not be confidently classified (list them for manual review)
特性数量占比
positive4253.8%
negative2228.2%
boundary810.3%
critical-path1215.4%
smoke33.8%
regression56.4%
integration45.1%
end-to-end22.6%
performance11.3%
security33.8%
concurrency22.6%
resilience11.3%
destructive11.3%
configuration22.6%
flaky11.3%
总测试数78--
注:占比总和超过100%,因为单个测试可拥有多个特性。

同时包含以下观察结果:
- 正向测试与负向测试的比例
- 关键公共API是否有核心路径测试
- 无法准确分类的测试(列出以便人工审核)

Validation

验证项

  • Every test method has at least one trait attribute (
    positive
    or
    negative
    at minimum)
  • No invented trait values outside the taxonomy table
  • Existing trait attributes were preserved, not duplicated
  • The trait summary table was generated
  • The project still builds after changes (
    dotnet build
    )
  • 每个测试方法至少拥有一个特性属性(至少标记
    positive
    negative
  • 未使用分类体系以外的特性取值
  • 保留了现有特性属性,未重复添加
  • 生成了特性汇总表格
  • 修改后项目仍可正常构建(
    dotnet build

Common Pitfalls

常见陷阱

PitfallSolution
Guessing traits without reading the test bodyAlways read assertions and setup to classify accurately
Tagging a test only as
boundary
without
positive
/
negative
Every test should also be
positive
or
negative
--
boundary
is additive
Using
TestCategory
syntax in an xUnit project
Match the attribute style to the detected framework
Duplicating an existing category attributeCheck for pre-existing traits in Step 2 before adding
Over-tagging as
critical-path
Reserve for tests on primary public entry points, not every helper
陷阱解决方案
未阅读测试内容就猜测特性务必阅读断言和配置内容以准确分类
仅标记
boundary
而未标记
positive
/
negative
每个测试还应标记
positive
negative
——
boundary
是附加特性
在xUnit项目中使用
TestCategory
语法
根据检测到的框架匹配对应的属性格式
重复添加已存在的分类属性步骤2中检查现有特性后再添加新属性
过度标记
critical-path
仅用于主要公共入口点的测试,而非所有辅助测试