Skip to content

test: clear all 504 xunit analyzer warnings - #588

Merged
jeremydmiller merged 1 commit into
mainfrom
fix/582-xunit-analyzer-warnings
Jul 29, 2026
Merged

test: clear all 504 xunit analyzer warnings#588
jeremydmiller merged 1 commit into
mainfrom
fix/582-xunit-analyzer-warnings

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #582

The 504 is really 129

Parsing the build log by unique (rule, file, line, col) shows the 504 warnings come from 129 distinct source locations — the rest is per-TFM (net9.0/net10.0) and per-node duplication. That changed the plan: 129 is small enough to fix every one by hand, so nothing is suppressed wholesale and there is no blanket NoWarn.

Rule Locations What was done
xUnit1051 89 TestContext.Current.CancellationToken threaded through
xUnit1013 26 Triaged individually — see below
xUnit1012 8 Theory parameters made nullable
xUnit1031 4 Two sync tests converted to async
xUnit1026 2 One was a real gap — see below

xUnit1013 was worth the hand triage

The issue predicted actual bugs could hide here. Two did:

ProjectionRebuildSelectionTests implemented IProjectionHost on itself. Interface members have to be public, so all four read as un-attributed test methods — the exact self-stub shape that broke all 16 SliceGroupTests in #577, where a self-stubbed IAsyncDisposable.DisposeAsync ran as test lifecycle instead of as a stub. Extracted to a RecordingProjectionHost class, which removes the warnings and the footgun together.

RetryBlockTests.retry_within_threshold was a commented-out //[Fact] — a test that had silently ceased to exist. Now [Fact(Skip = "Unreliable in CI - timing sensitive under load")], so it shows up as skipped on every run instead of vanishing. This is the one intentional baseline change: CoreTests reports 476 total, 475 passed, 1 skipped.

The rest were benign but fixed properly rather than suppressed:

  • Documentation samples on test classes (ResourceHostExtensionsTests, UsingSourceWriter) moved to sibling non-test classes. Deliberately not made private — sample_programmatically_control_resources includes its own method signature inside the #region, so reducing visibility would have changed published docs. Moving keeps the snippet text byte-for-byte identical.
  • Reflection targets (EventExtensionsTests ×2, event_parameter_naming_convention) made private, with BindingFlags.Instance | BindingFlags.NonPublic added where the lookup needed it. The expression-tree lookups bind private methods fine from inside the class.

xUnit1026 found a test asserting nothing

AggregateVersioningTests.set_version_single_stream_on_internal ran ten InlineData cases and had an empty body after TrySetVersion — no assertion at all. expected was unused because the assertion was never written. It only ever proved TrySetVersion() doesn't throw.

 versioning.TrySetVersion(aggregate, e);
-
-
+ versioning.GetVersion(aggregate).ShouldBe(expected);

It passes — the behavior was right, the test just wasn't checking it.

xUnit1031

StoreUriStampingObserverTests had two sync tests calling .Wait() on tasks. Both are now async Task with await.

xUnit1051 — one documented exception

All 89 got the token threaded through, except one where the analyzer's advice is wrong:

// SetCanceled(CancellationToken) records which token DID cancel the task; it does not
// observe one. Passing the test's (uncancelled) token would assert something false.
#pragma warning disable xUnit1051
tcs.SetCanceled();
#pragma warning restore xUnit1051

Verification

Clean rebuild:  504 xunit warnings  ->  0
CS warnings:    1920                ->  1920   (unchanged)

The CS count is the check that matters — no warnings were traded for others, and no nullable-annotation changes leaked new ones.

Suite Result #581 baseline
CoreTests 475 passed, 1 skipped 475
CodegenTests 419 419
CommandLineTests 295 295
EventTests 648 648
EventStoreTests 72 72
CodegenTests.FSharp 1 1
JasperFx.SourceGenerator.Tests 19 19
JasperFx.Events.SourceGenerator.Tests 26 26

CoreTests and EventTests also verified green on net10.0.

Not included

I did not add WarningsAsErrors for these rules to stop them creeping back — that changes your build's failure behavior and wasn't part of the ask. Happy to add it if you want the guard.

🤖 Generated with Claude Code

A clean rebuild emitted 504 xunit analyzer warnings, burying genuinely
interesting output. That 504 is 129 unique source locations - the rest is
per-TFM and per-node duplication - which made hand-fixing every one of
them practical, so nothing is suppressed wholesale.

xUnit1013 (26 locations) - triaged by hand, as the issue asked, and it
was worth it:

  - ProjectionRebuildSelectionTests implemented IProjectionHost on itself.
    Interface members must be public, so every one read as an
    un-attributed test method. That is the same self-stub shape that broke
    all 16 SliceGroupTests in #577. Extracted to RecordingProjectionHost.
  - RetryBlockTests.retry_within_threshold was a commented-out //[Fact].
    Now [Fact(Skip = "Unreliable in CI")] so it is visibly skipped rather
    than silently nonexistent. CoreTests totals 476 with 1 skipped.
  - Documentation samples on test classes (ResourceHostExtensionsTests,
    UsingSourceWriter) moved to sibling non-test classes, which keeps the
    #region snippet text byte-for-byte identical - one of those regions
    includes its method signature.
  - Reflection targets (EventExtensionsTests x2,
    event_parameter_naming_convention) made private, with BindingFlags
    added where the lookup needed it.

xUnit1026 (2) - one was a real gap. AggregateVersioningTests
set_version_single_stream_on_internal ran ten InlineData cases and
asserted nothing at all; 'expected' was unused because the assertion was
missing entirely. It only ever proved TrySetVersion() doesn't throw. Now
asserts GetVersion() == expected, and passes.

xUnit1031 (4) - StoreUriStampingObserverTests had two sync tests calling
.Wait() on tasks. Both are now async/await.

xUnit1012 (8) - theory parameters that take null are now nullable.

xUnit1051 (89) - TestContext.Current.CancellationToken threaded through.
One documented #pragma exception in TaskExtensionsTests: SetCanceled(ct)
records which token DID cancel a task rather than observing one, so
passing the test's uncancelled token would assert something false.

Verified: 504 -> 0 xunit warnings on a clean rebuild, and the CS warning
count is unchanged at exactly 1920, so nothing was traded away.

Test counts against the #581 baseline: CoreTests 475+1 skipped,
CodegenTests 419, CommandLineTests 295, EventTests 648, EventStoreTests
72, CodegenTests.FSharp 1, JasperFx.SourceGenerator.Tests 19,
JasperFx.Events.SourceGenerator.Tests 26. CoreTests and EventTests also
run green on net10.0.

Closes #582

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller merged commit 6cca047 into main Jul 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

504 xunit analyzer warnings across the test suites

1 participant