🎯 Repository Quality Improvement Report — GlobalTestInitialize/Cleanup Implementation Gaps
Analysis Date: 2026-07-06 | Strategy: Custom
Executive Summary
The GlobalTestInitialize and GlobalTestCleanup attributes have four concrete implementation gaps. Most critically, GlobalTestInitializeAttribute.cs states "TimeoutAttribute isn't supported on methods with this attribute" — directly contradicted by TryGetTimeoutInfo in TypeCache.ClassInfo.cs (which reads [Timeout] from the method first) and by acceptance test GlobalTestInitialize_WhenTimeoutExpires_GlobalTestInitializeIsCanceled_AttributeTakesPrecedence.
Structurally, global fixtures share FixtureKind.TestInitialize / FixtureKind.TestCleanup enum values (and therefore <TestInitializeTimeout> / <TestCleanupTimeout> RunSettings keys) with per-test methods. There is no way to set a timeout specifically for global fixtures without also affecting all [TestInitialize] / [TestCleanup] methods.
On the analyzer side, MSTEST0050 uses DiagnosticSeverity.Error while all six peer fixture rules (MSTEST0008–0013) use Warning, and the description text in Resources.resx incorrectly says static classes are invalid — contradicted by the WhenGlobalTestInitializeInStaticClass_NoDiagnostic test.
Full Analysis Report
Metrics:
| Metric |
Value |
Status |
| Peer fixture rules severity (MSTEST0008–0013) |
Warning |
✅ |
| MSTEST0050 severity |
Error |
❌ inconsistent |
GlobalTestInitializeAttribute doc: "[Timeout] not supported" |
Present |
❌ factually wrong |
TryGetTimeoutInfo reads [Timeout] on GlobalTestInitialize |
Yes |
✅ |
Acceptance test for [Timeout] attribute on GlobalTestInitialize |
Exists |
✅ |
Dedicated FixtureKind values for Global fixtures |
None |
⚠️ hidden coupling |
| MSTEST0050 description: "class shouldn't be static" |
In Resources.resx |
❌ contradicts analyzer test |
Findings:
-
[HIGH] Incorrect [Timeout] documentation — GlobalTestInitializeAttribute.cs claims [Timeout] is unsupported. Runtime (TypeCache.AssemblyInfo.cs line 97) calls TryGetTimeoutInfo(methodInfo, FixtureKind.TestInitialize), which (in TypeCache.ClassInfo.cs:197) first checks for [Timeout] on the method. Acceptance test GlobalTestInitialize_WhenTimeoutExpires_GlobalTestInitializeIsCanceled_AttributeTakesPrecedence verifies this end-to-end.
-
[HIGH] MSTEST0050 severity mismatch — All 6 peer rules use Warning; MSTEST0050 uses Error. Hard build-break for GlobalTestInitialize signature errors while equivalent ClassInitialize mistakes only warn.
-
[MEDIUM] No dedicated timeout config for global fixtures — FixtureKind has no GlobalTestInitialize/GlobalTestCleanup values. TimeoutWhenExpiresTests.InfoByKind confirms: "globalTestInit" → "TestInitializeTimeout". Setting <TestInitializeTimeout> silently also controls GlobalTestInitialize.
-
[MEDIUM] Description vs behavior inconsistency — Resources.resx description: "The class shouldn't be 'static'". Analyzer test WhenGlobalTestInitializeInStaticClass_NoDiagnostic passes [TestClass] public static class as valid.
-
[LOW] Single rule for two fixtures — ClassInitialize/ClassCleanup have separate MSTEST0010/0011. MSTEST0050 collapses both global fixtures into one rule and one message that doesn't indicate which attribute is wrong.
🤖 Suggested Improvement Tasks
Task 1: Correct GlobalTestInitializeAttribute docs for [Timeout]
Priority: High | Effort: Small
Remove the inaccurate sentence "In addition, TimeoutAttribute isn't supported on methods with this attribute" from GlobalTestInitializeAttribute.cs and replace it with documentation confirming [Timeout] IS supported (method-level attribute takes precedence over RunSettings global timeout, same as other fixture types).
File: src/TestFramework/TestFramework/Attributes/Lifecycle/Initialization/GlobalTestInitializeAttribute.cs
Task 2: Change MSTEST0050 severity from Error to Warning
Priority: High | Effort: Small
In GlobalTestFixtureShouldBeValidAnalyzer.cs, change DiagnosticSeverity.Error to DiagnosticSeverity.Warning to match MSTEST0008–0013. Update expected severity in GlobalTestFixtureShouldBeValidAnalyzerTests.cs.
File: src/Analyzers/MSTest.Analyzers/GlobalTestFixtureShouldBeValidAnalyzer.cs
Task 3: Add dedicated GlobalTestInitialize / GlobalTestCleanup entries to FixtureKind and MSTestSettings
Priority: Medium | Effort: Medium
- Add
GlobalTestInitialize and GlobalTestCleanup to FixtureKind enum
- Add
GlobalTestInitializeTimeout / GlobalTestCleanupTimeout to MSTestSettings, parsed from both RunSettings XML (<GlobalTestInitializeTimeout>) and testconfig.json (timeout:globalTestInitialize)
- Update
TimeoutInfo.FromFixtureSettings switch to handle the new values (fall back to TestInitializeTimeout/TestCleanupTimeout when not set, for backward compat)
- Update
TypeCache.AssemblyInfo.cs to use the new FixtureKind values
- Update
TimeoutWhenExpiresTests.InfoByKind and add acceptance tests for the new settings
Files: FixtureKind.cs, TimeoutInfo.cs, MSTestSettings.cs, TypeCache.AssemblyInfo.cs, TimeoutWhenExpiresTests.cs
Task 4: Fix MSTEST0050 description — remove incorrect static-class restriction
Priority: Medium | Effort: Small
Remove the bullet "-The class shouldn't be 'static'" from GlobalTestFixtureShouldBeValidDescription in Resources.resx. The analyzer's own WhenGlobalTestInitializeInStaticClass_NoDiagnostic test confirms [TestClass] public static class is valid. Regenerate XLF files via dotnet msbuild src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj /t:UpdateXlf after editing.
File: src/Analyzers/MSTest.Analyzers/Resources.resx
Task 5: Split MSTEST0050 into separate GlobalTestInitialize and GlobalTestCleanup rules
Priority: Low | Effort: Medium
All peer fixture types have separate rules (MSTEST0008/0009, 0010/0011, 0012/0013). MSTEST0050 collapses both into one. Splitting into MSTEST0050 (GlobalTestInitializeShouldBeValid) and a new ID (GlobalTestCleanupShouldBeValid) enables distinct FixtureParameterMode settings if requirements diverge and produces more targeted error messages. MSTEST0050 stays for Initialize; the new rule targets Cleanup. Update DiagnosticIds.cs, Resources.resx, analyzer file(s), and unit tests.
📊 Previous Focus Areas
| Date |
Focus Area |
| 2026-07-03 |
test-context-api-surface-consistency |
| 2026-07-02 |
cross-component-diagnostic-metadata-consistency |
| 2026-07-01 |
preprocessor-symbol-hygiene |
| 2026-06-30 |
mstest-sdk-runner-target-correctness |
| 2026-06-29 |
async-exception-assertion-gaps |
Next analysis: 2026-07-07
🤖 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 Repository Quality Improver workflow. · 172.6 AIC · ⌖ 10.3 AIC · ⊞ 10.2K · [◷]( · ◷)
Add this agentic workflows to your repo
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/repository-quality-improver.md@main
🎯 Repository Quality Improvement Report — GlobalTestInitialize/Cleanup Implementation Gaps
Analysis Date: 2026-07-06 | Strategy: Custom
Executive Summary
The
GlobalTestInitializeandGlobalTestCleanupattributes have four concrete implementation gaps. Most critically,GlobalTestInitializeAttribute.csstates "TimeoutAttribute isn't supported on methods with this attribute" — directly contradicted byTryGetTimeoutInfoinTypeCache.ClassInfo.cs(which reads[Timeout]from the method first) and by acceptance testGlobalTestInitialize_WhenTimeoutExpires_GlobalTestInitializeIsCanceled_AttributeTakesPrecedence.Structurally, global fixtures share
FixtureKind.TestInitialize/FixtureKind.TestCleanupenum values (and therefore<TestInitializeTimeout>/<TestCleanupTimeout>RunSettings keys) with per-test methods. There is no way to set a timeout specifically for global fixtures without also affecting all[TestInitialize]/[TestCleanup]methods.On the analyzer side, MSTEST0050 uses
DiagnosticSeverity.Errorwhile all six peer fixture rules (MSTEST0008–0013) useWarning, and the description text inResources.resxincorrectly says static classes are invalid — contradicted by theWhenGlobalTestInitializeInStaticClass_NoDiagnostictest.Full Analysis Report
Metrics:
WarningErrorGlobalTestInitializeAttributedoc: "[Timeout] not supported"TryGetTimeoutInforeads[Timeout]on GlobalTestInitialize[Timeout]attribute on GlobalTestInitializeFixtureKindvalues for Global fixturesResources.resxFindings:
[HIGH] Incorrect
[Timeout]documentation —GlobalTestInitializeAttribute.csclaims[Timeout]is unsupported. Runtime (TypeCache.AssemblyInfo.csline 97) callsTryGetTimeoutInfo(methodInfo, FixtureKind.TestInitialize), which (inTypeCache.ClassInfo.cs:197) first checks for[Timeout]on the method. Acceptance testGlobalTestInitialize_WhenTimeoutExpires_GlobalTestInitializeIsCanceled_AttributeTakesPrecedenceverifies this end-to-end.[HIGH] MSTEST0050 severity mismatch — All 6 peer rules use
Warning; MSTEST0050 usesError. Hard build-break for GlobalTestInitialize signature errors while equivalent ClassInitialize mistakes only warn.[MEDIUM] No dedicated timeout config for global fixtures —
FixtureKindhas noGlobalTestInitialize/GlobalTestCleanupvalues.TimeoutWhenExpiresTests.InfoByKindconfirms:"globalTestInit" → "TestInitializeTimeout". Setting<TestInitializeTimeout>silently also controls GlobalTestInitialize.[MEDIUM] Description vs behavior inconsistency —
Resources.resxdescription: "The class shouldn't be 'static'". Analyzer testWhenGlobalTestInitializeInStaticClass_NoDiagnosticpasses[TestClass] public static classas valid.[LOW] Single rule for two fixtures — ClassInitialize/ClassCleanup have separate MSTEST0010/0011. MSTEST0050 collapses both global fixtures into one rule and one message that doesn't indicate which attribute is wrong.
🤖 Suggested Improvement Tasks
Task 1: Correct
GlobalTestInitializeAttributedocs for[Timeout]Priority: High | Effort: Small
Remove the inaccurate sentence "In addition, TimeoutAttribute isn't supported on methods with this attribute" from
GlobalTestInitializeAttribute.csand replace it with documentation confirming[Timeout]IS supported (method-level attribute takes precedence over RunSettings global timeout, same as other fixture types).File:
src/TestFramework/TestFramework/Attributes/Lifecycle/Initialization/GlobalTestInitializeAttribute.csTask 2: Change MSTEST0050 severity from
ErrortoWarningPriority: High | Effort: Small
In
GlobalTestFixtureShouldBeValidAnalyzer.cs, changeDiagnosticSeverity.ErrortoDiagnosticSeverity.Warningto match MSTEST0008–0013. Update expected severity inGlobalTestFixtureShouldBeValidAnalyzerTests.cs.File:
src/Analyzers/MSTest.Analyzers/GlobalTestFixtureShouldBeValidAnalyzer.csTask 3: Add dedicated
GlobalTestInitialize/GlobalTestCleanupentries toFixtureKindandMSTestSettingsPriority: Medium | Effort: Medium
GlobalTestInitializeandGlobalTestCleanuptoFixtureKindenumGlobalTestInitializeTimeout/GlobalTestCleanupTimeouttoMSTestSettings, parsed from both RunSettings XML (<GlobalTestInitializeTimeout>) andtestconfig.json(timeout:globalTestInitialize)TimeoutInfo.FromFixtureSettingsswitch to handle the new values (fall back toTestInitializeTimeout/TestCleanupTimeoutwhen not set, for backward compat)TypeCache.AssemblyInfo.csto use the newFixtureKindvaluesTimeoutWhenExpiresTests.InfoByKindand add acceptance tests for the new settingsFiles:
FixtureKind.cs,TimeoutInfo.cs,MSTestSettings.cs,TypeCache.AssemblyInfo.cs,TimeoutWhenExpiresTests.csTask 4: Fix MSTEST0050 description — remove incorrect static-class restriction
Priority: Medium | Effort: Small
Remove the bullet "-The class shouldn't be 'static'" from
GlobalTestFixtureShouldBeValidDescriptioninResources.resx. The analyzer's ownWhenGlobalTestInitializeInStaticClass_NoDiagnostictest confirms[TestClass] public static classis valid. Regenerate XLF files viadotnet msbuild src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj /t:UpdateXlfafter editing.File:
src/Analyzers/MSTest.Analyzers/Resources.resxTask 5: Split MSTEST0050 into separate GlobalTestInitialize and GlobalTestCleanup rules
Priority: Low | Effort: Medium
All peer fixture types have separate rules (MSTEST0008/0009, 0010/0011, 0012/0013). MSTEST0050 collapses both into one. Splitting into MSTEST0050 (
GlobalTestInitializeShouldBeValid) and a new ID (GlobalTestCleanupShouldBeValid) enables distinctFixtureParameterModesettings if requirements diverge and produces more targeted error messages. MSTEST0050 stays for Initialize; the new rule targets Cleanup. UpdateDiagnosticIds.cs,Resources.resx, analyzer file(s), and unit tests.📊 Previous Focus Areas
Next analysis: 2026-07-07
Add this agentic workflows to your repo
To install this agentic workflow, run