Skip to content

feat: assertions on a Task or ValueTask, and CMTK0003 reports one left unawaited - #95

Merged
CaffeinatedCoder merged 2 commits into
release/2.3.0from
feat/async-assertions
Oct 28, 2026
Merged

CaffeinatedCoder merged 2 commits into
release/2.3.0from
feat/async-assertions

Conversation

@CaffeinatedCoder

Copy link
Copy Markdown
Owner

Closes #87

Problem

The Testing assertions worked only on a value the test already held, so a test of an async method wrote (await service.Find(id)).ShouldBeSuccess(). An async form adds a trap of its own. It fails the test only through the task it returns, so service.FindAsync(id).ShouldBeSome(); left without await passes whatever the task holds. C# warns about that only inside an async method.

Change

  • Testing: every one of the 16 assertions has a Task and a ValueTask form, placed next to its synchronous form. Each awaits the task and then answers as the synchronous form does, with the same content back and the same message. A task that throws propagates its own exception. A null task is refused, naming the parameter. Every form returns Task, as the core package's asynchronous members do.
  • CMTK0003: reports a statement that leaves such an assertion without await, including through ConfigureAwait and in a lambda's body. The rule knows the assertions by the Testing assembly's identity, as it already knows .Generators. So a consumer's own extension on a pending result is not reported. Every call it reports is new in 2.3, so the Error severity breaks no build that worked before.
  • Docs: the Testing README (a compiled sample and two bullets), CMTK0003 in the Analyzers README, docs/testing.md, the changelog. The roadmap item is removed.
  • Probe corpus: the C20 seed whichever-of-its-types is regenerated against the new FaultAssertions.cs.

Tests

  • AsyncAssertionTests:
    • Every assertion compared with its synchronous form over a pending Task and a pending ValueTask, on inputs it passes and fails.
    • A completeness test over the public surface: each of the 16 assertions has exactly one form of each kind, returning Task or Task<T> of what the synchronous form returns.
    • A faulted task, a cancelled task, and a null task.
  • IgnoredOutcomeAnalyzerTests, against the real Testing assembly:
    • Dropped assertions are reported: in a method that isn't async and in one that is, through ConfigureAwait, and in a lambda.
    • An assertion that is awaited, held in a variable, returned or discarded is silent.
    • The same shape from another assembly is silent.
  • Seeded and caught:
    • A Task form that doesn't assert.
    • A null task no longer refused by name.
    • A faulted task wrapped in an assertion failure.
    • The new report removed.
    • The rule widened to any assembly.
  • Full suite: 18,236 passed. The Testing and core packages pack with package validation against 2.2.0.

🤖 Generated with Claude Code

…t unawaited

Every assertion of CodoMetis.TypeKit.Testing has a form on a Task and on a
ValueTask of what it checks, beside its synchronous form: it awaits the task
and answers as the synchronous form does, the same content back and the same
message. A task that faults propagates its own exception, and a null task is
refused by the parameter's name.

An assertion on a task fails the test only through the task it returns, so
`service.FindAsync(id).ShouldBeSome();` without await passed whatever the
task held, and C# warns only in an async method. CMTK0003 reports such a
statement, through ConfigureAwait and in a lambda's body too. It knows the
assertions by the Testing assembly's identity, as it knows the Generators
assembly, so a consumer's own extension on a pending result stays silent:
every reported call is new in 2.3, and no build that worked before breaks.

The C20 seed whichever-of-its-types is regenerated against the new
FaultAssertions.cs.

Closes #87

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CaffeinatedCoder CaffeinatedCoder added this to the 2.3.0 milestone Oct 28, 2026
@CaffeinatedCoder CaffeinatedCoder added enhancement New feature or request package/analyzers Affects CodoMetis.TypeKit.Analyzers package/testing Affects CodoMetis.TypeKit.Testing area/option-result Option, Result and their extensions labels Oct 28, 2026
The changelog keeps every entry and the roadmap drops both items; the
prober seed this branch edited is deleted, as #108 retired the prober.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CaffeinatedCoder
CaffeinatedCoder merged commit 6993b5c into release/2.3.0 Oct 28, 2026
8 checks passed
@CaffeinatedCoder
CaffeinatedCoder deleted the feat/async-assertions branch October 28, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/option-result Option, Result and their extensions enhancement New feature or request package/analyzers Affects CodoMetis.TypeKit.Analyzers package/testing Affects CodoMetis.TypeKit.Testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant