Skip to content

perf(engine): skip Console.Out/Err FlushAsync when no output captured (#5712)#5724

Merged
thomhurst merged 1 commit intomainfrom
perf/5712-console-flush
Apr 24, 2026
Merged

perf(engine): skip Console.Out/Err FlushAsync when no output captured (#5712)#5724
thomhurst merged 1 commit intomainfrom
perf/5712-console-flush

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

Closes #5712

Summary

  • Adds a volatile HasCapturedConsoleOutput flag on Context, set by the console interceptor on any write path.
  • TestCoordinator checks the flag before awaiting Console.Out.FlushAsync() / Console.Error.FlushAsync() in the per-test finally block, skipping both calls when nothing was written.
  • Removes 2 async state machines per passing test with no output; CPU-sampling trace showed AsyncMethodBuilderCore.Start at 16.39% inclusive / 2.93% self — expected ~1.5-2% CPU reduction.

Correctness

  • The flag is monotonic (false -> true) and set before the buffer append, so any write that lands triggers the flush.
  • The fire-and-forget race (Task.Run(() => Console.WriteLine(...)) without awaiting) already exists under the old unconditional flush — the flag preserves identical semantics: when the Task.Run actually writes it flips the flag and is observed by the next test's finally or the test session cleanup path.
  • Partial writes (Console.Write without newline) are covered — they hit GetLineBufferForWrite which marks the flag before appending to the buffer.
  • Volatile read/write (no lock, no allocation) on the hot path.

Test plan

  • dotnet build TUnit.slnx -c Release succeeds (0 errors, pre-existing warnings only).
  • BasicTests smoke — 3/3 passed.
  • CaptureOutputTests (Console.WriteLine + GetStandardOutput assertions, [Repeat(15)]) — 80/80 passed.
  • TestBuildContextOutputCaptureTests — 7/7 passed.
  • ParallelConsoleOutputTests — 44/44 passed.
  • OutputTruncationTests — 3/3 passed.

Risks

  • If a test writes only during an async continuation that resumes after the coordinator's finally runs, output is lost — but this is already the case under the old code (FlushAsync is still a point-in-time call), so no regression.
  • The flag lives on Context (base class), not TestContext; writes from non-test contexts (hooks) also set it, which is harmless since the flag is per-context.

…#5712)

Every test unconditionally awaited two FlushAsync calls in the finally
block, producing two extra async state machines per test for the common
case where nothing was written to stdout/stderr.

The console interceptor now sets a volatile HasCapturedConsoleOutput flag
on the context whenever a write path runs. TestCoordinator checks the flag
before calling FlushAsync, avoiding the two state machines when no output
was captured. Correctness is preserved: any write lands -> flag set ->
flush happens, identical to the old unconditional flush for the
Task.Run fire-and-forget race.

~1.5-2% CPU reduction, -2 state machines per passing test.
@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: perf(engine): skip Console.Out/Err FlushAsync when no output captured

Overall Assessment: Approve with minor observations. The optimization is mechanically sound, the new flag is correctly placed and correctly read, and the PR does not regress any existing behaviour. The observations below are nits and clarifying notes rather than blockers.


Correctness

The new flag is genuinely necessary (not a simplification of an existing one).
HasCapturedOutput (existing) checks whether _outputWriter or _errorOutputWriter was ever initialized. Those lazy fields are only initialized when RouteToSinks pushes a complete line through to the TestOutputSink. A partial write — Console.Write("partial") without a subsequent newline — lands in the ConsoleLineBuffer but never reaches OutputWriter, so HasCapturedOutput remains false while the buffer holds unflushed data. Using the existing flag for the flush guard would silently drop partial writes. The new HasCapturedConsoleOutput flag being set before the buffer append (in GetLineBufferForWrite()) is the correct place.

All write paths are covered.
Tracing the delegation chain:

  • Write(bool/int/float/…)Write(value.ToString())GetLineBufferForWrite()
  • Write(char value), Write(char[], …), Write(string?)GetLineBufferForWrite() directly ✓
  • WriteLine()GetLineBufferForWrite().Drain()
  • WriteLine(string?), WriteLineAsync(string?)GetLineBufferForWrite()
  • All WriteAsync(…) overrides delegate to their sync Write(…) counterparts which go through GetLineBufferForWrite()
  • ReadOnlySpan<char> / ReadOnlyMemory<char> overrides convert to string then call the string overload ✓

The Flush() and FlushAsync() overrides intentionally use GetLineBuffer() — not GetLineBufferForWrite(). This is correct: flushing existing buffered content is not a new write, so the flag should not be set there.

Monotonic flag is safe under retries.
RetryHelper does not reset the flag between attempts. This is intentional and correct: the flag is a signal that a flush is needed at some point, not a per-attempt tracker. A partial write from attempt 1 that sits in the buffer will still be flushed when the test-level finally eventually runs.


Observations

1. int vs bool for the volatile flag

private int _consoleOutputCaptured;

Volatile.Read(ref bool) and Volatile.Write(ref bool, bool) are available in .NET and work correctly. Using bool would make the intent more self-documenting and remove the != 0 comparison on the read path. The int choice is not wrong — it enables Interlocked.CompareExchange if needed later — but there is no current use case for that. If CAS is not anticipated, bool reads more clearly.

2. Guard GetLineBuffer() against future misuse

The naming convention (GetLineBuffer vs GetLineBufferForWrite) has to be learned. If a contributor adds a new Write… override and accidentally uses GetLineBuffer() instead of GetLineBufferForWrite(), the flag will silently not be set for that path and the optimization may drop output. A short comment on GetLineBuffer() would prevent this:

// Use GetLineBufferForWrite() on all write paths to ensure HasCapturedConsoleOutput is set.
// Use this method only for Flush/Close paths.
protected abstract ConsoleLineBuffer GetLineBuffer();

3. Missing automated test for the skip-flush path

The test plan in the PR description is entirely manual. There is no unit test asserting HasCapturedConsoleOutput is false after a no-output test and true after any write. Given that the correctness of the entire optimization rests on this flag, a small unit test would make future regressions immediately visible. Suggested scenarios:

  • Context with no writes: HasCapturedConsoleOutput == false
  • Context after Console.Write("x") (partial, no newline): HasCapturedConsoleOutput == true
  • Context after Console.WriteLine() (empty line): HasCapturedConsoleOutput == true

Summary

The change is architecturally clean, the flag placement is correct, and the performance claim (skipping 2 async state machines per passing test with no output) is well-supported. The only items worth considering before merging:

  1. (Optional) Switch private int _consoleOutputCaptured to private volatile bool for clarity.
  2. (Recommended) Add a comment to GetLineBuffer() warning future contributors to use GetLineBufferForWrite() on write paths.
  3. (Recommended) Add at least one automated unit test asserting flag state under no-write, partial-write, and full-write scenarios.

🤖 Generated with Claude Code

@thomhurst thomhurst merged commit 9bdf15e into main Apr 24, 2026
15 checks passed
@thomhurst thomhurst deleted the perf/5712-console-flush branch April 24, 2026 12:20
@thomhurst
Copy link
Copy Markdown
Owner Author

Addressed the three review suggestions:

  1. Replaced int _consoleOutputCaptured + Volatile.Read/Write with private volatile bool _consoleOutputCaptured for clarity (no CAS was needed).
  2. Added a WHY comment on GetLineBuffer() noting it's for Flush/Close only — write paths must use GetLineBufferForWrite() so draining the buffer doesn't spuriously set HasCapturedConsoleOutput.
  3. Added ConsoleOutputCaptureFlagTests in TUnit.UnitTests covering the three requested scenarios (fresh context false; after Write("x") true; after empty WriteLine() true) plus the direct MarkConsoleOutputCaptured path. All 4 tests pass on net10.0.

This was referenced Apr 26, 2026
intellitect-bot pushed a commit to IntelliTect/EssentialCSharp.Web that referenced this pull request Apr 27, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.39.0 to
1.40.5.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.40.5

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.5 -->

## What's Changed
### Other Changes
* Fix reflection property injection reuse by @​thomhurst in
thomhurst/TUnit#5763
* fix(assertions): gate IsEqualTo<TValue, TOther> overload to net9+
(#​5765) by @​thomhurst in thomhurst/TUnit#5767
### Dependencies
* chore(deps): update tunit to 1.40.0 by @​thomhurst in
thomhurst/TUnit#5762


**Full Changelog**:
thomhurst/TUnit@v1.40.0...v1.40.5

## 1.40.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.0 -->

## What's Changed
### Other Changes
* perf(engine): collapse async forwarding wrappers in test execution
(#​5714) by @​thomhurst in thomhurst/TUnit#5725
* perf(engine): skip Console.Out/Err FlushAsync when no output captured
(#​5712) by @​thomhurst in thomhurst/TUnit#5724
* perf(engine): collapse async state machines on hook cache-hit /
empty-hook path (#​5713) by @​thomhurst in
thomhurst/TUnit#5726
* perf: eliminate per-test closure + GetOrAdd factory alloc (#​5710) by
@​thomhurst in thomhurst/TUnit#5727
* perf(engine): replace global lock in EventReceiverRegistry with
lock-free CAS by @​thomhurst in
thomhurst/TUnit#5731
* perf(engine): batch per-test overhead cleanups (#​5719) by @​thomhurst
in thomhurst/TUnit#5730
* #​5733 handling all arguments for Fact and Theory by @​inyutin-maxim
in thomhurst/TUnit#5734
* fix(assertions): prefer string overload of Member() over
IEnumerable<char> (#​5702) by @​thomhurst in
thomhurst/TUnit#5721
* fix(migration): preserve comments/XML docs when removing sole
attributes (#​5698) by @​thomhurst in
thomhurst/TUnit#5739
* perf(build): trim test TFMs and skip viewer dump by default by
@​thomhurst in thomhurst/TUnit#5741
* fix(pipeline): skip TestBaseModule frameworks with missing binaries by
@​thomhurst in thomhurst/TUnit#5752
* feat(assertions): focused diff messages for IsEqualTo/IsEquivalentTo
(#​5732) by @​thomhurst in thomhurst/TUnit#5747
* fix(analyzers): remove incorrect AOT rules TUnit0300/0301/0302
(#​5722) by @​thomhurst in thomhurst/TUnit#5746
* perf(engine): lazy hook metadata registration (#​5448) by @​thomhurst
in thomhurst/TUnit#5750
* chore(templates): unify TUnit version pinning to 1.* (#​5709) by
@​thomhurst in thomhurst/TUnit#5743
* fix(templates): floating TUnit.Aspire version (#​5708) by @​thomhurst
in thomhurst/TUnit#5742
* fix(assertions): preserve specialised source in .Count(itemAssertion)
(#​5707) by @​thomhurst in thomhurst/TUnit#5749
* feat(assertions): IsEqualTo with implicitly-convertible wrappers
(#​5720) by @​thomhurst in thomhurst/TUnit#5751
* feat(aspire): add ability to manually remove resources by @​Odonno in
thomhurst/TUnit#5586
* fix(fscheck): register default CancellationToken arbitrary that
surfaces TestContext token by @​JohnVerheij in
thomhurst/TUnit#5758
* fix(engine): allow keyed NotInParallel tests to run alongside
unconstrained tests (#​5700) by @​thomhurst in
thomhurst/TUnit#5740
* perf: skip TimeoutHelper wrap when no explicit [Timeout] is set
(#​5711) by @​thomhurst in thomhurst/TUnit#5728
### Dependencies
* chore(deps): update tunit to 1.39.0 by @​thomhurst in
thomhurst/TUnit#5701
* chore(deps): update aspire to 13.2.4 by @​thomhurst in
thomhurst/TUnit#5735
* chore(deps): bump postcss from 8.5.6 to 8.5.10 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5736
* chore(deps): update dependency fscheck to 3.3.3 by @​thomhurst in
thomhurst/TUnit#5760

## New Contributors
* @​inyutin-maxim made their first contribution in
thomhurst/TUnit#5734
* @​Odonno made their first contribution in
thomhurst/TUnit#5586

**Full Changelog**:
thomhurst/TUnit@v1.39.0...v1.40.0

Commits viewable in [compare
view](thomhurst/TUnit@v1.39.0...v1.40.5).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit&package-manager=nuget&previous-version=1.39.0&new-version=1.40.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
github-actions Bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request Apr 27, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.37.0 to
1.40.10.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit.Core's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.40.10

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.10 -->

## What's Changed
### Other Changes
* refactor(opentelemetry): depend on TUnit.Core instead of umbrella
TUnit by @​thomhurst in thomhurst/TUnit#5774
### Dependencies
* chore(deps): update tunit to 1.40.5 by @​thomhurst in
thomhurst/TUnit#5769


**Full Changelog**:
thomhurst/TUnit@v1.40.5...v1.40.10

## 1.40.5

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.5 -->

## What's Changed
### Other Changes
* Fix reflection property injection reuse by @​thomhurst in
thomhurst/TUnit#5763
* fix(assertions): gate IsEqualTo<TValue, TOther> overload to net9+
(#​5765) by @​thomhurst in thomhurst/TUnit#5767
### Dependencies
* chore(deps): update tunit to 1.40.0 by @​thomhurst in
thomhurst/TUnit#5762


**Full Changelog**:
thomhurst/TUnit@v1.40.0...v1.40.5

## 1.40.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.0 -->

## What's Changed
### Other Changes
* perf(engine): collapse async forwarding wrappers in test execution
(#​5714) by @​thomhurst in thomhurst/TUnit#5725
* perf(engine): skip Console.Out/Err FlushAsync when no output captured
(#​5712) by @​thomhurst in thomhurst/TUnit#5724
* perf(engine): collapse async state machines on hook cache-hit /
empty-hook path (#​5713) by @​thomhurst in
thomhurst/TUnit#5726
* perf: eliminate per-test closure + GetOrAdd factory alloc (#​5710) by
@​thomhurst in thomhurst/TUnit#5727
* perf(engine): replace global lock in EventReceiverRegistry with
lock-free CAS by @​thomhurst in
thomhurst/TUnit#5731
* perf(engine): batch per-test overhead cleanups (#​5719) by @​thomhurst
in thomhurst/TUnit#5730
* #​5733 handling all arguments for Fact and Theory by @​inyutin-maxim
in thomhurst/TUnit#5734
* fix(assertions): prefer string overload of Member() over
IEnumerable<char> (#​5702) by @​thomhurst in
thomhurst/TUnit#5721
* fix(migration): preserve comments/XML docs when removing sole
attributes (#​5698) by @​thomhurst in
thomhurst/TUnit#5739
* perf(build): trim test TFMs and skip viewer dump by default by
@​thomhurst in thomhurst/TUnit#5741
* fix(pipeline): skip TestBaseModule frameworks with missing binaries by
@​thomhurst in thomhurst/TUnit#5752
* feat(assertions): focused diff messages for IsEqualTo/IsEquivalentTo
(#​5732) by @​thomhurst in thomhurst/TUnit#5747
* fix(analyzers): remove incorrect AOT rules TUnit0300/0301/0302
(#​5722) by @​thomhurst in thomhurst/TUnit#5746
* perf(engine): lazy hook metadata registration (#​5448) by @​thomhurst
in thomhurst/TUnit#5750
* chore(templates): unify TUnit version pinning to 1.* (#​5709) by
@​thomhurst in thomhurst/TUnit#5743
* fix(templates): floating TUnit.Aspire version (#​5708) by @​thomhurst
in thomhurst/TUnit#5742
* fix(assertions): preserve specialised source in .Count(itemAssertion)
(#​5707) by @​thomhurst in thomhurst/TUnit#5749
* feat(assertions): IsEqualTo with implicitly-convertible wrappers
(#​5720) by @​thomhurst in thomhurst/TUnit#5751
* feat(aspire): add ability to manually remove resources by @​Odonno in
thomhurst/TUnit#5586
* fix(fscheck): register default CancellationToken arbitrary that
surfaces TestContext token by @​JohnVerheij in
thomhurst/TUnit#5758
* fix(engine): allow keyed NotInParallel tests to run alongside
unconstrained tests (#​5700) by @​thomhurst in
thomhurst/TUnit#5740
* perf: skip TimeoutHelper wrap when no explicit [Timeout] is set
(#​5711) by @​thomhurst in thomhurst/TUnit#5728
### Dependencies
* chore(deps): update tunit to 1.39.0 by @​thomhurst in
thomhurst/TUnit#5701
* chore(deps): update aspire to 13.2.4 by @​thomhurst in
thomhurst/TUnit#5735
* chore(deps): bump postcss from 8.5.6 to 8.5.10 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5736
* chore(deps): update dependency fscheck to 3.3.3 by @​thomhurst in
thomhurst/TUnit#5760

## New Contributors
* @​inyutin-maxim made their first contribution in
thomhurst/TUnit#5734
* @​Odonno made their first contribution in
thomhurst/TUnit#5586

**Full Changelog**:
thomhurst/TUnit@v1.39.0...v1.40.0

## 1.39.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.39.0 -->

## What's Changed
### Other Changes
* perf(mocks): shrink MethodSetup + cache stateless matchers by
@​thomhurst in thomhurst/TUnit#5669
* fix(mocks): handle base classes with explicit interface impls (#​5673)
by @​thomhurst in thomhurst/TUnit#5674
* fix(mocks): implement indexer in generated mock (#​5676) by
@​thomhurst in thomhurst/TUnit#5683
* fix(mocks): disambiguate IEquatable<T>.Equals from object.Equals
(#​5675) by @​thomhurst in thomhurst/TUnit#5680
* fix(mocks): escape C# keyword identifiers at all emit sites (#​5679)
by @​thomhurst in thomhurst/TUnit#5684
* fix(mocks): emit [SetsRequiredMembers] on generated mock ctor (#​5678)
by @​thomhurst in thomhurst/TUnit#5682
* fix(mocks): skip MockBridge for class targets with static-abstract
interfaces (#​5677) by @​thomhurst in
thomhurst/TUnit#5681
* chore(mocks): regenerate source generator snapshots by @​thomhurst in
thomhurst/TUnit#5691
* perf(engine): collapse async state-machine layers on hot test path
(#​5687) by @​thomhurst in thomhurst/TUnit#5690
* perf(engine): reduce lock contention in scheduling and hook caches
(#​5686) by @​thomhurst in thomhurst/TUnit#5693
* fix(assertions): prevent implicit-to-string op from NREing on null
(#​5692) by @​thomhurst in thomhurst/TUnit#5696
* perf(engine/core): reduce per-test allocations (#​5688) by @​thomhurst
in thomhurst/TUnit#5694
* perf(engine): reduce message-bus contention on test start (#​5685) by
@​thomhurst in thomhurst/TUnit#5695
### Dependencies
* chore(deps): update tunit to 1.37.36 by @​thomhurst in
thomhurst/TUnit#5667
* chore(deps): update verify to 31.16.2 by @​thomhurst in
thomhurst/TUnit#5699


**Full Changelog**:
thomhurst/TUnit@v1.37.36...v1.39.0

## 1.37.36

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.36 -->

## What's Changed
### Other Changes
* fix(telemetry): remove duplicate HTTP client spans by @​thomhurst in
thomhurst/TUnit#5668


**Full Changelog**:
thomhurst/TUnit@v1.37.35...v1.37.36

## 1.37.35

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.35 -->

## What's Changed
### Other Changes
* Add TUnit.TestProject.Library to the TUnit.Dev.slnx solution file by
@​Zodt in thomhurst/TUnit#5655
* fix(aspire): preserve user-supplied OTLP endpoint (#​4818) by
@​thomhurst in thomhurst/TUnit#5665
* feat(aspire): emit client spans for HTTP by @​thomhurst in
thomhurst/TUnit#5666
### Dependencies
* chore(deps): update dependency dotnet-sdk to v10.0.203 by @​thomhurst
in thomhurst/TUnit#5656
* chore(deps): update microsoft.aspnetcore to 10.0.7 by @​thomhurst in
thomhurst/TUnit#5657
* chore(deps): update tunit to 1.37.24 by @​thomhurst in
thomhurst/TUnit#5659
* chore(deps): update microsoft.extensions to 10.0.7 by @​thomhurst in
thomhurst/TUnit#5658
* chore(deps): update aspire to 13.2.3 by @​thomhurst in
thomhurst/TUnit#5661
* chore(deps): update dependency microsoft.net.test.sdk to 18.5.0 by
@​thomhurst in thomhurst/TUnit#5664

## New Contributors
* @​Zodt made their first contribution in
thomhurst/TUnit#5655

**Full Changelog**:
thomhurst/TUnit@v1.37.24...v1.37.35

## 1.37.24

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.24 -->

## What's Changed
### Other Changes
* docs: add Tluma Ask AI widget to Docusaurus site by @​thomhurst in
thomhurst/TUnit#5638
* Revert "chore(deps): update dependency docusaurus-plugin-llms to
^0.4.0 (#​5637)" by @​thomhurst in
thomhurst/TUnit#5640
* fix(asp-net): forward disposal in FlowSuppressingHostedService
(#​5651) by @​JohnVerheij in
thomhurst/TUnit#5652
### Dependencies
* chore(deps): update dependency docusaurus-plugin-llms to ^0.4.0 by
@​thomhurst in thomhurst/TUnit#5637
* chore(deps): update tunit to 1.37.10 by @​thomhurst in
thomhurst/TUnit#5639
* chore(deps): update opentelemetry to 1.15.3 by @​thomhurst in
thomhurst/TUnit#5645
* chore(deps): update opentelemetry by @​thomhurst in
thomhurst/TUnit#5647
* chore(deps): update dependency dompurify to v3.4.1 by @​thomhurst in
thomhurst/TUnit#5648
* chore(deps): update dependency system.commandline to 2.0.7 by
@​thomhurst in thomhurst/TUnit#5650
* chore(deps): update dependency microsoft.entityframeworkcore to 10.0.7
by @​thomhurst in thomhurst/TUnit#5649
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.203 by @​thomhurst in
thomhurst/TUnit#5653
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.203 by
@​thomhurst in thomhurst/TUnit#5654


**Full Changelog**:
thomhurst/TUnit@v1.37.10...v1.37.24

## 1.37.10

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.10 -->

## What's Changed
### Other Changes
* docs(test-filters): add migration callout for --filter →
--treenode-filter by @​johnkattenhorn in
thomhurst/TUnit#5628
* fix: re-enable RPC tests and modernize harness (#​5540) by @​thomhurst
in thomhurst/TUnit#5632
* fix(mocks): propagate [Obsolete] and null-forgiving raise dispatch
(#​5626) by @​JohnVerheij in
thomhurst/TUnit#5631
* ci: use setup-dotnet built-in NuGet cache by @​thomhurst in
thomhurst/TUnit#5635
* feat(playwright): propagate W3C trace context into browser contexts by
@​thomhurst in thomhurst/TUnit#5636
### Dependencies
* chore(deps): update tunit to 1.37.0 by @​thomhurst in
thomhurst/TUnit#5625

## New Contributors
* @​johnkattenhorn made their first contribution in
thomhurst/TUnit#5628
* @​JohnVerheij made their first contribution in
thomhurst/TUnit#5631

**Full Changelog**:
thomhurst/TUnit@v1.37.0...v1.37.10

Commits viewable in [compare
view](thomhurst/TUnit@v1.37.0...v1.40.10).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.37.0&new-version=1.40.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
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.

perf: skip Console.Out/Err FlushAsync when no output captured

1 participant