dotnet-test-frameworks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

.NET Test Framework Reference

.NET 测试框架参考

Language-specific detection patterns for .NET test frameworks (MSTest, xUnit, NUnit, TUnit).
针对.NET测试框架(MSTest、xUnit、NUnit、TUnit)的语言专属检测模式。

Test File Identification

测试文件识别

FrameworkTest class markersTest method markers
MSTest
[TestClass]
[TestMethod]
,
[DataTestMethod]
xUnit(none — convention-based)
[Fact]
,
[Theory]
NUnit
[TestFixture]
[Test]
,
[TestCase]
,
[TestCaseSource]
TUnit
[ClassDataSource]
[Test]
框架测试类标记测试方法标记
MSTest
[TestClass]
[TestMethod]
,
[DataTestMethod]
xUnit(无,基于约定识别)
[Fact]
,
[Theory]
NUnit
[TestFixture]
[Test]
,
[TestCase]
,
[TestCaseSource]
TUnit
[ClassDataSource]
[Test]

Assertion APIs by Framework

各框架断言API

CategoryMSTestxUnitNUnit
Equality
Assert.AreEqual
Assert.Equal
Assert.That(x, Is.EqualTo(y))
Boolean
Assert.IsTrue
/
Assert.IsFalse
Assert.True
/
Assert.False
Assert.That(x, Is.True)
Null
Assert.IsNull
/
Assert.IsNotNull
Assert.Null
/
Assert.NotNull
Assert.That(x, Is.Null)
Exception
Assert.Throws<T>()
/
Assert.ThrowsExactly<T>()
Assert.Throws<T>()
Assert.That(() => ..., Throws.TypeOf<T>())
Collection
CollectionAssert.Contains
Assert.Contains
Assert.That(col, Has.Member(x))
String
StringAssert.Contains
Assert.Contains(str, sub)
Assert.That(str, Does.Contain(sub))
Type
Assert.IsInstanceOfType
Assert.IsAssignableFrom
Assert.That(x, Is.InstanceOf<T>())
Inconclusive
Assert.Inconclusive()
skip via
[Fact(Skip)]
Assert.Inconclusive()
Fail
Assert.Fail()
Assert.Fail()
(.NET 10+)
Assert.Fail()
Third-party assertion libraries:
Should*
(Shouldly),
.Should()
(FluentAssertions / AwesomeAssertions),
Verify()
(Verify).
分类MSTestxUnitNUnit
相等判断
Assert.AreEqual
Assert.Equal
Assert.That(x, Is.EqualTo(y))
布尔判断
Assert.IsTrue
/
Assert.IsFalse
Assert.True
/
Assert.False
Assert.That(x, Is.True)
空值判断
Assert.IsNull
/
Assert.IsNotNull
Assert.Null
/
Assert.NotNull
Assert.That(x, Is.Null)
异常判断
Assert.Throws<T>()
/
Assert.ThrowsExactly<T>()
Assert.Throws<T>()
Assert.That(() => ..., Throws.TypeOf<T>())
集合判断
CollectionAssert.Contains
Assert.Contains
Assert.That(col, Has.Member(x))
字符串判断
StringAssert.Contains
Assert.Contains(str, sub)
Assert.That(str, Does.Contain(sub))
类型判断
Assert.IsInstanceOfType
Assert.IsAssignableFrom
Assert.That(x, Is.InstanceOf<T>())
不确定结果
Assert.Inconclusive()
通过
[Fact(Skip)]
跳过
Assert.Inconclusive()
强制失败
Assert.Fail()
Assert.Fail()
(.NET 10+)
Assert.Fail()
第三方断言库:
Should*
(Shouldly)、
.Should()
(FluentAssertions / AwesomeAssertions)、
Verify()
(Verify)。

Sleep/Delay Patterns

睡眠/延迟模式

PatternExample
Thread sleep
Thread.Sleep(2000)
Task delay
await Task.Delay(1000)
SpinWait
SpinWait.SpinUntil(() => condition, timeout)
模式示例
线程睡眠
Thread.Sleep(2000)
任务延迟
await Task.Delay(1000)
自旋等待
SpinWait.SpinUntil(() => condition, timeout)

Skip/Ignore Annotations

跳过/忽略注解

FrameworkAnnotationWith reason
MSTest
[Ignore]
[Ignore("reason")]
xUnit
[Fact(Skip = "reason")]
(reason is required)
NUnit
[Ignore("reason")]
(reason is required)
TUnit
[Skip("reason")]
(reason is required)
Conditional
#if false
/
#if NEVER
(no reason possible)
框架注解支持填写原因
MSTest
[Ignore]
[Ignore("reason")]
xUnit
[Fact(Skip = "reason")]
(必须填写原因)
NUnit
[Ignore("reason")]
(必须填写原因)
TUnit
[Skip("reason")]
(必须填写原因)
条件编译
#if false
/
#if NEVER
(无法填写原因)

Exception Handling — Idiomatic Alternatives

异常处理——惯用替代方案

When a test uses
try
/
catch
to verify exceptions, suggest the framework-native alternative:
MSTest:
csharp
// Instead of try/catch (matches exact type):
var ex = Assert.ThrowsExactly<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);

// Or (also matches derived types):
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);
xUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.Equal("Order must contain at least one item", ex.Message);
NUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.That(ex.Message, Is.EqualTo("Order must contain at least one item"));
当测试使用
try
/
catch
验证异常时,推荐使用框架原生的替代方案:
MSTest:
csharp
// 替代try/catch(匹配 exact 类型):
var ex = Assert.ThrowsExactly<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);

// 或者(也匹配派生类型):
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.AreEqual("Order must contain at least one item", ex.Message);
xUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.Equal("Order must contain at least one item", ex.Message);
NUnit:
csharp
var ex = Assert.Throws<InvalidOperationException>(
    () => processor.ProcessOrder(emptyOrder));
Assert.That(ex.Message, Is.EqualTo("Order must contain at least one item"));

Mystery Guest — Common .NET Patterns

神秘访客(Mystery Guest)——常见.NET模式

Smell indicatorWhat to look for
File system
File.ReadAllText
,
File.Exists
,
File.WriteAllBytes
,
Directory.GetFiles
,
Path.Combine
with hard-coded paths
Database
SqlConnection
,
DbContext
(without in-memory provider),
SqlCommand
Network
HttpClient
without
HttpMessageHandler
override,
WebRequest
,
TcpClient
Environment
Environment.GetEnvironmentVariable
,
Environment.CurrentDirectory
Acceptable
MemoryStream
,
StringReader
,
InMemory
database providers, custom
DelegatingHandler
坏味道指标排查点
文件系统带硬编码路径的
File.ReadAllText
、
File.Exists
、
File.WriteAllBytes
、
Directory.GetFiles
、
Path.Combine
数据库
SqlConnection
、未使用内存提供器的
DbContext
、
SqlCommand
网络请求未重写
HttpMessageHandler
的
HttpClient
、
WebRequest
、
TcpClient
环境变量
Environment.GetEnvironmentVariable
、
Environment.CurrentDirectory
可接受用法
MemoryStream
、
StringReader
、内存数据库提供器、自定义
DelegatingHandler

Integration Test Markers

集成测试标记

Recognize these as integration tests (adjust smell severity accordingly):
  • Class name contains
    Integration
    ,
    E2E
    ,
    EndToEnd
    , or
    Acceptance
  • [TestCategory("Integration")]
    (MSTest)
  • [Trait("Category", "Integration")]
    (xUnit)
  • [Category("Integration")]
    (NUnit)
  • Project name ending in
    .IntegrationTests
    or
    .E2ETests
以下特征可识别为集成测试(对应调整坏味道严重等级):
  • 类名包含
    Integration
    、
    E2E
    、
    EndToEnd
    或
    Acceptance
  • [TestCategory("Integration")]
    (MSTest)
  • [Trait("Category", "Integration")]
    (xUnit)
  • [Category("Integration")]
    (NUnit)
  • 项目名以
    .IntegrationTests
    或
    .E2ETests
    结尾

Setup/Teardown Methods

Setup/Teardown 方法

FrameworkSetupTeardown
MSTest
[TestInitialize]
or constructor
[TestCleanup]
or
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
xUnitconstructor
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
NUnit
[SetUp]
[TearDown]
MSTest (class)
[ClassInitialize]
[ClassCleanup]
NUnit (class)
[OneTimeSetUp]
[OneTimeTearDown]
xUnit (class)
IClassFixture<T>
fixture's
Dispose
框架SetupTeardown
MSTest
[TestInitialize]
或构造函数
[TestCleanup]
或
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
xUnit构造函数
IDisposable.Dispose
/
IAsyncDisposable.DisposeAsync
NUnit
[SetUp]
[TearDown]
MSTest(类级别)
[ClassInitialize]
[ClassCleanup]
NUnit(类级别)
[OneTimeSetUp]
[OneTimeTearDown]
xUnit(类级别)
IClassFixture<T>
fixture 的
Dispose
方法