csharp-xunit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

XUnit Best Practices

XUnit最佳实践

Your goal is to help me write effective unit tests with XUnit, covering both standard and data-driven testing approaches.
你的目标是帮助我编写高效的XUnit单元测试,涵盖标准测试和数据驱动测试两种方式。

Project Setup

项目设置

  • Use a separate test project with naming convention
    [ProjectName].Tests
  • Reference Microsoft.NET.Test.Sdk, xunit, and xunit.runner.visualstudio packages
  • Create test classes that match the classes being tested (e.g.,
    CalculatorTests
    for
    Calculator
    )
  • Use .NET SDK test commands:
    dotnet test
    for running tests
  • 使用独立的测试项目,命名遵循
    [项目名称].Tests
    规范
  • 引用Microsoft.NET.Test.Sdk、xunit和xunit.runner.visualstudio包
  • 创建与被测类对应的测试类(例如,针对
    Calculator
    类创建
    CalculatorTests
    测试类)
  • 使用.NET SDK测试命令:
    dotnet test
    来运行测试

Test Structure

测试结构

  • No test class attributes required (unlike MSTest/NUnit)
  • Use fact-based tests with
    [Fact]
    attribute for simple tests
  • Follow the Arrange-Act-Assert (AAA) pattern
  • Name tests using the pattern
    MethodName_Scenario_ExpectedBehavior
  • Use constructor for setup and
    IDisposable.Dispose()
    for teardown
  • Use
    IClassFixture<T>
    for shared context between tests in a class
  • Use
    ICollectionFixture<T>
    for shared context between multiple test classes
  • 不需要测试类属性(与MSTest/NUnit不同)
  • 对简单测试使用
    [Fact]
    标记的基于事实的测试
  • 遵循Arrange-Act-Assert(AAA)模式
  • 测试命名采用
    方法名_场景_预期行为
    的格式
  • 使用构造函数进行初始化,
    IDisposable.Dispose()
    进行清理
  • 使用
    IClassFixture<T>
    在类内的测试之间共享上下文
  • 使用
    ICollectionFixture<T>
    在多个测试类之间共享上下文

Standard Tests

标准测试

  • Keep tests focused on a single behavior
  • Avoid testing multiple behaviors in one test method
  • Use clear assertions that express intent
  • Include only the assertions needed to verify the test case
  • Make tests independent and idempotent (can run in any order)
  • Avoid test interdependencies
  • 保持测试聚焦于单一行为
  • 避免在一个测试方法中测试多个行为
  • 使用清晰的断言来表达测试意图
  • 仅保留验证测试用例所需的断言
  • 确保测试独立且幂等(可按任意顺序运行)
  • 避免测试之间存在依赖关系

Data-Driven Tests

数据驱动测试

  • Use
    [Theory]
    combined with data source attributes
  • Use
    [InlineData]
    for inline test data
  • Use
    [MemberData]
    for method-based test data
  • Use
    [ClassData]
    for class-based test data
  • Create custom data attributes by implementing
    DataAttribute
  • Use meaningful parameter names in data-driven tests
  • 结合使用
    [Theory]
    特性和数据源特性
  • 对内联测试数据使用
    [InlineData]
  • 对基于方法的测试数据使用
    [MemberData]
  • 对基于类的测试数据使用
    [ClassData]
  • 通过实现
    DataAttribute
    来创建自定义数据特性
  • 在数据驱动测试中使用有意义的参数名称

Assertions

断言

  • Use
    Assert.Equal
    for value equality
  • Use
    Assert.Same
    for reference equality
  • Use
    Assert.True
    /
    Assert.False
    for boolean conditions
  • Use
    Assert.Contains
    /
    Assert.DoesNotContain
    for collections
  • Use
    Assert.Matches
    /
    Assert.DoesNotMatch
    for regex pattern matching
  • Use
    Assert.Throws<T>
    or
    await Assert.ThrowsAsync<T>
    to test exceptions
  • Use fluent assertions library for more readable assertions
  • 使用
    Assert.Equal
    验证值相等
  • 使用
    Assert.Same
    验证引用相等
  • 使用
    Assert.True
    /
    Assert.False
    验证布尔条件
  • 使用
    Assert.Contains
    /
    Assert.DoesNotContain
    验证集合
  • 使用
    Assert.Matches
    /
    Assert.DoesNotMatch
    验证正则表达式匹配
  • 使用
    Assert.Throws<T>
    await Assert.ThrowsAsync<T>
    测试异常
  • 使用流畅断言库以提高断言的可读性

Mocking and Isolation

模拟与隔离

  • Consider using Moq or NSubstitute alongside XUnit
  • Mock dependencies to isolate units under test
  • Use interfaces to facilitate mocking
  • Consider using a DI container for complex test setups
  • 考虑将Moq或NSubstitute与XUnit配合使用
  • 模拟依赖项以隔离被测单元
  • 使用接口以便于模拟
  • 对于复杂的测试设置,考虑使用DI容器

Test Organization

测试组织

  • Group tests by feature or component
  • Use
    [Trait("Category", "CategoryName")]
    for categorization
  • Use collection fixtures to group tests with shared dependencies
  • Consider output helpers (
    ITestOutputHelper
    ) for test diagnostics
  • Skip tests conditionally with
    Skip = "reason"
    in fact/theory attributes
  • 按功能或组件对测试进行分组
  • 使用
    [Trait("Category", "CategoryName")]
    进行分类
  • 使用集合夹具对具有共享依赖的测试进行分组
  • 考虑使用输出助手(
    ITestOutputHelper
    )进行测试诊断
  • 在Fact/Theory特性中通过
    Skip = "原因"
    条件性跳过测试