CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/dotnet-unit-tests

.NET unit testing (C# / F# / VB.NET) with xUnit.net as the primary framework - `[Fact]` single tests, `[Theory]` + `[InlineData]`/`[ClassData]`/`[MemberData]` parametrization, class and collection fixtures (`IClassFixture` / `ICollectionFixture`), parallel-execution config, `ITestOutputHelper` output, skip/traits filtering, and `dotnet test` CI with trx + coverage. Includes framework choice (xUnit for new projects; match an existing NUnit/MSTest convention detected from csproj PackageReferences; legacy .NET Framework 4.x → NUnit or MSTest) and test-authoring conventions (AAA mapping, argument-order traps, no fabricated methods, no smoke asserts). References cover NUnit (`[TestCase]`, constraint-model `Assert.That`), MSTest (`[TestClass]` / `[DataRow]` / TestContext), and the FluentAssertions `.Should()` catalog including the v8 commercial-license change. Use for any .NET unit-test task: choosing or configuring a framework, writing or parameterizing tests, fixtures, or wiring CI.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

mstest.mdreferences/

MSTest - Microsoft first-party .NET testing (reference)

Companion reference for dotnet-unit-tests. Consult for existing MSTest projects (the Visual Studio default before ~2018) or Microsoft-toolchain shops standardized on first-party tooling. For new code, xUnit (SKILL.md) or NUnit (nunit.md) are more mainstream.

Per learn.microsoft.com/dotnet/core/testing/unit-testing-with-mstest:

Install and first test

dotnet new mstest -n MyTests
# Or: dotnet add package MSTest.TestFramework + MSTest.TestAdapter + Microsoft.NET.Test.Sdk
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class CalculatorTests
{
    [TestMethod]
    public void Adds_TwoNumbers()
    {
        Assert.AreEqual(3, Calculator.Add(1, 2));
    }
}

[TestClass] is required - unlike NUnit, discovery fails without it. Assert.AreEqual(expected, actual) takes expected first. Run: dotnet test.

Lifecycle

Per ms-doc: [ClassInitialize] / [ClassCleanup] (static, once per class - ClassInitialize receives a TestContext), [TestInitialize] / [TestCleanup] (per test), and [AssemblyInitialize] / [AssemblyCleanup] at assembly level.

Parametrize

[TestMethod]
[DataRow(1, 2, 3)]
[DataRow(0, 0, 0)]
[DataRow(-1, 1, 0)]
public void Adds_VariousInputs(int a, int b, int expected)
{
    Assert.AreEqual(expected, Calculator.Add(a, b));
}

// Dynamic data source
[TestMethod]
[DynamicData(nameof(AddCases), DynamicDataSourceType.Method)]
public void Adds_FromDynamic(int a, int b, int expected) { ... }

public static IEnumerable<object[]> AddCases()
{
    yield return new object[] { 1, 2, 3 };
    yield return new object[] { 0, 0, 0 };
}

TestContext

Auto-injected per test instance - per-test metadata (test name, deployment dir, .runsettings properties) plus WriteLine output (the MSTest analog of xUnit's ITestOutputHelper):

[TestClass]
public class TestsWithContext
{
    public TestContext TestContext { get; set; }   // auto-populated by runner

    [TestMethod]
    public void LogsContext()
    {
        TestContext.WriteLine("Test name: {0}", TestContext.TestName);
    }
}

Skip patterns

[Ignore("Requires staging DB; tracked in JIRA-1234")] for permanent skips; Assert.Inconclusive("...") for runtime conditional skips (marks neither pass nor fail - don't overuse it, signals get lost).

Categories, parallelism, CI

[TestMethod]
[TestCategory("Integration")]
public void IntegrationTest() { }
// Filter: dotnet test --filter "TestCategory=Integration"

.runsettings parallelism:

<RunSettings>
  <RunConfiguration>
    <MaxCpuCount>4</MaxCpuCount>
  </RunConfiguration>
  <MSTest>
    <Parallelize>
      <Workers>4</Workers>
      <Scope>MethodLevel</Scope>
    </Parallelize>
  </MSTest>
</RunSettings>

Scope: MethodLevel (parallel within class) or ClassLevel (parallel across classes only).

- run: dotnet test --logger "trx;LogFileName=test-results.trx" \
    --collect:"XPlat Code Coverage" \
    --settings test.runsettings

Anti-patterns

Anti-patternWhy it failsFix
Assert.AreEqual(actual, expected) reversedMSTest is (expected, actual); misleading diffsExpected first, or FluentAssertions (fluentassertions.md)
Missing [TestClass]Discovery failsAlways include
Console.WriteLine for outputMay not appear in the runnerTestContext.WriteLine
Assert.Inconclusive overuseTests neither pass nor fail[Ignore] for permanent skips

Limitations

  • More verbose attributes than xUnit / NUnit.
  • Historically Visual Studio-centric; CLI integration improved but docs are still VS-flavored.
  • [DynamicData] is less ergonomic than xUnit's [MemberData].

References

  • ms-doc - Microsoft MSTest tutorial
  • github.com/microsoft/testfx - MSTest source

SKILL.md

tile.json