csharp-xunit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseXUnit 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., for
CalculatorTests)Calculator - Use .NET SDK test commands: for running tests
dotnet test
- 使用独立的测试项目,命名遵循规范
[项目名称].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 attribute for simple tests
[Fact] - Follow the Arrange-Act-Assert (AAA) pattern
- Name tests using the pattern
MethodName_Scenario_ExpectedBehavior - Use constructor for setup and for teardown
IDisposable.Dispose() - Use for shared context between tests in a class
IClassFixture<T> - Use for shared context between multiple test classes
ICollectionFixture<T>
- 不需要测试类属性(与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 combined with data source attributes
[Theory] - Use for inline test data
[InlineData] - Use for method-based test data
[MemberData] - Use for class-based test data
[ClassData] - Create custom data attributes by implementing
DataAttribute - Use meaningful parameter names in data-driven tests
- 结合使用特性和数据源特性
[Theory] - 对内联测试数据使用
[InlineData] - 对基于方法的测试数据使用
[MemberData] - 对基于类的测试数据使用
[ClassData] - 通过实现来创建自定义数据特性
DataAttribute - 在数据驱动测试中使用有意义的参数名称
Assertions
断言
- Use for value equality
Assert.Equal - Use for reference equality
Assert.Same - Use /
Assert.Truefor boolean conditionsAssert.False - Use /
Assert.Containsfor collectionsAssert.DoesNotContain - Use /
Assert.Matchesfor regex pattern matchingAssert.DoesNotMatch - Use or
Assert.Throws<T>to test exceptionsawait Assert.ThrowsAsync<T> - 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 for categorization
[Trait("Category", "CategoryName")] - Use collection fixtures to group tests with shared dependencies
- Consider output helpers () for test diagnostics
ITestOutputHelper - Skip tests conditionally with in fact/theory attributes
Skip = "reason"
- 按功能或组件对测试进行分组
- 使用进行分类
[Trait("Category", "CategoryName")] - 使用集合夹具对具有共享依赖的测试进行分组
- 考虑使用输出助手()进行测试诊断
ITestOutputHelper - 在Fact/Theory特性中通过条件性跳过测试
Skip = "原因"