Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In this article, you learn about the APIs and conventions used by MSTest to help you write and shape your tests.
Note
Attribute names ending with "Attribute" can use the short form. TestClass and TestClassAttribute are equivalent. Attributes with parameterless constructors can omit parentheses.
Test structure
Every MSTest test class must have the TestClass attribute, and every test method must have the TestMethod attribute:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class CalculatorTests
{
[TestMethod]
public void Add_TwoNumbers_ReturnsSum()
{
// Arrange
var calculator = new Calculator();
// Act
var result = calculator.Add(2, 3);
// Assert
Assert.AreEqual(5, result);
}
}
TestClassAttribute
The TestClassAttribute marks a class that contains tests and, optionally, initialize or cleanup methods. You can extend this attribute to customize test class behavior.
TestMethodAttribute
The TestMethodAttribute marks a method as a test to run. Test methods must be:
- Instance methods (not static)
- Public
- Return
void,Task, orValueTask(MSTest v3.3+) - Parameterless, unless using data-driven attributes
[TestClass]
public class TestMethodExamples
{
[TestMethod]
public void SynchronousTest()
{
Assert.IsTrue(true);
}
[TestMethod]
public async Task AsynchronousTest()
{
await Task.Delay(100);
Assert.IsTrue(true);
}
}
Warning
Don't use async void for test methods. Use async Task or async ValueTask instead.
DiscoverInternalsAttribute
The DiscoverInternalsAttribute assembly attribute enables MSTest to discover internal test classes and methods. By default, only public tests are discovered. This attribute is particularly useful when you have parameterized tests that use internal types as parameters:
[assembly: DiscoverInternals]
internal record TestInput(int Value, string Description);
[TestClass]
public class CalculatorTests
{
internal static IEnumerable<TestInput> TestData
{
get
{
yield return new TestInput(1, "one");
yield return new TestInput(2, "two");
}
}
[TestMethod]
[DynamicData(nameof(TestData))]
internal void Add_WithTestInput_ReturnsExpected(TestInput input)
{
var calculator = new Calculator();
var result = calculator.Add(input.Value, 1);
Assert.AreEqual(input.Value + 1, result);
}
}
Without DiscoverInternals, the test method and its internal TestInput parameter type wouldn't be discovered by the test runner.
Core concepts
MSTest documentation is organized by topic:
| Topic | Description |
|---|---|
| Assertions | Verify expected results with Assert classes |
| Data-driven testing | Run tests with multiple inputs (DataRow, DynamicData) |
| Test lifecycle | Setup and cleanup at assembly, class, and test levels |
| Execution control | Threading, parallelization, timeouts, retries, and conditional execution |
| Test organization | Categories, priorities, owners, and metadata |
| TestContext | Access test runtime information |
Attribute quick reference
| Category | Attributes | See |
|---|---|---|
| Test identification | TestClass, TestMethod, DiscoverInternals |
This page |
| Data-driven | DataRow, DynamicData, TestDataRow |
Data-driven testing |
| Lifecycle | AssemblyInitialize, ClassInitialize, TestInitialize, and cleanup counterparts |
Test lifecycle |
| Threading | STATestClass, STATestMethod, UITestMethod |
Execution control |
| Parallelization | Parallelize, DoNotParallelize |
Execution control |
| Timeout/Retry | Timeout, Retry |
Execution control |
| Conditional | Ignore, OSCondition, CICondition |
Execution control |
| Metadata | TestCategory, TestProperty, Owner, Priority |
Test organization |
| Work tracking | WorkItem, GitHubWorkItem |
Test organization |
Assertions
Use the Assert classes of the Microsoft.VisualStudio.TestTools.UnitTesting namespace to verify specific functionality. A test method exercises code in your application, but it reports correctness only when you include Assert statements.
MSTest assertions are divided into:
Assertclass: General-purpose assertions (AreEqual,IsTrue,ThrowsException)StringAssertclass: String-specific assertions (Contains,Matches,StartsWith)CollectionAssertclass: Collection assertions (Contains,AllItemsAreUnique,AreEquivalent)
Testing private members
You can test private members using reflection wrapper classes:
- PrivateObject: For private instance methods
- PrivateType: For private static methods
Tip
Consider whether private methods need direct testing. Often, testing through public interfaces provides better coverage and more maintainable tests.