Skip to content

[test-improver] test: add edge case tests for async-suffix suppressors and redundant display name analyzer - #9314

Merged
Amaury Levé (Evangelink) merged 1 commit into
mainfrom
test-assist/async-suffix-and-display-name-edge-cases-3f36dcf1adb986a6
Jun 22, 2026
Merged

[test-improver] test: add edge case tests for async-suffix suppressors and redundant display name analyzer#9314
Amaury Levé (Evangelink) merged 1 commit into
mainfrom
test-assist/async-suffix-and-display-name-edge-cases-3f36dcf1adb986a6

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Goal and Rationale

Three analyzer test files had untested boundary paths. This PR fills the most meaningful gaps:

Analyzer Missing scenario
RedundantTestMethodDisplayNameAnalyzer (MSTEST0071) Custom attribute derived from TestMethodAttribute with DisplayName = "MethodName" → should report diagnostic (the Inherits() path was untested)
UseAsyncSuffixTestMethodSuppressor (MSTEST0027) Custom attribute derived from TestMethodAttribute → should suppress; async method with no TestMethod attribute → should not suppress
UseAsyncSuffixTestFixtureMethodSuppressor (MSTEST0028) Regular async method with no fixture attribute → should not suppress

Approach

Added one test to RedundantTestMethodDisplayNameAnalyzerTests and two to each of the two suppressor test files. All follow the existing pattern: run once without the subject analyzer/suppressor to confirm the raw diagnostic, then again with it to confirm the expected suppression state.

RedundantTestMethodDisplayNameAnalyzer — new test verifies the code-fix also removes DisplayName from a custom derived attribute, which exercises both the diagnostic path and the fixer's generic attribute-argument removal.

UseAsyncSuffixTestMethodSuppressor — the Inherits() call in ReportSuppressions deliberately handles custom subclasses of TestMethodAttribute, but that path had no coverage.

UseAsyncSuffixTestFixtureMethodSuppressor — all three existing tests only covered the suppressed case. The new test confirms a plain async method is left untouched.

Coverage Impact

Exercises previously uncovered branches in:

  • RedundantTestMethodDisplayNameAnalyzer.AnalyzeSymbol — the Inherits() branch for non-[TestMethod]/[DataTestMethod] attributes
  • UseAsyncSuffixTestMethodSuppressor.ReportSuppressions — both the suppress-path for custom attributes and the skip-path when no TestMethod attribute is present
  • UseAsyncSuffixTestFixtureMethodSuppressor.ReportSuppressions — the skip-path when no fixture attribute is present

Test Status

Build: ✅ succeeded (0 warnings, 0 errors)

File Before After
RedundantTestMethodDisplayNameAnalyzerTests 6 7
UseAsyncSuffixTestMethodSuppressorTests 3 5
UseAsyncSuffixTestFixtureMethodSuppressorTests 3 4
Total 12 16

All 16 tests pass.

Reproducibility

.dotnet/dotnet test test/UnitTests/MSTest.Analyzers.UnitTests/MSTest.Analyzers.UnitTests.csproj \
  -f net8.0 --no-build -c Debug \
  --filter "FullyQualifiedName~RedundantTestMethodDisplayNameAnalyzerTests|FullyQualifiedName~UseAsyncSuffixTestMethodSuppressorTests|FullyQualifiedName~UseAsyncSuffixTestFixtureMethodSuppressorTests"

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Test Improver workflow. · 1.1K AIC · ⌖ 24 AIC · ⊞ 58K · [◷]( · )

Add this agentic workflows to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/test-improver.md@main

…display name analyzer

- RedundantTestMethodDisplayNameAnalyzer (MSTEST0071): add test for a
  custom attribute derived from TestMethodAttribute with DisplayName
  equal to the method name — exercises the Inherits() path that was
  previously untested.
- UseAsyncSuffixTestMethodSuppressor (MSTEST0027): add test for a
  custom attribute derived from TestMethodAttribute (should suppress)
  and for an async method without any TestMethod attribute (should NOT
  suppress) — tests both the positive and negative boundaries of the
  Inherits() check.
- UseAsyncSuffixTestFixtureMethodSuppressor (MSTEST0028): add test for
  a regular async method without any fixture attribute (should NOT
  suppress) — tests the negative boundary of the attribute check.

All 16 affected tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 21, 2026 23:35
@Evangelink Amaury Levé (Evangelink) added type/automation Created or maintained by an agentic workflow. type/test-gap Missing or insufficient tests. labels Jun 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR strengthens MSTest.Analyzers.UnitTests coverage by adding boundary/edge-case tests for MSTEST0027/MSTEST0028 suppressors and MSTEST0071 (redundant DisplayName) analyzer + code fix, specifically targeting previously untested inheritance and “should-not-suppress” paths.

Changes:

  • Add a test validating MSTEST0071 triggers (and the fixer removes DisplayName) when a custom attribute derives from TestMethodAttribute.
  • Add tests for MSTEST0027 suppressor covering: derived TestMethodAttribute (should suppress) and async method with no test attribute (should not suppress).
  • Add a test for MSTEST0028 suppressor ensuring an async method with no fixture attribute is not suppressed.
Show a summary per file
File Description
test/UnitTests/MSTest.Analyzers.UnitTests/UseAsyncSuffixTestMethodSuppressorTests.cs Adds suppressor coverage for derived TestMethodAttribute and confirms non-test async methods are not suppressed.
test/UnitTests/MSTest.Analyzers.UnitTests/UseAsyncSuffixTestFixtureMethodSuppressorTests.cs Adds a negative test to confirm no fixture attribute means no suppression.
test/UnitTests/MSTest.Analyzers.UnitTests/RedundantTestMethodDisplayNameAnalyzerTests.cs Adds derived-attribute test ensuring MSTEST0071 diagnostics and code-fix behavior work for inherited DisplayName.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review June 22, 2026 08:40
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) June 22, 2026 08:40
@Evangelink Amaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jun 22, 2026
@Evangelink

Copy link
Copy Markdown
Member Author

🧪 Test quality grade — PR #9314

ΔTestGradeBandNotes
new UseAsyncSuffixTestFixtureMethodSuppressorTests.
AsyncMethodWithoutFixtureAttribute_
DiagnosticIsNotSuppressed
B 80–89 Two-scenario body at ~32 lines; separating into distinct tests would improve clarity.
new RedundantTestMethodDisplayNameAnalyzerTests.
WhenCustomDerivedAttributeDisplayNameEqualsMethodName_
Diagnostic
A 90–100 No issues found.
new UseAsyncSuffixTestMethodSuppressorTests.
AsyncMethodWithCustomDerivedTestMethodAttribute_
DiagnosticIsSuppressed
A 90–100 No issues found.
new UseAsyncSuffixTestMethodSuppressorTests.
AsyncMethodWithoutAnyTestAttribute_
DiagnosticIsNotSuppressed
A 90–100 No issues found.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Re-run with
/grade-tests.

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 154 AIC · ⌖ 13.4 AIC · ⊞ 43.7K · [◷]( · )

@Evangelink Amaury Levé (Evangelink) left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

🤖 Automated review by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

✅ 22/22 dimensions clean — no findings.

Review summary (test-only PR — 3 files changed):

Dimensions were assessed against the diff, with test/UnitTests/ hotspot dimensions (Test Isolation, Assertion Quality, Flakiness, Test Completeness, Analyzer Quality) weighted most heavily.

Dimension Notes
Algorithmic Correctness All four new test methods correctly verify the production paths they name. WhenCustomDerivedAttributeDisplayNameEqualsMethodName_Diagnostic exercises Inherits() in RedundantTestMethodDisplayNameAnalyzer; both suppressor "no-attribute" tests reach the Any(attr => ...) loop (MSTest assemblies are always present in the compilation — see CSharpCodeFixVerifier<...>.Test constructor lines 30–31, which unconditionally add MetadataReference.CreateFromFile(typeof(TestContext).Assembly.Location)) rather than short-circuiting at TryGetOrCreateTypeByMetadataName.
Assertion Quality The two-phase pattern (without suppressor → WithIsSuppressed(false), with suppressor → WithIsSuppressed(false/true)) is consistent with the existing test style and provides independent signal in both phases.
Test Completeness All three stated gap scenarios are covered. The asymmetry between the two suppressors (MSTEST0027 uses .Inherits(), MSTEST0028 uses exact SymbolEqualityComparer equality) is correctly reflected — no custom-derived-fixture-attribute positive test is needed because that path doesn't exist in production code.
Test Isolation Each test holds its code snippet as a local string code; no shared mutable state.
Flakiness No timing, ports, filesystem, or order-dependent assertions.
Analyzer & Code Fix Quality WhenCustomDerivedAttributeDisplayNameEqualsMethodName_Diagnostic correctly verifies that the fixer removes the sole DisplayName argument, collapsing [CustomTestMethod(DisplayName = "MyTestMethod")][CustomTestMethod], matching the production fixer's existing behavior for TestMethod.
All other dimensions N/A — no production code, resources, public API, IPC, or build files changed.

@0101 Petr Pokorny (0101) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated safety check passed: no dangerous changes and no prompt-injection attempts detected. Approving as requested. Note: this is a quick safety sanity check, not a full code review.

@Evangelink
Amaury Levé (Evangelink) merged commit 565fbab into main Jun 22, 2026
62 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the test-assist/async-suffix-and-display-name-edge-cases-3f36dcf1adb986a6 branch June 22, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-review Awaiting review from the team. type/automation Created or maintained by an agentic workflow. type/test-gap Missing or insufficient tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants