Skip to content

Commit fd4d88a

Browse files
CopilotYoussef1313
andauthored
Document MSTest analyzers MSTEST0051-MSTEST0055 (#48813)
* Initial plan * Add documentation for MSTest analyzers MSTEST0051-MSTEST0055 Co-authored-by: Youssef1313 <[email protected]> * Update ms.date in usage-rules.md Co-authored-by: Youssef1313 <[email protected]> * Add MSTEST0051-MSTEST0055 to devops-testing TOC Co-authored-by: Youssef1313 <[email protected]> * Update doc * Update date * Update usage-rules.md --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: Youssef1313 <[email protected]> Co-authored-by: Youssef1313 <[email protected]>
1 parent 8cde0f5 commit fd4d88a

File tree

7 files changed

+357
-1
lines changed

7 files changed

+357
-1
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: "MSTEST0051: Assert.Throws should contain only a single statement"
3+
description: "Learn about code analysis rule MSTEST0051: Assert.Throws should contain only a single statement"
4+
ms.date: 10/01/2025
5+
f1_keywords:
6+
- MSTEST0051
7+
- AssertThrowsShouldContainSingleStatementAnalyzer
8+
helpviewer_keywords:
9+
- AssertThrowsShouldContainSingleStatementAnalyzer
10+
- MSTEST0051
11+
author: Youssef1313
12+
ms.author: ygerges
13+
ai-usage: ai-generated
14+
---
15+
# MSTEST0051: Assert.Throws should contain only a single statement
16+
17+
| Property | Value |
18+
|-------------------------------------|------------------------------------------------------------------------------------------|
19+
| **Rule ID** | MSTEST0051 |
20+
| **Title** | Assert.Throws should contain only a single statement |
21+
| **Category** | Usage |
22+
| **Fix is breaking or non-breaking** | Non-breaking |
23+
| **Enabled by default** | Yes |
24+
| **Default severity** | Info |
25+
| **Introduced in version** | 3.11.0 |
26+
| **Is there a code fix** | No |
27+
28+
## Cause
29+
30+
A call to <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Throws%2A>, <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsAsync%2A>, <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactly%2A>, or <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactlyAsync%2A> contains multiple statements in the action delegate.
31+
32+
## Rule description
33+
34+
To ensure that only the specific method call that is expected to throw an exception is tested, the action delegate passed to `Assert.Throws`, `Assert.ThrowsAsync`, `Assert.ThrowsExactly`, or `Assert.ThrowsExactlyAsync` should contain exactly one statement. Including multiple statements can lead to passing tests when the exception is thrown by a statement that is not intended to throw. If it's not the last statement in the action that is intended to throw, then the test has dead code. If it's the last statement, the intent should be clearly stated.
35+
36+
## How to fix violations
37+
38+
Refactor the test to ensure that the action delegate contains only the single statement that is expected to throw the exception. Move any setup code outside the assertion call.
39+
40+
For example, change this:
41+
42+
```csharp
43+
[TestMethod]
44+
public void TestMethod()
45+
{
46+
var obj = new MyClass();
47+
Assert.ThrowsExactly<InvalidOperationException>(() =>
48+
{
49+
obj.Initialize();
50+
obj.Execute(); // Only this should be inside the assertion
51+
});
52+
}
53+
```
54+
55+
To this:
56+
57+
```csharp
58+
[TestMethod]
59+
public void TestMethod()
60+
{
61+
var obj = new MyClass();
62+
obj.Initialize();
63+
Assert.ThrowsExactly<InvalidOperationException>(() => obj.Execute());
64+
}
65+
```
66+
67+
## When to suppress warnings
68+
69+
Don't suppress warnings from this rule. Including multiple statements in the action delegate can make it unclear which operation is being tested and can lead to passing tests when the original intent is violated.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
title: "MSTEST0052: Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior"
3+
description: "Learn about code analysis rule MSTEST0052: Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior"
4+
ms.date: 10/01/2025
5+
f1_keywords:
6+
- MSTEST0052
7+
- AvoidExplicitDynamicDataSourceTypeAnalyzer
8+
helpviewer_keywords:
9+
- AvoidExplicitDynamicDataSourceTypeAnalyzer
10+
- MSTEST0052
11+
author: Youssef1313
12+
ms.author: ygerges
13+
ai-usage: ai-generated
14+
---
15+
# MSTEST0052: Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior
16+
17+
| Property | Value |
18+
|-------------------------------------|--------------------------------------------------------------------------------------------|
19+
| **Rule ID** | MSTEST0052 |
20+
| **Title** | Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior |
21+
| **Category** | Usage |
22+
| **Fix is breaking or non-breaking** | Non-breaking |
23+
| **Enabled by default** | Yes |
24+
| **Default severity** | Warning |
25+
| **Introduced in version** | 3.11.0 |
26+
| **Is there a code fix** | Yes |
27+
28+
## Cause
29+
30+
A <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute> explicitly specifies <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.Property> or <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.Method> instead of using the default <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.AutoDetect>.
31+
32+
## Rule description
33+
34+
Starting with MSTest 3.8, `DynamicDataSourceType.AutoDetect` is the default value for the `DynamicDataSourceType` parameter in the `DynamicDataAttribute` constructor. This enhancement automatically detects whether the data source is a property, method, or field, eliminating the need to explicitly specify the source type. Using `AutoDetect` makes the code more maintainable and reduces verbosity.
35+
36+
## How to fix violations
37+
38+
Remove the explicit `DynamicDataSourceType` parameter from the `DynamicData` attribute and let the framework auto-detect the source type.
39+
40+
For example, change this:
41+
42+
```csharp
43+
public static IEnumerable<object[]> TestData { get; } = new[]
44+
{
45+
new object[] { 1, 2, 3 },
46+
new object[] { 4, 5, 9 }
47+
};
48+
49+
[TestMethod]
50+
[DynamicData(nameof(TestData), DynamicDataSourceType.Property)]
51+
public void TestMethod(int a, int b, int expected)
52+
{
53+
Assert.AreEqual(expected, a + b);
54+
}
55+
```
56+
57+
To this:
58+
59+
```csharp
60+
public static IEnumerable<object[]> TestData { get; } = new[]
61+
{
62+
new object[] { 1, 2, 3 },
63+
new object[] { 4, 5, 9 }
64+
};
65+
66+
[TestMethod]
67+
[DynamicData(nameof(TestData))]
68+
public void TestMethod(int a, int b, int expected)
69+
{
70+
Assert.AreEqual(expected, a + b);
71+
}
72+
```
73+
74+
## When to suppress warnings
75+
76+
Don't suppress warnings from this rule. Following the analyzer suggestion leads to less noise in the test code.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: "MSTEST0053: Avoid using Assert methods with format parameters"
3+
description: "Learn about code analysis rule MSTEST0053: Avoid using Assert methods with format parameters"
4+
ms.date: 10/01/2025
5+
f1_keywords:
6+
- MSTEST0053
7+
- AvoidAssertFormatParametersAnalyzer
8+
helpviewer_keywords:
9+
- AvoidAssertFormatParametersAnalyzer
10+
- MSTEST0053
11+
author: Youssef1313
12+
ms.author: ygerges
13+
ai-usage: ai-generated
14+
---
15+
# MSTEST0053: Avoid using Assert methods with format parameters
16+
17+
| Property | Value |
18+
|-------------------------------------|------------------------------------------------------------------------------------------|
19+
| **Rule ID** | MSTEST0053 |
20+
| **Title** | Avoid using Assert methods with format parameters |
21+
| **Category** | Usage |
22+
| **Fix is breaking or non-breaking** | Non-breaking |
23+
| **Enabled by default** | Yes |
24+
| **Default severity** | Warning |
25+
| **Introduced in version** | 3.11.0 |
26+
| **Is there a code fix** | Yes |
27+
28+
## Cause
29+
30+
An assertion method call uses the `message` and `parameters` arguments for string formatting instead of using string interpolation.
31+
32+
## Rule description
33+
34+
Using the assertion overloads that accept `message` and `parameters` are no longer recommended. These overloads are removed in MSTest v4. It's advised to use string interpolation instead.
35+
36+
## How to fix violations
37+
38+
Replace calls that use message format parameters with string interpolation.
39+
40+
For example, change this:
41+
42+
```csharp
43+
[TestMethod]
44+
public void TestMethod()
45+
{
46+
int expected = 5;
47+
int actual = GetValue();
48+
Assert.AreEqual(expected, actual, "Expected {0} but got {1}", expected, actual);
49+
}
50+
```
51+
52+
To this:
53+
54+
```csharp
55+
[TestMethod]
56+
public void TestMethod()
57+
{
58+
int expected = 5;
59+
int actual = GetValue();
60+
Assert.AreEqual(expected, actual, $"Expected {expected} but got {actual}");
61+
}
62+
```
63+
64+
## When to suppress warnings
65+
66+
Don't suppress warnings from this rule. These overloads are removed in MSTest v4 and are not recommended.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: "MSTEST0054: Use TestContext.CancellationToken instead of TestContext.CancellationTokenSource.Token"
3+
description: "Learn about code analysis rule MSTEST0054: Use TestContext.CancellationToken instead of TestContext.CancellationTokenSource.Token"
4+
ms.date: 10/01/2025
5+
f1_keywords:
6+
- MSTEST0054
7+
- UseCancellationTokenPropertyAnalyzer
8+
helpviewer_keywords:
9+
- UseCancellationTokenPropertyAnalyzer
10+
- MSTEST0054
11+
author: Youssef1313
12+
ms.author: ygerges
13+
ai-usage: ai-generated
14+
---
15+
# MSTEST0054: Use cancellation token from TestContext.CancellationToken
16+
17+
| Property | Value |
18+
|-------------------------------------|------------------------------------------------------------------------------------------|
19+
| **Rule ID** | MSTEST0054 |
20+
| **Title** | Use TestContext.CancellationToken instead of TestContext.CancellationTokenSource.Token |
21+
| **Category** | Usage |
22+
| **Fix is breaking or non-breaking** | Non-breaking |
23+
| **Enabled by default** | Yes |
24+
| **Default severity** | Info |
25+
| **Introduced in version** | 3.11.0 |
26+
| **Is there a code fix** | Yes |
27+
28+
## Cause
29+
30+
Accessing `CancellationToken` via `TestContext.CancellationTokenSource.Token` instead of using the `TestContext.CancellationToken` property.
31+
32+
## Rule description
33+
34+
MSTest provides a cancellation token through the `TestContext.CancellationToken` property. Accessing `TestContext.CancellationTokenSource` is not recommended, and it might be removed in a future release. It's also simpler to use `TestContext.CancellationToken` compared to `TestContext.CancellationTokenSource.Token`.
35+
36+
## How to fix violations
37+
38+
Use the `TestContext.CancellationToken` property instead of `TestContext.CancellationTokenSource.Token`.
39+
40+
For example, change this:
41+
42+
```csharp
43+
public TestContext TestContext { get; set; }
44+
45+
[TestMethod]
46+
public async Task TestMethod()
47+
{
48+
await Task.Delay(1000, TestContext.CancellationTokenSource.Token);
49+
}
50+
```
51+
52+
To this:
53+
54+
```csharp
55+
public TestContext TestContext { get; set; }
56+
57+
[TestMethod]
58+
public async Task TestMethod()
59+
{
60+
await Task.Delay(1000, TestContext.CancellationToken);
61+
}
62+
```
63+
64+
## When to suppress warnings
65+
66+
Don't suppress warnings from this rule. The use of `CancellationTokenSource` property is not recommended and might be removed in a future release.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: "MSTEST0055: Do not ignore the return value of string methods"
3+
description: "Learn about code analysis rule MSTEST0055: Do not ignore the return value of string methods"
4+
ms.date: 10/01/2025
5+
f1_keywords:
6+
- MSTEST0055
7+
- IgnoreStringMethodReturnValueAnalyzer
8+
helpviewer_keywords:
9+
- IgnoreStringMethodReturnValueAnalyzer
10+
- MSTEST0055
11+
author: Youssef1313
12+
ms.author: ygerges
13+
ai-usage: ai-generated
14+
---
15+
# MSTEST0055: Do not ignore the return value of string methods
16+
17+
| Property | Value |
18+
|-------------------------------------|------------------------------------------------------------------------------------------|
19+
| **Rule ID** | MSTEST0055 |
20+
| **Title** | Do not ignore the return value of string methods |
21+
| **Category** | Usage |
22+
| **Fix is breaking or non-breaking** | Non-breaking |
23+
| **Enabled by default** | Yes |
24+
| **Default severity** | Warning |
25+
| **Introduced in version** | 3.11.0 |
26+
| **Is there a code fix** | No |
27+
28+
## Cause
29+
30+
A call to `string.Contains`, `string.StartsWith`, or `string.EndsWith` is made and its return value is ignored.
31+
32+
## Rule description
33+
34+
Those methods don't have any side effects and ignoring the return result is always wrong. It's more likely that the original intent of those calls are to assert that they are true.
35+
36+
## How to fix violations
37+
38+
Capture and use the return value from string methods, or use a proper assertion method.
39+
40+
For example, change this:
41+
42+
```csharp
43+
[TestMethod]
44+
public void TestMethod()
45+
{
46+
string value = "Hello world";
47+
value.StartsWith("Hello");
48+
}
49+
```
50+
51+
To this:
52+
53+
```csharp
54+
[TestMethod]
55+
public void TestMethod()
56+
{
57+
string value = "Hello world";
58+
Assert.IsTrue(value.StartsWith("Hello")); // or, Assert.StartsWith("Hello", value);
59+
}
60+
```
61+
62+
## When to suppress warnings
63+
64+
Don't suppress warnings from this rule. Calling string methods without using their return value is always a bug or a dead code.

docs/core/testing/mstest-analyzers/usage-rules.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: MSTest Usage rules (code analysis)
33
description: Learn about MSTest code analysis usage rules.
44
author: evangelink
55
ms.author: amauryleve
6-
ms.date: 01/03/2024
6+
ms.date: 10/01/2025
77
---
88

99
# MSTest usage rules
@@ -44,3 +44,8 @@ Identifier | Name | Description
4444
[MSTEST0048](mstest0048.md) | TestContextPropertyUsageAnalyzer | A fixture method (methods with <xref:Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyInitializeAttribute>, <xref:Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyCleanupAttribute>, <xref:Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute>, or <xref:Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupAttribute>) accesses restricted <xref:Microsoft.VisualStudio.TestTools.UnitTesting.TestContext> properties.
4545
[MSTEST0049](mstest0049.md) | FlowTestContextCancellationTokenAnalyzer | A method call within a test context doesn't use the <xref:System.Threading.CancellationToken> available from <xref:Microsoft.VisualStudio.TestTools.UnitTesting.TestContext> when the called method has a parameter or overload that accepts a <xref:System.Threading.CancellationToken>.
4646
[MSTEST0050](mstest0050.md) | GlobalTestFixtureShouldBeValidAnalyzer | A global test fixture method (marked with `GlobalTestInitializeAttribute` or `GlobalTestCleanupAttribute`) doesn't follow the required layout or has invalid configuration.
47+
[MSTEST0051](mstest0051.md) | AssertThrowsShouldContainSingleStatementAnalyzer | A call to <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Throws%2A>, <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsAsync%2A>, <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactly%2A>, or <xref:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactlyAsync%2A> contains multiple statements in the action delegate.
48+
[MSTEST0052](mstest0052.md) | AvoidExplicitDynamicDataSourceTypeAnalyzer | A <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute> explicitly specifies <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.Property> or <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.Method> instead of using the default <xref:Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType.AutoDetect>.
49+
[MSTEST0053](mstest0053.md) | AvoidAssertFormatParametersAnalyzer | An assertion method call uses the `message` and `parameters` arguments for string formatting instead of using string interpolation.
50+
[MSTEST0054](mstest0054.md) | UseCancellationTokenPropertyAnalyzer | Accessing `CancellationToken` via `TestContext.CancellationTokenSource.Token` instead of using the `TestContext.CancellationToken` property.
51+
[MSTEST0055](mstest0055.md) | IgnoreStringMethodReturnValueAnalyzer | A call to `string.Contains`, `string.StartsWith`, or `string.EndsWith` is made and its return value is ignored.

docs/navigate/devops-testing/toc.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ items:
227227
href: ../../core/testing/mstest-analyzers/mstest0049.md
228228
- name: MSTEST0050
229229
href: ../../core/testing/mstest-analyzers/mstest0050.md
230+
- name: MSTEST0051
231+
href: ../../core/testing/mstest-analyzers/mstest0051.md
232+
- name: MSTEST0052
233+
href: ../../core/testing/mstest-analyzers/mstest0052.md
234+
- name: MSTEST0053
235+
href: ../../core/testing/mstest-analyzers/mstest0053.md
236+
- name: MSTEST0054
237+
href: ../../core/testing/mstest-analyzers/mstest0054.md
238+
- name: MSTEST0055
239+
href: ../../core/testing/mstest-analyzers/mstest0055.md
230240
- name: Test platforms
231241
items:
232242
- name: Microsoft.Testing.Platform

0 commit comments

Comments
 (0)