[quality-improver] CiRunSummaryAggregateReader.ValidateModule provenance cross-check guards are untested on the throwing path
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 70/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- csharp
- Domain
- testing-qa
Research direction
The issue is about adding unit tests for the provenance guards in CiRunSummaryAggregateReader.ValidateModule. Start by reading the existing test file at test/UnitTests/Microsoft.Testing.Extensions.UnitTests/CiRunSummaryAggregationTests.cs and the helper method CreateInput. Then, modify the helper to accept optional parameters for mismatched provenance values. Write new tests that pass mismatched InputArtifact values for ProducingTestModule, TargetFramework, Architecture, and ExecutionId/AttemptNumber, and assert that FormatException is thrown with the expected message. Run the tests to ensure they pass and cover the previously untested throwing paths.
Written by the indexing model from the issue text.
Description
🎯 Repository Quality Improvement Report — CI Run Summary Provenance Guard Coverage Gap
Analysis Date: 2026-09-23
Focus Area: ci-run-summary-provenance-guard-coverage-gap
Strategy Type: Custom
Executive Summary
Microsoft.Testing.Extensions.SharedExtensionHelpers recently gained a new CiRunSummaryAggregation/CiRunSummaryAggregateReader pair that aggregates per-module CI run summary fragments (coverage, flaky tests, history, dependencies) shared by both the AzureDevOpsReport and GitHubActionsReport extensions. CiRunSummaryAggregateReader.ValidateModule includes four distinct "provenance" guards that cross-check a deserialized fragment's ModulePath, TargetFramework, Architecture, and ExecutionId/AttemptNumber against the InputArtifact metadata supplied by the platform's artifact post-processing pipeline, throwing FormatException on any mismatch. These guards exist specifically to catch fragments that were mixed up between modules/frameworks/architectures/retry attempts in CI — exactly the kind of defect that is silent until multi-module or multi-attempt runs corrupt an aggregate report.
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/CiRunSummaryAggregationTests.cs is a substantial 972-line, 23-test suite that already covers schema-version mismatches, duplicate identities, null bounded collections, and null history/dependency entries — but every test constructs its InputArtifact via the CreateInput helper, which always derives producingTestModule, targetFramework, architecture, and executionId directly from the same module object being validated. As a result the four provenance-mismatch branches (lines ~183–192 of CiRunSummaryAggregateReader.cs) are never exercised on their throwing path — a regression that silently disabled cross-module corruption detection (e.g. reverting a != to ==, or dropping a branch) would compile and pass the entire existing suite.
The task below adds targeted tests that pass a mismatched InputArtifact for each of the four provenance dimensions plus the RetryAttempts attempt-number variant, asserting the specific FormatException message for each.
Full Analysis Report
Focus Area: CI Run Summary Provenance Guard Coverage Gap
Current State Assessment
Metrics Collected:
| Metric | Value | Status |
|---|---|---|
CiRunSummaryAggregateReader.cs size |
248 lines | — |
| Existing test file size / test count | 972 lines / 23 [TestMethod]s |
✅ generally strong |
Provenance guards in ValidateModule |
4 (ProducingTestModule, TargetFramework, Architecture, ExecutionId/AttemptNumber) |
❌ 0 tested on throwing path |
CreateInput helper derives fields from module under test |
Always | ❌ guarantees provenance always matches |
Related sibling files (NamedPipeServerFactory.cs, PipeNameEnvironmentVariableProviderBase.cs, CiRunSummaryFragmentIo.cs, ReportFileNameHelper.cs) |
0 dedicated unit tests each | ⚠️ noted, out of scope for this task |
Findings
Strengths
- The overall
CiRunSummaryAggregationtest suite is unusually thorough: schema-version checks, malformed JSON, duplicate identities, bounded-collection truncation ordering, and coverage aggregation are all covered with clear Arrange/Act/Assert structure and descriptive test names. ValidateModule's validation logic itself is well-structured and defensive (checked arithmetic, explicit NaN/Infinity guards, bounded collection caps).
Areas for Improvement
- ⚠️ Medium severity: The four provenance cross-check guards in
ValidateModule(src/Platform/SharedExtensionHelpers/CiRunSummaryAggregateReader.cs, lines ~163–192) have no test coverage for their throwing path.CreateInput(test helper, line ~851) always builds anInputArtifactwhoseproducingTestModule/targetFramework/architecture/executionIdmatch the module being validated, so a regression that weakens or removes any of these fourifchecks would not be caught by the existing 23 tests. - ⚠️ Low-medium severity (noted, not actioned):
NamedPipeServerFactory.cs,PipeNameEnvironmentVariableProviderBase.cs,CiRunSummaryFragmentIo.cs, andReportFileNameHelper.csin the sameSharedExtensionHelpersproject also have zero dedicated unit tests, but their logic is comparatively thin (pipe naming/env var plumbing, file read/write wrappers) and lower risk than the provenance guards, which protect data integrity of CI reporting across concurrent/retried test runs.
🤖 Suggested Improvement Tasks
Task 1: Add tests for ValidateModule's ProducingTestModule provenance mismatch
Priority: Medium
Estimated Effort: Small
In test/UnitTests/Microsoft.Testing.Extensions.UnitTests/CiRunSummaryAggregationTests.cs, add a test that writes a valid fragment for a module (e.g. via CreateModule/WriteFragmentAsync), then calls CiRunSummaryAggregation.ReadAndAggregate with an InputArtifact whose producingTestModule argument is a different path than module.ModulePath (while input.Path still points at the correct fragment file). Assert Assert.ThrowsExactly<FormatException>(...) and, ideally, assert on the exception message containing "provenance does not match" to pin the specific guard. This exercises src/Platform/SharedExtensionHelpers/CiRunSummaryAggregateReader.cs's if (input.ProducingTestModule is not null && !PathsEqual(...)) branch.
Task 2: Add tests for TargetFramework and Architecture provenance mismatch
Priority: Medium
Estimated Effort: Small
Add two tests (or one [DataRow]-parameterized test) analogous to Task 1, but instead pass an InputArtifact with a targetFramework or architecture value that differs from the fragment's module. Both branches are in ValidateModule immediately after the ProducingTestModule check. Consider extracting a small helper overload of CreateInput that accepts explicit override values for producingTestModule, targetFramework, architecture, and executionId instead of always deriving them from module, to keep the new tests concise and to make future provenance tests easy to add.
Task 3: Add tests for ExecutionId/AttemptNumber provenance mismatch in both post-processing modes
Priority: Medium
Estimated Effort: Small
Add tests covering both branches of the ternary in the ExecutionId guard:
ArtifactPostProcessingMode.RetryAttempts: pass aninput.ExecutionIdthat either failsint.TryParseor parses to a value different frommodule.AttemptNumber.- Default mode: pass an
input.ExecutionIdstring that differs frommodule.ExecutionId.
Both should throw FormatException with the execution-provenance message. This directly complements the existing GitHubAggregate_ForRetryAttempts_UsesInitialAttemptCoverage test, which exercises the happy path of RetryAttempts mode but not its mismatch guard.
Task 4: Extend the shared CreateInput test helper to support mismatched provenance construction
Priority: Low
Estimated Effort: Small
Refactor CreateInput(string path, CiRunSummaryModule module) (line ~851) to add optional parameters (producingTestModule, targetFramework, architecture, executionId) defaulting to the module's own values, so Tasks 1–3 can construct mismatched InputArtifacts without duplicating the existing helper's boilerplate. Keep the existing call sites unchanged by relying on the new parameters' defaults.
📊 Historical Context
Previous Focus Areas
| Date | Focus Area | Type |
|---|---|---|
| 2026-09-21 | extension-self-registration-acceptance-coverage | Custom |
| 2026-09-22 | noncooperative-parent-process-listener-untested | Custom |
| 2026-09-23 | ci-run-summary-provenance-guard-coverage-gap | Custom |
🎯 Recommendations
Immediate Actions (This Week)
- Add the four provenance-mismatch tests (Tasks 1–3) — Priority: Medium
Short-term Actions (This Month)
- Consider adding basic unit tests for
NamedPipeServerFactory,PipeNameEnvironmentVariableProviderBase,CiRunSummaryFragmentIo, andReportFileNameHelperinSharedExtensionHelpers— Priority: Low
Next analysis: 2026-09-24 — Focus area selected based on diversity algorithm
🤖 Automated content by GitHub Copilot. Generated by the Repository Quality Improver workflow. · copilot · auto · 113.4 AIC · ⌖ 6.87 AIC · ⊞ 16.5K · [◷]( · ◷)
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 25, 2026, 10:27 PM UTC
- Dominant language
- C#
- Stars
- 1k
- Forks
- 314
- Avg merge
- 8h 40m
- Merged PRs (30d)
- 435
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing 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
-
[test-improver] Add unit tests for ConsoleTestExecutionFilterFactoryPossibly taken @Evangelink claimed this 1 day ago. Openarea/mtp needs/triage
microsoft/testfx#11873 · 1 reaction · 2 assignees ·
Maintainers usually reply within 1 day
-
area/analyzers needs/triage
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Maintainers usually reply within 1 day
-
[test-improver] Add unit tests for RetryAttemptPropertyExtensions.IsSupersededRetryAttemptPossibly taken @Evangelink claimed this 1 day ago. Openarea/mtp-retry needs/triage
Difficulty 2/5 1-3 hours Newbie friendliness 25/100
microsoft/testfx#11869 · 1 reaction · 2 assignees ·
Maintainers usually reply within 1 day
-
area/server-mode-jsonrpc
Difficulty 5/5 Over a week Newbie friendliness 8/100
Maintainers usually reply within 1 day
-
type/automation type/test-gap
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Maintainers usually reply within 1 day
All issues in microsoft/testfx
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
Maintainers usually reply within 1 day
-
question
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
代理地址输入框的示例提示容易被误认为已配置代理Possibly taken @jay23606 claimed this today. Openbug
Difficulty 1/5 1-3 hours Newbie friendliness 78/100
kookxiang/jellyfin-plugin-bangumi#297 ·
Maintainers usually reply within 1 day
-
A numeric literal is parsed in the host's culture, so 1.5 is 15 in a made EXE on a comma-decimal OSOpenbug interpreter silently-wrong small
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day