[quality-improver] AssertSourceCompatibilityTests.SpanAndMemoryCalls tests only half of the Span/Memory × comparer overload combinations
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
Research direction
Open test/IntegrationTests/MSTest.Acceptance.IntegrationTests/AssertSourceCompatibilityTests.cs and start with SpanAndMemoryCalls. Add the missing comparer and no-comparer combinations for Contains, DoesNotContain, ContainsAll, and DoesNotContainAll described in the issue. Run the acceptance integration tests and confirm every specified Span/Memory overload shape is represented.
Written by the indexing model from the issue text.
Description
🎯 Repository Quality Improvement Report — Assert Span/Memory Overload Coverage Gap
Analysis Date: 2026-09-24
Focus Area: Assert Span/Memory Overload Resolution Test Coverage
Strategy Type: Custom
Executive Summary
AssertSourceCompatibilityTests.cs exists specifically to "compile manually maintained consumer call shapes" and catch overload-resolution regressions across Span<T>, ReadOnlySpan<T>, arrays, and IEnumerable<T> implicit conversions — a documented concern in this repo because adding overloads can silently make previously-unambiguous calls ambiguous for consumers. Its own VerifyEveryPublicAssertMethodFamilyHasAConsumerCall guard explicitly warns: "It cannot detect a new overload in an existing family, so every overload change must also add representative implicit consumer call shapes."
However, the SpanAndMemoryCalls scenario in that file does not follow its own rule for four heavily-overloaded method families: Assert.Contains, Assert.DoesNotContain, Assert.ContainsAll, and Assert.DoesNotContainAll. Each of these has Span<T>, ReadOnlySpan<T>, Memory<T>, and ReadOnlyMemory<T> overloads in both a "no comparer" and an "IEqualityComparer<T>" shape (8 combinations per family for the value/collection forms), but the test only ever exercises 4 of those 8 combinations per family — and always the same 4, systematically skipping the Span<T>+comparer and Memory<T>+comparer shapes, plus predicate overloads over Span<T>/ReadOnlyMemory<T>. A future overload addition or refactor in this specific slice (e.g. a new Span<T> overload with a different comparer constraint) could introduce an ambiguity for consumers today's suite would not detect.
Full Analysis Report
Focus Area: Assert Span/Memory Overload Resolution Test Coverage
Current State Assessment
Untested combinations (source has the overload; SpanAndMemoryCalls never calls it):
| Method | Missing combination(s) |
|---|---|
Assert.Contains |
Span<T> value+comparer; Memory<T> value+comparer; predicate over Span<T>; predicate over ReadOnlySpan<T>; predicate over ReadOnlyMemory<T> |
Assert.DoesNotContain |
Same pattern as Contains |
Assert.ContainsAll |
Span<T>+comparer; ReadOnlySpan<T> no-comparer; Memory<T>+comparer; ReadOnlyMemory<T> no-comparer |
Assert.DoesNotContainAll |
Same pattern as ContainsAll |
Concretely, in test/IntegrationTests/MSTest.Acceptance.IntegrationTests/AssertSourceCompatibilityTests.cs (SpanAndMemoryCalls, ~lines 526–541):
Assert.Contains(1, span); // Span, no comparer — tested
Assert.Contains(1, readOnlySpan, comparer); // ReadOnlySpan, comparer — tested
Assert.Contains((int value) => value > 0, memory); // Memory, predicate — tested
Assert.Contains(1, readOnlyMemory); // ReadOnlyMemory, no comparer — tested
// Never called: Contains(1, span, comparer), Contains(1, memory, comparer),
// Contains(predicate, span/readOnlySpan/readOnlyMemory)
Assert.ContainsAll(span, span); // Span, no comparer — tested
Assert.ContainsAll(readOnlySpan, readOnlySpan, comparer); // ReadOnlySpan, comparer — tested
Assert.ContainsAll(memory, memory); // Memory, no comparer — tested
Assert.ContainsAll(readOnlyMemory, readOnlyMemory, comparer); // ReadOnlyMemory, comparer — tested
// Never called: ContainsAll(span, span, comparer), ContainsAll(readOnlySpan, readOnlySpan),
// ContainsAll(memory, memory, comparer), ContainsAll(readOnlyMemory, readOnlyMemory)
The corresponding overloads do exist in src/TestFramework/TestFramework/Assertions/Assert.Contains.cs, Assert.DoesNotContain.cs, Assert.ContainsAll.cs, and Assert.DoesNotContainAll.cs — this is a test-coverage gap, not a missing-API gap.
Strengths
- Every other Span/Memory overload family in the same test (
AreAllDistinct,AreAllNotNull,AreAllOfType,AreEquivalent,AreSequenceEqual,HasCount,IsEmpty,IsNotEmpty,ContainsSingle) exercises both the comparer and no-comparer, and both value and predicate shapes, across all four span/memory types. - The method-family-level guard (
VerifyEveryPublicAssertMethodFamilyHasAConsumerCall) correctly prevents an entirely newAssertfamily from shipping without any consumer call.
Areas for Improvement
- ⚠️ Medium —
Contains/DoesNotContain/ContainsAll/DoesNotContainAllsystematically skip half of their Span/Memory × comparer combinations inSpanAndMemoryCalls, contrary to the pattern used for every sibling method family in the same test and contrary to the file's stated purpose.
🤖 Suggested Improvement Tasks
Task 1: Add missing Contains/DoesNotContain Span/Memory combinations
Priority: Medium
Estimated Effort: Small
In SpanAndMemoryCalls, add calls for Assert.Contains(1, span, comparer), Assert.Contains(1, memory, comparer), Assert.Contains(predicate, span) (or readOnlySpan), Assert.Contains(predicate, readOnlyMemory), and the equivalent DoesNotContain shapes, mirroring the existing pattern used for AreAllDistinct/ContainsSingle in the same method (all four collection types × both comparer/no-comparer × value/predicate exercised at least once).
Relevant file: test/IntegrationTests/MSTest.Acceptance.IntegrationTests/AssertSourceCompatibilityTests.cs
Task 2: Add missing ContainsAll/DoesNotContainAll Span/Memory combinations
Priority: Medium
Estimated Effort: Small
Add Assert.ContainsAll(span, span, comparer), Assert.ContainsAll(readOnlySpan, readOnlySpan) (no comparer), Assert.ContainsAll(memory, memory, comparer), Assert.ContainsAll(readOnlyMemory, readOnlyMemory) (no comparer), and the equivalent DoesNotContainAll calls, so all four collection types are exercised with and without a comparer.
Relevant file: test/IntegrationTests/MSTest.Acceptance.IntegrationTests/AssertSourceCompatibilityTests.cs
Task 3: Add a lightweight combinatorial coverage assertion
Priority: Low
Estimated Effort: Medium
Consider a small reflection-based helper (scoped to just Contains/DoesNotContain/ContainsAll/DoesNotContainAll, since these are the families with the most overload combinations) that asserts every distinct (collectionType, hasComparer, isPredicate) shape found in the public API surface has at least one matching call in ConsumerSource. This would make the gap self-detecting instead of relying on manual review, without expanding VerifyEveryPublicAssertMethodFamilyHasAConsumerCall's scope beyond family names.
Relevant file: test/IntegrationTests/MSTest.Acceptance.IntegrationTests/AssertSourceCompatibilityTests.cs
📊 Historical Context
Previous Focus Areas
| Date | Focus Area | Type |
|---|---|---|
| 2026-09-19 | opentelemetry-platformservice-metrics-and-tracestate-coverage-gap | Custom |
| 2026-09-18 | msbuild-namespace-sanitization-coverage-gap | Custom |
| 2026-09-16 | extension-self-registration-acceptance-coverage | Custom |
| 2026-09-12 | noncooperative-parent-process-listener-untested | Custom |
| 2026-09-10 | ci-run-summary-provenance-guard-coverage-gap | Custom |
🎯 Recommendations
Immediate Actions (This Week)
- Add the missing
Contains/DoesNotContaincombinations toSpanAndMemoryCalls— Priority: Medium
Short-term Actions (This Month)
- Add the missing
ContainsAll/DoesNotContainAllcombinations — Priority: Medium - Evaluate a reflection-based combinatorial coverage check for these four families — Priority: Low
Next analysis: 2026-09-25 — Focus area selected based on diversity algorithm
🤖 Automated content by GitHub Copilot. Generated by the Repository Quality Improver workflow. · copilot · auto · 211.8 AIC · ⌖ 8 AIC · ⊞ 17.2K · [◷]( · ◷)
Add this agentic workflow to your repo
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/repository-quality-improver.md@main
- expires on Sep 26, 2026, 10:36 PM UTC
- Dominant language
- C#
- Stars
- 1k
- Forks
- 312
- Avg merge
- 8h 14m
- Merged PRs (30d)
- 497
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/testfx
-
agentic-workflows area/performance type/automation
Difficulty 2/5 1-3 hours Newbie friendliness 15/100
-
[file-diet] Refactor AzureDevOpsTestResultsPublisher.cs (578 lines) into focused partial-class files Opentype/automation type/tech-debt
-
area/mtp needs/triage
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
area/winui
-
type/automation type/tech-debt
Difficulty 5/5 Over a week Newbie friendliness 10/100
All issues in microsoft/testfx
Similar issues
-
untriaged
Difficulty 1/5 Under an hour Newbie friendliness 88/100
dotnet/dotnet-api-docs#13095 ·
-
area-deployment area-integrations triage:bot-seen
Difficulty 2/5 Half a day Newbie friendliness 86/100
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 90/100
newrelic/newrelic-dotnet-agent#3850 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
LuckyPennySoftware/AutoMapper#4660 ·
-
clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:no-new-fix-pr issue-rating: 🌊 off-meta tidepool P2
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
openclaw/openclaw-windows-packaging#116 · 1 comment · 1 reaction ·