Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ The `Workers` property specifies the maximum number of threads for parallel exec
> You can also configure parallelization through [runsettings](unit-testing-mstest-configure.md#mstest-element) or [testconfig.json](unit-testing-mstest-configure.md#testconfigjson) without modifying code.

> [!TIP]
> Enable parallelization at the assembly level by default, even if many tests currently require sequential execution. This approach encourages writing new tests that support parallel execution from the start. Use the [MSTEST0001](mstest-analyzers/mstest0001.md) analyzer to ensure that every test class explicitly declares its parallelization intent, which forces you to review whether each class safely supports concurrent execution. Often, excluding just a few classes or methods with `DoNotParallelize` is sufficient, allowing the majority of your tests to run in parallel for significantly faster test execution.
> Enable parallelization at the assembly level by default, even if many tests currently require sequential execution. This approach encourages writing new tests that support parallel execution from the start. Use the [MSTEST0001](mstest-analyzers/mstest0001.md) analyzer to ensure that the assembly explicitly declares its parallelization intent with `[assembly: Parallelize]` or `[assembly: DoNotParallelize]`. Once parallelization is enabled, review each test class to determine whether it safely supports concurrent execution. Often, excluding just a few classes or methods with `DoNotParallelize` is sufficient, allowing the majority of your tests to run in parallel for significantly faster test execution.

### `DoNotParallelizeAttribute`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ MSTest provides several attributes for data-driven testing:
|-----------|----------|----------|
| [`DataRow`](#datarowattribute) | Inline test data | Simple, static test cases |
| [`DynamicData`](#dynamicdataattribute) | Data from methods, properties, or fields | Complex or computed test data |
| [`TestDataRow<T>`](#testdatarow) | Enhanced data with metadata | Test cases needing display names or categories |
| [`DataSource`](#datasourceattribute) | External data files or databases | Legacy scenarios with external data sources |
| [`ITestDataSource`](#itestdatasource) | Custom data source attributes | Fully custom data-driven scenarios |

MSTest also provides the following types to extend data-driven scenarios:

- [`TestDataRow<T>`](#testdatarow): A return type for `ITestDataSource` implementations (including `DynamicData`) that adds metadata support such as display names, categories, and ignore messages to individual test cases.
- [`ITestDataSource`](#itestdatasource): An interface you can implement on a custom attribute to create fully custom data source attributes.

> [!TIP]
> For combinatorial testing (testing all combinations of multiple parameter sets), use the open-source [Combinatorial.MSTest](https://www.nuget.org/packages/Combinatorial.MSTest) NuGet package. This community-maintained package is [available on GitHub](https://github.com/Youssef1313/Combinatorial.MSTest) but isn't maintained by Microsoft.
Expand Down Expand Up @@ -237,10 +240,10 @@ Specify a different class using the type parameter:
```csharp
public class TestDataProvider
{
public static IEnumerable<object[]> GetTestData()
public static IEnumerable<(int, string)> GetTestData()
{
yield return new object[] { 1, "first" };
yield return new object[] { 2, "second" };
yield return (1, "first");
yield return (2, "second");
}
}

Expand Down Expand Up @@ -273,10 +276,10 @@ public class DynamicDataDisplayNameExample
Assert.IsTrue(value1 > 0);
}

public static IEnumerable<object[]> GetTestData()
public static IEnumerable<(int, string)> GetTestData()
{
yield return new object[] { 1, "first" };
yield return new object[] { 2, "second" };
yield return (1, "first");
yield return (2, "second");
}

public static string GetDisplayName(MethodInfo methodInfo, object[] data)
Expand Down Expand Up @@ -307,10 +310,10 @@ public class IgnoreDynamicDataExample
// All test cases from GetTestData are skipped
}

public static IEnumerable<object[]> GetTestData()
public static IEnumerable<(int, string)> GetTestData()
{
yield return new object[] { 1, "first" };
yield return new object[] { 2, "second" };
yield return (1, "first");
yield return (2, "second");
}
}
```
Expand Down Expand Up @@ -340,20 +343,20 @@ public class TestDataRowExample
Assert.IsTrue(value1 > 0);
}

public static IEnumerable<TestDataRow> GetTestDataRows()
public static IEnumerable<TestDataRow<(int, string)>> GetTestDataRows()
{
yield return new TestDataRow((1, "first"))
yield return new TestDataRow<(int, string)>((1, "first"))
{
DisplayName = "Test Case 1: Basic scenario",
};

yield return new TestDataRow((2, "second"))
yield return new TestDataRow<(int, string)>((2, "second"))
{
DisplayName = "Test Case 2: Edge case",
TestCategories = ["HighPriority", "Critical"],
};

yield return new TestDataRow((3, "third"))
yield return new TestDataRow<(int, string)>((3, "third"))
{
IgnoreMessage = "Not yet implemented",
};
Expand Down Expand Up @@ -511,27 +514,22 @@ For most scenarios, the default `Auto` behavior provides the best balance. Consi
public class UnfoldingExample
{
[TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Unfold)] // That's the default behavior
[DataRow(1)]
[DataRow(2)]
[DataRow(3)]
[DataRow(1, "one")]
[DataRow(2, "two")]
[DataRow(3, "three")]
public void TestMethodWithUnfolding(int value, string text)
{
// Each test case appears individually in Test Explorer
}

[TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Fold)]
[DynamicData(nameof(GetData))]
[DataRow(1, "one")]
[DataRow(2, "two")]
[DataRow(3, "three")]
public void TestMethodWithFolding(int value, string text)
{
// All test cases appear as a single collapsed node
}

public static IEnumerable<(int, string)> GetData()
{
yield return (1, "one");
yield return (2, "two");
yield return (3, "three");
}
}
```

Expand Down