From e6f7c9a48a6c89bcb7f531216ec25c6b7f4b1ebc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 11:57:17 +0000 Subject: [PATCH 1/7] Initial plan From 908e3777862ffead898fed645b268e01702e1774 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 12:03:02 +0000 Subject: [PATCH 2/7] Add documentation for MSTest analyzers MSTEST0051-MSTEST0055 Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com> --- .../testing/mstest-analyzers/mstest0051.md | 69 ++++++++++++++++ .../testing/mstest-analyzers/mstest0052.md | 76 ++++++++++++++++++ .../testing/mstest-analyzers/mstest0053.md | 66 ++++++++++++++++ .../testing/mstest-analyzers/mstest0054.md | 71 +++++++++++++++++ .../testing/mstest-analyzers/mstest0055.md | 79 +++++++++++++++++++ .../testing/mstest-analyzers/usage-rules.md | 5 ++ 6 files changed, 366 insertions(+) create mode 100644 docs/core/testing/mstest-analyzers/mstest0051.md create mode 100644 docs/core/testing/mstest-analyzers/mstest0052.md create mode 100644 docs/core/testing/mstest-analyzers/mstest0053.md create mode 100644 docs/core/testing/mstest-analyzers/mstest0054.md create mode 100644 docs/core/testing/mstest-analyzers/mstest0055.md diff --git a/docs/core/testing/mstest-analyzers/mstest0051.md b/docs/core/testing/mstest-analyzers/mstest0051.md new file mode 100644 index 0000000000000..df91880e549a9 --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0051.md @@ -0,0 +1,69 @@ +--- +title: "MSTEST0051: Assert.Throws should contain a single statement" +description: "Learn about code analysis rule MSTEST0051: Assert.Throws should contain a single statement" +ms.date: 01/29/2025 +f1_keywords: +- MSTEST0051 +- AssertThrowsShouldContainSingleStatementAnalyzer +helpviewer_keywords: +- AssertThrowsShouldContainSingleStatementAnalyzer +- MSTEST0051 +author: Evangelink +ms.author: amauryleve +ai-usage: ai-generated +--- +# MSTEST0051: Assert.Throws should contain a single statement + +| Property | Value | +|-------------------------------------|------------------------------------------------------------------------------------------| +| **Rule ID** | MSTEST0051 | +| **Title** | Assert.Throws should contain a single statement | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Info | +| **Introduced in version** | 3.10.0 | +| **Is there a code fix** | No | + +## Cause + +A call to , , , or contains multiple statements or no statements in the action delegate. + +## Rule description + +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 unclear test results when an unexpected exception is thrown from a different statement than intended. + +## How to fix violations + +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. + +For example, change this: + +```csharp +[TestMethod] +public void TestMethod() +{ + var obj = new MyClass(); + Assert.ThrowsExactly(() => + { + obj.Initialize(); + obj.Execute(); // Only this should be inside the assertion + }); +} +``` + +To this: + +```csharp +[TestMethod] +public void TestMethod() +{ + var obj = new MyClass(); + obj.Initialize(); + Assert.ThrowsExactly(() => obj.Execute()); +} +``` + +## When to suppress warnings + +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 false positives when unrelated code throws an exception. diff --git a/docs/core/testing/mstest-analyzers/mstest0052.md b/docs/core/testing/mstest-analyzers/mstest0052.md new file mode 100644 index 0000000000000..c9840a309048b --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0052.md @@ -0,0 +1,76 @@ +--- +title: "MSTEST0052: Prefer DynamicDataSourceType.AutoDetect" +description: "Learn about code analysis rule MSTEST0052: Prefer DynamicDataSourceType.AutoDetect" +ms.date: 01/29/2025 +f1_keywords: +- MSTEST0052 +- PreferDynamicDataSourceTypeAutoDetectAnalyzer +helpviewer_keywords: +- PreferDynamicDataSourceTypeAutoDetectAnalyzer +- MSTEST0052 +author: Evangelink +ms.author: amauryleve +ai-usage: ai-generated +--- +# MSTEST0052: Prefer DynamicDataSourceType.AutoDetect + +| Property | Value | +|-------------------------------------|------------------------------------------------------------------------------------------| +| **Rule ID** | MSTEST0052 | +| **Title** | Prefer DynamicDataSourceType.AutoDetect | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Warning | +| **Introduced in version** | 3.10.0 | +| **Is there a code fix** | Yes | + +## Cause + +A explicitly specifies or instead of using the default . + +## Rule description + +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 or method, eliminating the need to explicitly specify the source type. Using `AutoDetect` makes the code more maintainable and reduces verbosity. + +## How to fix violations + +Remove the explicit `DynamicDataSourceType` parameter from the `DynamicData` attribute and let the framework auto-detect the source type. + +For example, change this: + +```csharp +public static IEnumerable TestData { get; } = new[] +{ + new object[] { 1, 2, 3 }, + new object[] { 4, 5, 9 } +}; + +[TestMethod] +[DynamicData(nameof(TestData), DynamicDataSourceType.Property)] +public void TestMethod(int a, int b, int expected) +{ + Assert.AreEqual(expected, a + b); +} +``` + +To this: + +```csharp +public static IEnumerable TestData { get; } = new[] +{ + new object[] { 1, 2, 3 }, + new object[] { 4, 5, 9 } +}; + +[TestMethod] +[DynamicData(nameof(TestData))] +public void TestMethod(int a, int b, int expected) +{ + Assert.AreEqual(expected, a + b); +} +``` + +## When to suppress warnings + +You can suppress warnings from this rule if you're using a version of MSTest earlier than 3.8, where `AutoDetect` isn't available. However, consider upgrading to MSTest 3.8 or later to take advantage of this feature. diff --git a/docs/core/testing/mstest-analyzers/mstest0053.md b/docs/core/testing/mstest-analyzers/mstest0053.md new file mode 100644 index 0000000000000..924618c4c9c7d --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0053.md @@ -0,0 +1,66 @@ +--- +title: "MSTEST0053: Avoid Assert method format parameters" +description: "Learn about code analysis rule MSTEST0053: Avoid Assert method format parameters" +ms.date: 01/29/2025 +f1_keywords: +- MSTEST0053 +- AvoidAssertFormatParametersAnalyzer +helpviewer_keywords: +- AvoidAssertFormatParametersAnalyzer +- MSTEST0053 +author: Evangelink +ms.author: amauryleve +ai-usage: ai-generated +--- +# MSTEST0053: Avoid Assert method format parameters + +| Property | Value | +|-------------------------------------|------------------------------------------------------------------------------------------| +| **Rule ID** | MSTEST0053 | +| **Title** | Avoid Assert method format parameters | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Warning | +| **Introduced in version** | 3.10.0 | +| **Is there a code fix** | Yes | + +## Cause + +An assertion method call uses the `message` and `parameters` arguments for string formatting instead of using string interpolation. + +## Rule description + +Older versions of MSTest assertion methods accepted a `message` parameter and a `params object[]` array for formatting the message. Modern C# supports string interpolation, which provides better compile-time checking, readability, and performance. The newer assertion method overloads support interpolated strings directly, making the format parameters obsolete. + +## How to fix violations + +Replace calls that use message format parameters with string interpolation. + +For example, change this: + +```csharp +[TestMethod] +public void TestMethod() +{ + int expected = 5; + int actual = GetValue(); + Assert.AreEqual(expected, actual, "Expected {0} but got {1}", expected, actual); +} +``` + +To this: + +```csharp +[TestMethod] +public void TestMethod() +{ + int expected = 5; + int actual = GetValue(); + Assert.AreEqual(expected, actual, $"Expected {expected} but got {actual}"); +} +``` + +## When to suppress warnings + +Don't suppress warnings from this rule. String interpolation provides better compile-time safety and readability compared to format parameters. diff --git a/docs/core/testing/mstest-analyzers/mstest0054.md b/docs/core/testing/mstest-analyzers/mstest0054.md new file mode 100644 index 0000000000000..8ee0dc9cb03ca --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0054.md @@ -0,0 +1,71 @@ +--- +title: "MSTEST0054: Use cancellation token from TestContext.CancellationToken" +description: "Learn about code analysis rule MSTEST0054: Use cancellation token from TestContext.CancellationToken" +ms.date: 01/29/2025 +f1_keywords: +- MSTEST0054 +- UseCancellationTokenPropertyAnalyzer +helpviewer_keywords: +- UseCancellationTokenPropertyAnalyzer +- MSTEST0054 +author: Evangelink +ms.author: amauryleve +ai-usage: ai-generated +--- +# MSTEST0054: Use cancellation token from TestContext.CancellationToken + +| Property | Value | +|-------------------------------------|------------------------------------------------------------------------------------------| +| **Rule ID** | MSTEST0054 | +| **Title** | Use cancellation token from TestContext.CancellationToken | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Info | +| **Introduced in version** | 3.10.0 | +| **Is there a code fix** | No | + +## Cause + +A test method creates a new or instead of using the property. + +## Rule description + +MSTest provides a cancellation token through the property that is tied to the test execution lifetime and respects timeouts. Creating a separate cancellation token in the test defeats this integration and can lead to tests that don't respect configured timeouts or cancellation requests. + +Starting with MSTest 3.4, when a test timeout expires and `TimeoutAttribute.CooperativeCancellation` is `true`, the framework signals cancellation through `TestContext.CancellationToken`. Using this property ensures your async tests can be cancelled cooperatively. + +## How to fix violations + +Use the property instead of creating a new cancellation token or source. + +For example, change this: + +```csharp +public TestContext TestContext { get; set; } + +[TestMethod] +[Timeout(5000, CooperativeCancellation = true)] +public async Task TestMethod() +{ + var cts = new CancellationTokenSource(); + await SomeAsyncOperation(cts.Token); +} +``` + +To this: + +```csharp +public TestContext TestContext { get; set; } + +[TestMethod] +[Timeout(5000, CooperativeCancellation = true)] +public async Task TestMethod() +{ + await SomeAsyncOperation(TestContext.CancellationToken); +} +``` + +## When to suppress warnings + +You might suppress warnings from this rule if you have a specific need for a separate cancellation token that is independent of the test execution lifetime. However, in most cases, using the provided `TestContext.CancellationToken` is the better approach. diff --git a/docs/core/testing/mstest-analyzers/mstest0055.md b/docs/core/testing/mstest-analyzers/mstest0055.md new file mode 100644 index 0000000000000..1be957898efb0 --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0055.md @@ -0,0 +1,79 @@ +--- +title: "MSTEST0055: String method return value should not be ignored" +description: "Learn about code analysis rule MSTEST0055: String method return value should not be ignored" +ms.date: 01/29/2025 +f1_keywords: +- MSTEST0055 +- IgnoreStringMethodReturnValueAnalyzer +helpviewer_keywords: +- IgnoreStringMethodReturnValueAnalyzer +- MSTEST0055 +author: Evangelink +ms.author: amauryleve +ai-usage: ai-generated +--- +# MSTEST0055: String method return value should not be ignored + +| Property | Value | +|-------------------------------------|------------------------------------------------------------------------------------------| +| **Rule ID** | MSTEST0055 | +| **Title** | String method return value should not be ignored | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Warning | +| **Introduced in version** | 3.10.0 | +| **Is there a code fix** | No | + +## Cause + +A test method calls a string manipulation method (such as `ToUpper`, `ToLower`, `Trim`, `Replace`, `Substring`) but doesn't use the return value. + +## Rule description + +Strings in .NET are immutable. Methods like `ToUpper()`, `ToLower()`, `Trim()`, `Replace()`, and `Substring()` don't modify the original string; instead, they return a new string with the modifications applied. Calling these methods without using the return value has no effect and is likely a programming error. + +This issue is particularly common in tests where developers might mistakenly believe they're modifying a string in place, leading to incorrect test expectations. + +## How to fix violations + +Capture and use the return value from string methods. + +For example, change this: + +```csharp +[TestMethod] +public void TestMethod() +{ + string value = " hello world "; + value.Trim(); // Return value is ignored + Assert.AreEqual("hello world", value); // This will fail +} +``` + +To this: + +```csharp +[TestMethod] +public void TestMethod() +{ + string value = " hello world "; + value = value.Trim(); // Use the return value + Assert.AreEqual("hello world", value); +} +``` + +Or use the return value directly: + +```csharp +[TestMethod] +public void TestMethod() +{ + string value = " hello world "; + Assert.AreEqual("hello world", value.Trim()); +} +``` + +## When to suppress warnings + +Don't suppress warnings from this rule. Calling string methods without using their return value is always a bug because strings are immutable in .NET. diff --git a/docs/core/testing/mstest-analyzers/usage-rules.md b/docs/core/testing/mstest-analyzers/usage-rules.md index 081ae40c21f5e..827021b8036ad 100644 --- a/docs/core/testing/mstest-analyzers/usage-rules.md +++ b/docs/core/testing/mstest-analyzers/usage-rules.md @@ -44,3 +44,8 @@ Identifier | Name | Description [MSTEST0048](mstest0048.md) | TestContextPropertyUsageAnalyzer | A fixture method (methods with , , , or ) accesses restricted properties. [MSTEST0049](mstest0049.md) | FlowTestContextCancellationTokenAnalyzer | A method call within a test context doesn't use the available from when the called method has a parameter or overload that accepts a . [MSTEST0050](mstest0050.md) | GlobalTestFixtureShouldBeValidAnalyzer | A global test fixture method (marked with `GlobalTestInitializeAttribute` or `GlobalTestCleanupAttribute`) doesn't follow the required layout or has invalid configuration. +[MSTEST0051](mstest0051.md) | AssertThrowsShouldContainSingleStatementAnalyzer | A call to , , , or contains multiple statements or no statements in the action delegate. +[MSTEST0052](mstest0052.md) | PreferDynamicDataSourceTypeAutoDetectAnalyzer | A explicitly specifies or instead of using the default . +[MSTEST0053](mstest0053.md) | AvoidAssertFormatParametersAnalyzer | An assertion method call uses the `message` and `parameters` arguments for string formatting instead of using string interpolation. +[MSTEST0054](mstest0054.md) | UseCancellationTokenPropertyAnalyzer | A test method creates a new or instead of using the property. +[MSTEST0055](mstest0055.md) | IgnoreStringMethodReturnValueAnalyzer | A test method calls a string manipulation method (such as `ToUpper`, `ToLower`, `Trim`, `Replace`, `Substring`) but doesn't use the return value. From 2ff6e259653992ea4176c73d54b1a909e2643850 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 12:06:49 +0000 Subject: [PATCH 3/7] Update ms.date in usage-rules.md Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com> --- docs/core/testing/mstest-analyzers/usage-rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/testing/mstest-analyzers/usage-rules.md b/docs/core/testing/mstest-analyzers/usage-rules.md index 827021b8036ad..6f5e35bfe634a 100644 --- a/docs/core/testing/mstest-analyzers/usage-rules.md +++ b/docs/core/testing/mstest-analyzers/usage-rules.md @@ -3,7 +3,7 @@ title: MSTest Usage rules (code analysis) description: Learn about MSTest code analysis usage rules. author: evangelink ms.author: amauryleve -ms.date: 01/03/2024 +ms.date: 01/29/2025 --- # MSTest usage rules From e883950f56f8763b1a6155485ca5ab289a5babd1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 12:11:23 +0000 Subject: [PATCH 4/7] Add MSTEST0051-MSTEST0055 to devops-testing TOC Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com> --- docs/navigate/devops-testing/toc.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/navigate/devops-testing/toc.yml b/docs/navigate/devops-testing/toc.yml index 57a6ce1b45d6c..9356d2a89e479 100644 --- a/docs/navigate/devops-testing/toc.yml +++ b/docs/navigate/devops-testing/toc.yml @@ -227,6 +227,16 @@ items: href: ../../core/testing/mstest-analyzers/mstest0049.md - name: MSTEST0050 href: ../../core/testing/mstest-analyzers/mstest0050.md + - name: MSTEST0051 + href: ../../core/testing/mstest-analyzers/mstest0051.md + - name: MSTEST0052 + href: ../../core/testing/mstest-analyzers/mstest0052.md + - name: MSTEST0053 + href: ../../core/testing/mstest-analyzers/mstest0053.md + - name: MSTEST0054 + href: ../../core/testing/mstest-analyzers/mstest0054.md + - name: MSTEST0055 + href: ../../core/testing/mstest-analyzers/mstest0055.md - name: Test platforms items: - name: Microsoft.Testing.Platform From b6aa6571169ec56723e05c88f25e0a167d290cc1 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 1 Oct 2025 14:33:53 +0200 Subject: [PATCH 5/7] Update doc --- .../testing/mstest-analyzers/mstest0051.md | 22 ++++----- .../testing/mstest-analyzers/mstest0052.md | 40 ++++++++-------- .../testing/mstest-analyzers/mstest0053.md | 20 ++++---- .../testing/mstest-analyzers/mstest0054.md | 33 ++++++------- .../testing/mstest-analyzers/mstest0055.md | 47 +++++++------------ 5 files changed, 71 insertions(+), 91 deletions(-) diff --git a/docs/core/testing/mstest-analyzers/mstest0051.md b/docs/core/testing/mstest-analyzers/mstest0051.md index df91880e549a9..08c15940a4c52 100644 --- a/docs/core/testing/mstest-analyzers/mstest0051.md +++ b/docs/core/testing/mstest-analyzers/mstest0051.md @@ -1,37 +1,37 @@ --- -title: "MSTEST0051: Assert.Throws should contain a single statement" -description: "Learn about code analysis rule MSTEST0051: Assert.Throws should contain a single statement" -ms.date: 01/29/2025 +title: "MSTEST0051: Assert.Throws should contain only a single statement" +description: "Learn about code analysis rule MSTEST0051: Assert.Throws should contain only a single statement" +ms.date: 10/01/2025 f1_keywords: - MSTEST0051 - AssertThrowsShouldContainSingleStatementAnalyzer helpviewer_keywords: - AssertThrowsShouldContainSingleStatementAnalyzer - MSTEST0051 -author: Evangelink -ms.author: amauryleve +author: Youssef1313 +ms.author: ygerges ai-usage: ai-generated --- -# MSTEST0051: Assert.Throws should contain a single statement +# MSTEST0051: Assert.Throws should contain only a single statement | Property | Value | |-------------------------------------|------------------------------------------------------------------------------------------| | **Rule ID** | MSTEST0051 | -| **Title** | Assert.Throws should contain a single statement | +| **Title** | Assert.Throws should contain only a single statement | | **Category** | Usage | | **Fix is breaking or non-breaking** | Non-breaking | | **Enabled by default** | Yes | | **Default severity** | Info | -| **Introduced in version** | 3.10.0 | +| **Introduced in version** | 3.11.0 | | **Is there a code fix** | No | ## Cause -A call to , , , or contains multiple statements or no statements in the action delegate. +A call to , , , or contains multiple statements in the action delegate. ## Rule description -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 unclear test results when an unexpected exception is thrown from a different statement than intended. +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. ## How to fix violations @@ -66,4 +66,4 @@ public void TestMethod() ## When to suppress warnings -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 false positives when unrelated code throws an exception. +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. diff --git a/docs/core/testing/mstest-analyzers/mstest0052.md b/docs/core/testing/mstest-analyzers/mstest0052.md index c9840a309048b..6031b203fc76f 100644 --- a/docs/core/testing/mstest-analyzers/mstest0052.md +++ b/docs/core/testing/mstest-analyzers/mstest0052.md @@ -1,29 +1,29 @@ --- -title: "MSTEST0052: Prefer DynamicDataSourceType.AutoDetect" -description: "Learn about code analysis rule MSTEST0052: Prefer DynamicDataSourceType.AutoDetect" -ms.date: 01/29/2025 +title: "MSTEST0052: Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior" +description: "Learn about code analysis rule MSTEST0052: Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior" +ms.date: 10/01/2025 f1_keywords: - MSTEST0052 -- PreferDynamicDataSourceTypeAutoDetectAnalyzer +- AvoidExplicitDynamicDataSourceTypeAnalyzer helpviewer_keywords: -- PreferDynamicDataSourceTypeAutoDetectAnalyzer +- AvoidExplicitDynamicDataSourceTypeAnalyzer - MSTEST0052 -author: Evangelink -ms.author: amauryleve +author: Youssef1313 +ms.author: ygerges ai-usage: ai-generated --- -# MSTEST0052: Prefer DynamicDataSourceType.AutoDetect +# MSTEST0052: Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior -| Property | Value | -|-------------------------------------|------------------------------------------------------------------------------------------| -| **Rule ID** | MSTEST0052 | -| **Title** | Prefer DynamicDataSourceType.AutoDetect | -| **Category** | Usage | -| **Fix is breaking or non-breaking** | Non-breaking | -| **Enabled by default** | Yes | -| **Default severity** | Warning | -| **Introduced in version** | 3.10.0 | -| **Is there a code fix** | Yes | +| Property | Value | +|-------------------------------------|--------------------------------------------------------------------------------------------| +| **Rule ID** | MSTEST0052 | +| **Title** | Avoid passing an explicit 'DynamicDataSourceType' and use the default auto detect behavior | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Warning | +| **Introduced in version** | 3.11.0 | +| **Is there a code fix** | Yes | ## Cause @@ -31,7 +31,7 @@ A expli ## Rule description -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 or method, eliminating the need to explicitly specify the source type. Using `AutoDetect` makes the code more maintainable and reduces verbosity. +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. ## How to fix violations @@ -73,4 +73,4 @@ public void TestMethod(int a, int b, int expected) ## When to suppress warnings -You can suppress warnings from this rule if you're using a version of MSTest earlier than 3.8, where `AutoDetect` isn't available. However, consider upgrading to MSTest 3.8 or later to take advantage of this feature. +Don't suppress warnings from this rule. Following the analyzer suggestion leads to less noise in the test code. diff --git a/docs/core/testing/mstest-analyzers/mstest0053.md b/docs/core/testing/mstest-analyzers/mstest0053.md index 924618c4c9c7d..b44274a561549 100644 --- a/docs/core/testing/mstest-analyzers/mstest0053.md +++ b/docs/core/testing/mstest-analyzers/mstest0053.md @@ -1,28 +1,28 @@ --- -title: "MSTEST0053: Avoid Assert method format parameters" -description: "Learn about code analysis rule MSTEST0053: Avoid Assert method format parameters" -ms.date: 01/29/2025 +title: "MSTEST0053: Avoid using Assert methods with format parameters" +description: "Learn about code analysis rule MSTEST0053: Avoid using Assert methods with format parameters" +ms.date: 10/01/2025 f1_keywords: - MSTEST0053 - AvoidAssertFormatParametersAnalyzer helpviewer_keywords: - AvoidAssertFormatParametersAnalyzer - MSTEST0053 -author: Evangelink -ms.author: amauryleve +author: Youssef1313 +ms.author: ygerges ai-usage: ai-generated --- -# MSTEST0053: Avoid Assert method format parameters +# MSTEST0053: Avoid using Assert methods with format parameters | Property | Value | |-------------------------------------|------------------------------------------------------------------------------------------| | **Rule ID** | MSTEST0053 | -| **Title** | Avoid Assert method format parameters | +| **Title** | Avoid using Assert methods with format parameters | | **Category** | Usage | | **Fix is breaking or non-breaking** | Non-breaking | | **Enabled by default** | Yes | | **Default severity** | Warning | -| **Introduced in version** | 3.10.0 | +| **Introduced in version** | 3.11.0 | | **Is there a code fix** | Yes | ## Cause @@ -31,7 +31,7 @@ An assertion method call uses the `message` and `parameters` arguments for strin ## Rule description -Older versions of MSTest assertion methods accepted a `message` parameter and a `params object[]` array for formatting the message. Modern C# supports string interpolation, which provides better compile-time checking, readability, and performance. The newer assertion method overloads support interpolated strings directly, making the format parameters obsolete. +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. ## How to fix violations @@ -63,4 +63,4 @@ public void TestMethod() ## When to suppress warnings -Don't suppress warnings from this rule. String interpolation provides better compile-time safety and readability compared to format parameters. +Don't suppress warnings from this rule. These overloads are removed in MSTest v4 and are not recommended. diff --git a/docs/core/testing/mstest-analyzers/mstest0054.md b/docs/core/testing/mstest-analyzers/mstest0054.md index 8ee0dc9cb03ca..d36f9effad832 100644 --- a/docs/core/testing/mstest-analyzers/mstest0054.md +++ b/docs/core/testing/mstest-analyzers/mstest0054.md @@ -1,15 +1,15 @@ --- -title: "MSTEST0054: Use cancellation token from TestContext.CancellationToken" -description: "Learn about code analysis rule MSTEST0054: Use cancellation token from TestContext.CancellationToken" -ms.date: 01/29/2025 +title: "MSTEST0054: Use TestContext.CancellationToken instead of TestContext.CancellationTokenSource.Token" +description: "Learn about code analysis rule MSTEST0054: Use TestContext.CancellationToken instead of TestContext.CancellationTokenSource.Token" +ms.date: 10/01/2025 f1_keywords: - MSTEST0054 - UseCancellationTokenPropertyAnalyzer helpviewer_keywords: - UseCancellationTokenPropertyAnalyzer - MSTEST0054 -author: Evangelink -ms.author: amauryleve +author: Youssef1313 +ms.author: ygerges ai-usage: ai-generated --- # MSTEST0054: Use cancellation token from TestContext.CancellationToken @@ -17,27 +17,25 @@ ai-usage: ai-generated | Property | Value | |-------------------------------------|------------------------------------------------------------------------------------------| | **Rule ID** | MSTEST0054 | -| **Title** | Use cancellation token from TestContext.CancellationToken | +| **Title** | Use TestContext.CancellationToken instead of TestContext.CancellationTokenSource.Token | | **Category** | Usage | | **Fix is breaking or non-breaking** | Non-breaking | | **Enabled by default** | Yes | | **Default severity** | Info | -| **Introduced in version** | 3.10.0 | -| **Is there a code fix** | No | +| **Introduced in version** | 3.11.0 | +| **Is there a code fix** | Yes | ## Cause -A test method creates a new or instead of using the property. +Accessing `CancellationToken` via `TestContext.CancellationTokenSource.Token` instead of using the `TestContext.CancellationToken` property. ## Rule description -MSTest provides a cancellation token through the property that is tied to the test execution lifetime and respects timeouts. Creating a separate cancellation token in the test defeats this integration and can lead to tests that don't respect configured timeouts or cancellation requests. - -Starting with MSTest 3.4, when a test timeout expires and `TimeoutAttribute.CooperativeCancellation` is `true`, the framework signals cancellation through `TestContext.CancellationToken`. Using this property ensures your async tests can be cancelled cooperatively. +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`. ## How to fix violations -Use the property instead of creating a new cancellation token or source. +Use the `TestContext.CancellationToken` property instead of `TestContext.CancellationTokenSource.Token`. For example, change this: @@ -45,11 +43,9 @@ For example, change this: public TestContext TestContext { get; set; } [TestMethod] -[Timeout(5000, CooperativeCancellation = true)] public async Task TestMethod() { - var cts = new CancellationTokenSource(); - await SomeAsyncOperation(cts.Token); + await Task.Delay(1000, TestContext.CancellationTokenSource.Token); } ``` @@ -59,13 +55,12 @@ To this: public TestContext TestContext { get; set; } [TestMethod] -[Timeout(5000, CooperativeCancellation = true)] public async Task TestMethod() { - await SomeAsyncOperation(TestContext.CancellationToken); + await Task.Delay(1000, TestContext.CancellationToken); } ``` ## When to suppress warnings -You might suppress warnings from this rule if you have a specific need for a separate cancellation token that is independent of the test execution lifetime. However, in most cases, using the provided `TestContext.CancellationToken` is the better approach. +Don't suppress warnings from this rule. The use of `CancellationTokenSource` property is not recommended and might be removed in a future release. diff --git a/docs/core/testing/mstest-analyzers/mstest0055.md b/docs/core/testing/mstest-analyzers/mstest0055.md index 1be957898efb0..209244376392f 100644 --- a/docs/core/testing/mstest-analyzers/mstest0055.md +++ b/docs/core/testing/mstest-analyzers/mstest0055.md @@ -1,43 +1,41 @@ --- -title: "MSTEST0055: String method return value should not be ignored" -description: "Learn about code analysis rule MSTEST0055: String method return value should not be ignored" -ms.date: 01/29/2025 +title: "MSTEST0055: Do not ignore the return value of string methods" +description: "Learn about code analysis rule MSTEST0055: Do not ignore the return value of string methods" +ms.date: 10/01/2025 f1_keywords: - MSTEST0055 - IgnoreStringMethodReturnValueAnalyzer helpviewer_keywords: - IgnoreStringMethodReturnValueAnalyzer - MSTEST0055 -author: Evangelink -ms.author: amauryleve +author: Youssef1313 +ms.author: ygerges ai-usage: ai-generated --- -# MSTEST0055: String method return value should not be ignored +# MSTEST0055: Do not ignore the return value of string methods | Property | Value | |-------------------------------------|------------------------------------------------------------------------------------------| | **Rule ID** | MSTEST0055 | -| **Title** | String method return value should not be ignored | +| **Title** | Do not ignore the return value of string methods | | **Category** | Usage | | **Fix is breaking or non-breaking** | Non-breaking | | **Enabled by default** | Yes | | **Default severity** | Warning | -| **Introduced in version** | 3.10.0 | +| **Introduced in version** | 3.11.0 | | **Is there a code fix** | No | ## Cause -A test method calls a string manipulation method (such as `ToUpper`, `ToLower`, `Trim`, `Replace`, `Substring`) but doesn't use the return value. +A call to `string.Contains`, `string.StartsWith`, or `string.EndsWith` is made and its return value is ignored. ## Rule description -Strings in .NET are immutable. Methods like `ToUpper()`, `ToLower()`, `Trim()`, `Replace()`, and `Substring()` don't modify the original string; instead, they return a new string with the modifications applied. Calling these methods without using the return value has no effect and is likely a programming error. - -This issue is particularly common in tests where developers might mistakenly believe they're modifying a string in place, leading to incorrect test expectations. +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. ## How to fix violations -Capture and use the return value from string methods. +Capture and use the return value from string methods, or use a proper assertion method. For example, change this: @@ -45,9 +43,8 @@ For example, change this: [TestMethod] public void TestMethod() { - string value = " hello world "; - value.Trim(); // Return value is ignored - Assert.AreEqual("hello world", value); // This will fail + string value = "Hello world"; + value.StartsWith("Hello"); } ``` @@ -57,23 +54,11 @@ To this: [TestMethod] public void TestMethod() { - string value = " hello world "; - value = value.Trim(); // Use the return value - Assert.AreEqual("hello world", value); -} -``` - -Or use the return value directly: - -```csharp -[TestMethod] -public void TestMethod() -{ - string value = " hello world "; - Assert.AreEqual("hello world", value.Trim()); + string value = "Hello world"; + Assert.IsTrue(value.StartsWith("Hello")); // or, Assert.StartsWith("Hello", value); } ``` ## When to suppress warnings -Don't suppress warnings from this rule. Calling string methods without using their return value is always a bug because strings are immutable in .NET. +Don't suppress warnings from this rule. Calling string methods without using their return value is always a bug or a dead code. From a6421f769e9666ecbae545a01d91d66bb26f05d2 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 1 Oct 2025 14:35:00 +0200 Subject: [PATCH 6/7] Update date --- docs/core/testing/mstest-analyzers/usage-rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/testing/mstest-analyzers/usage-rules.md b/docs/core/testing/mstest-analyzers/usage-rules.md index 6f5e35bfe634a..8f0d76a747f6e 100644 --- a/docs/core/testing/mstest-analyzers/usage-rules.md +++ b/docs/core/testing/mstest-analyzers/usage-rules.md @@ -3,7 +3,7 @@ title: MSTest Usage rules (code analysis) description: Learn about MSTest code analysis usage rules. author: evangelink ms.author: amauryleve -ms.date: 01/29/2025 +ms.date: 10/01/2025 --- # MSTest usage rules From bd110d0e10b9c22b3e66187862549bfff9f207ea Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 1 Oct 2025 14:38:53 +0200 Subject: [PATCH 7/7] Update usage-rules.md --- docs/core/testing/mstest-analyzers/usage-rules.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/core/testing/mstest-analyzers/usage-rules.md b/docs/core/testing/mstest-analyzers/usage-rules.md index 8f0d76a747f6e..50c3bc7503de9 100644 --- a/docs/core/testing/mstest-analyzers/usage-rules.md +++ b/docs/core/testing/mstest-analyzers/usage-rules.md @@ -44,8 +44,8 @@ Identifier | Name | Description [MSTEST0048](mstest0048.md) | TestContextPropertyUsageAnalyzer | A fixture method (methods with , , , or ) accesses restricted properties. [MSTEST0049](mstest0049.md) | FlowTestContextCancellationTokenAnalyzer | A method call within a test context doesn't use the available from when the called method has a parameter or overload that accepts a . [MSTEST0050](mstest0050.md) | GlobalTestFixtureShouldBeValidAnalyzer | A global test fixture method (marked with `GlobalTestInitializeAttribute` or `GlobalTestCleanupAttribute`) doesn't follow the required layout or has invalid configuration. -[MSTEST0051](mstest0051.md) | AssertThrowsShouldContainSingleStatementAnalyzer | A call to , , , or contains multiple statements or no statements in the action delegate. -[MSTEST0052](mstest0052.md) | PreferDynamicDataSourceTypeAutoDetectAnalyzer | A explicitly specifies or instead of using the default . +[MSTEST0051](mstest0051.md) | AssertThrowsShouldContainSingleStatementAnalyzer | A call to , , , or contains multiple statements in the action delegate. +[MSTEST0052](mstest0052.md) | AvoidExplicitDynamicDataSourceTypeAnalyzer | A explicitly specifies or instead of using the default . [MSTEST0053](mstest0053.md) | AvoidAssertFormatParametersAnalyzer | An assertion method call uses the `message` and `parameters` arguments for string formatting instead of using string interpolation. -[MSTEST0054](mstest0054.md) | UseCancellationTokenPropertyAnalyzer | A test method creates a new or instead of using the property. -[MSTEST0055](mstest0055.md) | IgnoreStringMethodReturnValueAnalyzer | A test method calls a string manipulation method (such as `ToUpper`, `ToLower`, `Trim`, `Replace`, `Substring`) but doesn't use the return value. +[MSTEST0054](mstest0054.md) | UseCancellationTokenPropertyAnalyzer | Accessing `CancellationToken` via `TestContext.CancellationTokenSource.Token` instead of using the `TestContext.CancellationToken` property. +[MSTEST0055](mstest0055.md) | IgnoreStringMethodReturnValueAnalyzer | A call to `string.Contains`, `string.StartsWith`, or `string.EndsWith` is made and its return value is ignored.