| description | Reference data for .NET test framework detection patterns, assertion APIs, skip annotations, setup/teardown methods, and common test smell indicators across MSTest, xUnit, NUnit, and TUnit. DO NOT USE directly — loaded by test analysis skills (test-anti-patterns, exp-test-smell-detection, exp-assertion-quality, exp-test-maintainability, exp-test-tagging) when they need framework-specific lookup tables. |
| metadata | {"github-path":"plugins/dotnet-test/skills/dotnet-test-frameworks","github-pinned":"v1.0.0","github-ref":"refs/tags/v1.0.0","github-repo":"https://github.com/dotnet/skills","github-tree-sha":"e63b5feebdab4ff15d5e7c961b082222bfb74afa"} |
| name | dotnet-test-frameworks |
| user-invocable | false |
.NET Test Framework Reference
Language-specific detection patterns for .NET test frameworks (MSTest, xUnit, NUnit, TUnit).
Test File Identification
| Framework | Test class markers | Test method markers |
|---|
| MSTest | [TestClass] | [TestMethod], [DataTestMethod] |
| xUnit | (none — convention-based) | [Fact], [Theory] |
| NUnit | [TestFixture] | [Test], [TestCase], [TestCaseSource] |
| TUnit | [ClassDataSource] | [Test] |
Assertion APIs by Framework
| Category | MSTest | xUnit | NUnit |
|---|
| 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).
Sleep/Delay Patterns
| Pattern | Example |
|---|
| Thread sleep | Thread.Sleep(2000) |
| Task delay | await Task.Delay(1000) |
| SpinWait | SpinWait.SpinUntil(() => condition, timeout) |
Skip/Ignore Annotations
| Framework | Annotation | With 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) |
Exception Handling — Idiomatic Alternatives
When a test uses try/catch to verify exceptions, suggest the framework-native alternative:
MSTest:
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:
var ex = Assert.Throws<InvalidOperationException>(
() => processor.ProcessOrder(emptyOrder));
Assert.Equal("Order must contain at least one item", ex.Message);
NUnit:
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
| Smell indicator | What 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 |
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
Setup/Teardown Methods
| Framework | Setup | Teardown |
|---|
| MSTest | [TestInitialize] or constructor | [TestCleanup] or IDisposable.Dispose / IAsyncDisposable.DisposeAsync |
| xUnit | constructor | IDisposable.Dispose / IAsyncDisposable.DisposeAsync |
| NUnit | [SetUp] | [TearDown] |
| MSTest (class) | [ClassInitialize] | [ClassCleanup] |
| NUnit (class) | [OneTimeSetUp] | [OneTimeTearDown] |
| xUnit (class) | IClassFixture<T> | fixture's Dispose |