Skip to content

Tags: thomhurst/TUnit

Tags

v1.13.60

Toggle v1.13.60's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Detect async void lambdas in AsyncVoidAnalyzer (TUnit0031) (#4758)

* Initial plan

* Enhance AsyncVoidAnalyzer to detect async void lambdas and anonymous delegates

Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>

v1.13.56

Toggle v1.13.56's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: support assembly-level [assembly: Repeat(N)] attribute (#4753)

RepeatAttribute declares AttributeTargets.Assembly but neither the source
generator nor the reflection engine checked assembly-level attributes.
This adds assembly as the lowest-precedence fallback (method > class > assembly)
in both ExtractRepeatCount overloads and the reflection discovery path.

Also tighten all RepeatAttribute checks in the source generator to verify
the attribute's containing namespace is TUnit.Core, preventing false matches
against user-defined attributes with the same name.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

v1.13.54

Toggle v1.13.54's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: disable IDE streaming sink by default to prevent test runner cra…

…shes (#4751)

The IdeStreamingSink causes crashes in Rider and VS Code due to the
Microsoft Testing Platform's TestApplicationResult.ConsumeAsync throwing
on duplicate TestNodeUid keys. Gate the feature behind the
TUNIT_ENABLE_IDE_STREAMING=1 environment variable so users can opt in.

Closes #4749

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

v1.13.51

Toggle v1.13.51's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: prevent test hangs when IAsyncDiscoveryInitializer partially ini…

…tializes then throws (#4715) (#4746)

When InitializeAsync() starts resources (e.g. ports, background processes)
then throws, TUnit was removing the failed entry from its initialization
caches to allow retry. The retry calls InitializeAsync() again on the same
partially-initialized shared object, which hangs because the first
resources still hold ports/processes.

- Stop removing failed/cancelled entries from ObjectInitializer and
  ObjectLifecycleService caches so the faulted task is returned immediately
  to subsequent callers
- Fix fast-path in ObjectLifecycleService to also check IsCanceled so
  cancelled initializations don't silently return uninitialized objects
- Add 5-minute discovery timeout to the filter execution path matching
  the existing streaming path timeout
- Add engine test for attribute-based property injection failure scenario

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

v1.13.48

Toggle v1.13.48's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: evaluate SkipAttribute before data source initialization (#4737) (

…#4743)

Derived SkipAttribute subclasses (e.g., skip-in-CI attributes) set
SkipReason during OnTestRegistered, but the execution path called
CreateInstanceAsync() — triggering expensive IAsyncInitializer calls —
before checking SkipReason. If initialization threw (e.g., no database
in CI), the test was marked as failed instead of skipped.

Three layered fixes:

1. TestFilterService.RegisterTest: fire OnTestRegistered event receivers
   BEFORE RegisterTestArgumentsAsync, and skip argument registration
   entirely when SkipReason is set. This prevents ClassDataSource
   initialization for skipped tests during the registration phase.

2. TestCoordinator.ExecuteTestInternalAsync: check SkipReason before
   entering retry/timeout logic and instance creation.

3. TestCoordinator.ExecuteTestLifecycleAsync: check SkipReason before
   CreateInstanceAsync() to prevent data source initialization that
   would fail or waste resources for skipped tests.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

v1.13.47

Toggle v1.13.47's commit message

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
chore(deps): update verify to 31.12.5 (#4742)

Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>

v1.13.40

Toggle v1.13.40's commit message

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
chore(deps): update dependency dotnet-sdk to v10.0.103 (#4733)

Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>

v1.13.30

Toggle v1.13.30's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: consistent test time tracking - exclude Before/After hooks from …

…headline duration (#4723)

Before hooks were already excluded from test duration (TestStart set after
Before hooks), but After hooks were included (TestEnd only set after After
hooks completed). This made reported test times inconsistent and inflated.

Now TestEnd is set immediately after the test body finishes (before After
hooks run), and both Before/After test-level hooks are recorded as step
timings via Timings.Record() for granular visibility. EndTime assignments
in TestRunner, TestStateManager use ??= to respect the body-level TestEnd.
Timings are cleared on retry and re-execution.

Closes #4711

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

v1.13.27

Toggle v1.13.27's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: prevent After(TestSession) hook from firing prematurely on test …

…timeout (#4720)

* fix: prevent After(TestSession) hook from firing prematurely on test timeout

When a test timed out, the cancellation callback registered by
AfterHookPairTracker would fire the session-level After hooks
immediately — even while other tests were still running. Additionally,
TestScheduler called HookExecutor directly, bypassing the tracker's
deduplication, causing hooks to run a second time.

Fix by: (1) adding a first-call-wins guard so only the first
RegisterAfterTestSessionHook call registers a cancellation callback
(the one from TestCoordinator with the session-level token, not
per-test timeout tokens), and (2) routing TestScheduler through
AfterHookPairTracker.GetOrCreateAfterTestSessionTask instead of
calling HookExecutor directly.

Closes #4712

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf: avoid redundant ValueTask-Task-ValueTask conversion in TestScheduler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

v1.13.24

Toggle v1.13.24's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: prevent tests hanging when InitializeAsync throws in chained Cla…

…ssDataSource dependencies (#4715) (#4717)

Three bugs combined to cause indefinite hangs when IAsyncDiscoveryInitializer.InitializeAsync() throws:

1. CreateFailedTestDetails called InitializeAttributesAsync — the exact method that caused the original exception — re-triggering the failure inside the catch block. Made it synchronous with empty attributes matching the safe TestBuilderPipeline pattern.

2. FailedExecutableTest in TestBuilder was missing State=Failed and Result, so failed tests didn't get the early-exit in TestCoordinator.ExecuteTestInternalAsync.

3. The 5-minute discovery timeout CTS was created but the original cancellationToken was passed instead of cts.Token, so the timeout was never applied.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>