Skip to content

perf(analyzers): cut TUnit analyzer build time ~60% on large test projects - #6862

Merged
thomhurst merged 2 commits into
mainfrom
perf/analyzer-build-time
Sep 22, 2026
Merged

thomhurst merged 2 commits into
mainfrom
perf/analyzer-build-time

Conversation

@thomhurst

@thomhurst thomhurst commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

meziantou's framework benchmark found TUnit builds about 2× slower than the other frameworks at 10,000 tests. Profiling with -p:ReportAnalyzer=true showed the source generator itself is cheap. A large share of the extra time was TUnit's Roslyn analyzers doing expensive work on every syntax node, even in a project with no assertions at all:

  • CompilerArgumentsPopulatedAnalyzer called SemanticModel.GetOperation on every argument in the compilation.
  • Hot paths compared symbol.GloballyQualified() == "global::...", which builds a display string for every candidate symbol.
  • BeforeHookAsyncLocal looked up GetTypeByMetadataName with a freshly built string on every call, so the per-compilation cache always missed.

Changes:

  • Name-check helpers: new IsGloballyQualified / IsGloballyQualifiedNonGeneric helpers compare the symbol's simple name first and only build the display string when that name matches. All hot-path comparisons now use them. A new test checks that the helpers always agree with the plain string comparison, over more than 10,000 symbol/name pairs covering generics, nested types, arrays, nullables, tuples and methods.
  • CompilerArgumentsPopulatedAnalyzer: now an operation action limited to explicitly written arguments, so it no longer calls GetOperation for each syntax node.
  • Invocation analyzers: AwaitAssertion, XUnitAssertion, GenerateAssertion and ClassDataSourceConstructor check the method or attribute name before doing any symbol formatting.
  • Other analyzers: MissingTestAttribute and PublicMethodMissingTestAttribute run their cheaper checks first. SingleTUnitAttribute returns early when a symbol has fewer than two attributes. BeforeHookAsyncLocal uses a fixed string for its type lookup, so the cache now hits.

The reported diagnostics are unchanged. Running main's and this branch's analyzers over the full TUnit.TestProject and TUnit.Assertions.Tests sources gives identical results (226 and 60 diagnostics, including 3 TUnitAssertions0003).

Benchmark

Median of 6 interleaved builds of the 10,000-test project with -p:ReportAnalyzer=true -p:UseSharedCompilation=false, comparing against current main. The machine was shared, so treat these as directional:

main this PR
All analyzers (summed) 6.93 s 4.60 s
TUnit.Analyzers 1.97 s 0.94 s
TUnit.Assertions.Analyzers 0.83 s 0.18 s
CompilerArgumentsPopulated (TUnitAssertions0003) 0.462 s 0.021 s
GlobalTestHooks 0.389 s 0.065 s
SingleTUnitAttribute (TUnit0029) 0.232 s 0.005 s
DependsOnConflict 0.178 s 0.072 s
AwaitAssertion 0.104 s 0.007 s

A controlled harness that ran the analyzers warm and single-threaded gave TUnit analyzer time per pass of 343–606 ms on main and 130–194 ms here (medians).

On TUnit.TestProject, TUnit.Assertions.Analyzers went from 0.57 s to 0.18 s and total analyzer time from 6.6 s to 5.7 s.

Tests

  • TUnit.Analyzers.Tests: 784 passed, 1 skipped (already skipped on main).
  • TUnit.Assertions.Analyzers.Tests: 112 passed.
  • TUnit.Assertions.Analyzers.CodeFixers.Tests: 19 passed.
  • New tests:
    • Helper equivalence, in both analyzer test projects, using the shared tests/SharedTestHelpers/GloballyQualifiedComparisonCases.cs.
    • Three CompilerArgumentsPopulated tests covering named arguments, lambdas, local functions, field and property initializers, constructor initializers, nested calls, and non-TUnit caller-info parameters. They pass on both the old and new implementations.
  • The Roslyn44, Roslyn47 and Roslyn414 variants and the CodeFixers projects build.

Remaining big costs: DisposableFieldPropertyAnalyzer and TestDataAnalyzer. Their time is mostly method-body binding through GetOperation, and I left them alone because the cheaper pre-filters I could see risked changing results.

Summary by CodeRabbit

  • Bug Fixes

    • Improved analyzer recognition of fully qualified types and attributes, preserving existing diagnostics while reducing missed or incorrect matches.
    • Explicit compiler-supplied arguments in assertion APIs are now consistently reported, including named arguments and nested or lambda-based usage.
    • Unrelated methods and symbols are filtered earlier, improving analyzer responsiveness without changing supported behavior.
  • Tests

    • Expanded coverage for qualified-name matching and compiler-argument diagnostics across diverse language constructs.

- Add IsGloballyQualified/IsGloballyQualifiedNonGeneric helpers that reject on
  the symbol's simple name before building a display string, and use them for
  every per-attribute / per-base-type / per-parameter / per-invocation name
  comparison (SingleTUnitAttribute, DependsOnConflict, hooks, data sources,
  Timeout, ConsoleOut, MixAndOr, ObjectBaseEquals, AwaitValueTaskAssertThat...).
- CompilerArgumentsPopulatedAnalyzer: operation action on OperationKind.Argument
  (non-implicit, ArgumentSyntax) instead of SemanticModel.GetOperation for every
  ArgumentSyntax in the compilation.
- AwaitAssertion/XUnitAssertion/GenerateAssertion/ClassDataSourceConstructor:
  cheap name pre-filters before display strings.
- Pass stable strings to GetTypeByMetadataName (its cache is keyed by string
  reference); cheaper check ordering in MissingTestAttribute and
  PublicMethodMissingTestAttribute; skip SingleTUnitAttribute work for < 2 attributes.

Diagnostics are unchanged: an equivalence test checks the helpers against plain
display-string comparison over a broad symbol matrix, new
CompilerArgumentsPopulated tests pass against both the old and new
implementation, and the reported diagnostics for TUnit.TestProject and
TUnit.Assertions.Tests are identical before/after.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-22T21:05:16.661854Z 1ae9a70 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: e3242564-c6c1-48b7-ade1-f117ad427059

📥 Commits

Reviewing files that changed from the base of the PR and between 0b47237 and 1ae9a70.

📒 Files selected for processing (4)
  • src/TUnit.Analyzers/Extensions/TypeExtensions.GloballyQualified.cs
  • src/TUnit.Analyzers/Extensions/TypeExtensions.cs
  • src/TUnit.Assertions.Analyzers/Extensions/TypeExtensions.cs
  • src/TUnit.Assertions.Analyzers/TUnit.Assertions.Analyzers.csproj

Included review availability: Your plan provides up to 8 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The pull request adds allocation-saving qualified-name predicates, replaces direct display-string comparisons across both analyzer projects, updates analyzer execution paths, and adds comparison and compiler-argument tests.

Changes

Qualified symbol matching

Layer / File(s) Summary
Qualified-name predicate helpers
src/TUnit.Analyzers/Extensions/TypeExtensions.cs, src/TUnit.Analyzers/Extensions/TypeExtensions.GloballyQualified.cs, src/TUnit.Assertions.Analyzers/Extensions/TypeExtensions.cs, src/TUnit.Assertions.Analyzers/TUnit.Assertions.Analyzers.csproj
Adds shared IsGloballyQualified and IsGloballyQualifiedNonGeneric helpers. Both analyzer projects compile the shared implementation.
TUnit analyzer migration
src/TUnit.Analyzers/...
Replaces direct qualified-name string comparisons. It also hoists metadata names, reorders predicates, and uses symbol sets for test-method checks.
Assertions analyzer updates
src/TUnit.Assertions.Analyzers/...
Uses the new predicates in assertion analyzers. CompilerArgumentsPopulatedAnalyzer now processes argument operations. Assertion invocation analyzers add early filters.
Comparison and analyzer tests
tests/SharedTestHelpers/GloballyQualifiedComparisonCases.cs, tests/TUnit.Analyzers.Tests/..., tests/TUnit.Assertions.Analyzers.Tests/...
Adds shared predicate-equivalence tests and compiler-argument analyzer tests. Both test projects compile the shared helper.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 1ae9a

The optimization is mergeable; reviewed analyzer behavior and shared helper wiring preserve the existing contracts.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 66 functions across 35 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: a performance improvement that reduces TUnit analyzer build time for large test projects.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 6.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 66 functions across 35 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit reads each line,
The patch grows clear beneath the moon,
Small changes hop in place,
Tests guard the garden path,
Reviews bloom before the dawn.

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Code Review

Reviewed the full diff (33 files, analyzer perf work cutting build time ~60% by adding IsGloballyQualified/IsGloballyQualifiedNonGeneric fast-path predicates in place of direct display-string comparisons across TUnit.Analyzers and TUnit.Assertions.Analyzers).

Correctness: I traced the new hand-rolled parser (TryGetLastSegmentName / CanHaveGloballyQualifiedName) by hand against nested generics, verbatim identifiers, tuples, pointers, nullable annotations, delegates, and malformed input. Whenever it can't confidently identify the last dotted segment of the expected name, it returns false from TryGetLastSegmentName, which makes CanHaveGloballyQualifiedName fall back to true (i.e. falls through to the original full-string comparison) — so the optimization is fail-safe by construction. This is backed by the PR's own >10,000-case property test in GloballyQualifiedComparisonCases.cs, shared between both test projects. The MethodKind.Ordinary guards in AwaitAssertionAnalyzer/XUnitAssertionAnalyzer and the CompilerArgumentsPopulatedAnalyzer migration from a syntax-node action to an operation action also check out against their new test coverage (named/lambda/local-function/initializer arguments). No correctness bugs found.

One structural finding:

  • src/TUnit.Assertions.Analyzers/Extensions/TypeExtensions.cs (lines ~27–128) duplicates src/TUnit.Analyzers/Extensions/TypeExtensions.cs (lines ~74–177) verbatim — GloballyQualified, GloballyQualifiedNonGeneric, IsGloballyQualified, IsGloballyQualifiedNonGeneric, CanHaveGloballyQualifiedName, and TryGetLastSegmentName (~95 lines including the non-trivial segment parser) are byte-for-byte identical in both files.

    This PR already establishes the pattern for sharing this exact kind of file across the two projects: tests/SharedTestHelpers/GloballyQualifiedComparisonCases.cs is linked into both TUnit.Analyzers.Tests and TUnit.Assertions.Analyzers.Tests via <Compile Include="..." Link="..."/>, and TUnit.Analyzers.csproj already links ParsableTypeExtensions.cs from TUnit.Core.SourceGenerator the same way. Applying that same linked-Compile-item approach to the parser here (e.g. keep one copy in TUnit.Analyzers and link it into TUnit.Assertions.Analyzers, or extract to a small shared file linked into both) would mean a future edge-case fix to the segment parser only needs to be made once. As two separate copies, it's easy for a fix or extension to land in only one file, silently causing TUnit.Analyzers and TUnit.Assertions.Analyzers to diverge in which attributes/types they recognize as matching a given globally-qualified name — a correctness regression that wouldn't be caught unless both test suites exercise the same case.

No other structural or design concerns. Nice work on making a hot-path allocation optimization provably safe via the fallback-to-true design rather than trying to make the fast path exhaustive.

…alyzer projects

Move GloballyQualified/IsGloballyQualified and their name-prefilter helpers into TypeExtensions.GloballyQualified.cs (partial TypeExtensions) in TUnit.Analyzers and link it into TUnit.Assertions.Analyzers. The namespace is selected via TUNIT_ASSERTIONS_ANALYZERS so DisplayFormats still binds to each assembly's own (differing) formats and call sites are unchanged.
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed the duplication in 1ae9a70.

The GloballyQualified / IsGloballyQualified helpers and the name-prefilter logic now live in one file, src/TUnit.Analyzers/Extensions/TypeExtensions.GloballyQualified.cs (a partial of TypeExtensions). It's linked into TUnit.Assertions.Analyzers with <Compile Include ... Link=...>, and the copies in both TypeExtensions.cs files are removed.

One thing to know: the code was identical, but each assembly has its own DisplayFormats, and they differ. The assertions formats don't set UseSpecialTypes or the nullable modifier. To keep each project's behavior, the shared file picks its namespace with a TUNIT_ASSERTIONS_ANALYZERS define, so DisplayFormats resolves to that assembly's own class. Call sites don't change.

TUnit.Analyzers.Tests (2352 passed, 3 skipped) and TUnit.Assertions.Analyzers.Tests (336 passed) both pass.

@thomhurst
thomhurst deployed to Pull Requests September 22, 2026 21:02 — with GitHub Actions Active
@thomhurst
thomhurst deployed to Pull Requests September 22, 2026 21:02 — with GitHub Actions Active
@thomhurst
thomhurst deployed to Pull Requests September 22, 2026 21:02 — with GitHub Actions Active
@greptile-apps

greptile-apps Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the performance-oriented prefilters and callback changes preserving the analyzer behaviors examined.

Summary

This PR reduces analyzer build overhead by adding allocation-avoiding symbol-name prefilters, reusing Roslyn operation analysis for explicit arguments, caching metadata lookup strings, and reordering or memoizing common analyzer checks.

  • Shares fully qualified symbol comparison helpers across both analyzer assemblies while retaining each assembly's display formats.
  • Reworks CompilerArgumentsPopulatedAnalyzer to analyze explicit IArgumentOperation instances without repeatedly binding syntax nodes.
  • Adds broad equivalence and diagnostic-coverage tests for symbol comparisons and caller-information arguments.
  • Preserves the analyzer contracts around awaited assertions, foreign xUnit assertions, generated assertions, and caller argument expressions.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
    C[C# compilation] --> R[Roslyn analyzer callbacks]
    R --> O[Operation actions]
    R --> S[Symbol actions]
    O --> A[Explicit argument and invocation checks]
    S --> P[Cheap name and attribute prefilters]
    P --> Q{Simple name can match?}
    Q -->|No| X[Skip display formatting]
    Q -->|Yes| F[Exact fully qualified comparison]
    A --> D[Diagnostics]
    F --> D
Loading

Reviews (1) · Last reviewed commit: "refactor(analyzers): share globally-qual..."

intellitect-bot pushed a commit to IntelliTect/EssentialCSharp.Web that referenced this pull request Sep 24, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.68.4 to
1.69.0.

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

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

## 1.69.0

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

## What's Changed
### Other Changes
* feat(templates): add enableDotCover flag (#​6714) by @​ForNeVeR in
thomhurst/TUnit#6844
* fix: don't request semantic models for attribute syntax from other
compilations (DevKit crash) by @​thomhurst in
thomhurst/TUnit#6855
* fix(ci): restore net472 PublicAPI tests on Windows by @​thomhurst in
thomhurst/TUnit#6857
* perf(html-report): stream report JSON through pooled chunks and
overlap sidecar serialization by @​thomhurst in
thomhurst/TUnit#6860
* chore(renovate): cap Microsoft.Build packages below 18.10.0 by
@​thomhurst in thomhurst/TUnit#6863
* perf: shrink generated per-class test source static constructors (~40%
less startup JIT) by @​thomhurst in
thomhurst/TUnit#6859
* refactor: remove unreachable decimal source-text path from
GenerateAttributeInstantiation by @​thomhurst in
thomhurst/TUnit#6856
* perf: cut per-test allocations in discovery and execution (-61% at 10k
tests) by @​thomhurst in thomhurst/TUnit#6861
* perf: stop hashing per-test event receivers during registration
(data-driven tests 2.9x faster at 10k) by @​thomhurst in
thomhurst/TUnit#6858
* perf(analyzers): cut TUnit analyzer build time ~60% on large test
projects by @​thomhurst in thomhurst/TUnit#6862
### Dependencies
* chore(deps): update opentelemetry to 1.19.0 by @​thomhurst in
thomhurst/TUnit#6838
* chore(deps): update dependency opentelemetry.instrumentation.runtime
to 1.19.0 by @​thomhurst in thomhurst/TUnit#6840
* chore(deps): update tunit to 1.68.17 by @​thomhurst in
thomhurst/TUnit#6839
* chore(deps): update verify to 33.1.0 by @​thomhurst in
thomhurst/TUnit#6843
* chore(deps): update verify to 33.1.1 by @​thomhurst in
thomhurst/TUnit#6847
* chore(deps): update opentelemetry to 1.19.1 by @​thomhurst in
thomhurst/TUnit#6850
* chore(deps): update dependency grpc.core.api to 2.84.0 by @​thomhurst
in thomhurst/TUnit#6851
* chore(deps): update dependency stackexchange.redis to 3.3.1 by
@​thomhurst in thomhurst/TUnit#6853
* chore(deps): update dependency polyfill to 11.4.0 by @​thomhurst in
thomhurst/TUnit#6841
* chore(deps): update dependency polyfill to 11.4.0 by @​thomhurst in
thomhurst/TUnit#6842

## New Contributors
* @​ForNeVeR made their first contribution in
thomhurst/TUnit#6844

**Full Changelog**:
thomhurst/TUnit@v1.68.17...v1.69.0

## 1.68.17

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

## What's Changed
### Other Changes
* fix(mocks): emit init accessors for init-only properties and indexers
by @​thomhurst in thomhurst/TUnit#6833
* fix(mocks): let one type be mocked regularly and wrapped in one
compilation by @​thomhurst in
thomhurst/TUnit#6835
* fix(mocks): keep editors in sync with publicized project references
(#​6836) by @​thomhurst in thomhurst/TUnit#6837
### Dependencies
* chore(deps): update tunit to 1.68.4 by @​thomhurst in
thomhurst/TUnit#6824
* chore(deps): update mstest to 4.4.1 by @​thomhurst in
thomhurst/TUnit#6825
* chore(deps): update microsoft.testing by @​thomhurst in
thomhurst/TUnit#6717
* chore(deps): update verify to v33 by @​thomhurst in
thomhurst/TUnit#6794
* chore(deps): update dependency stackexchange.redis to 3.2.15 by
@​thomhurst in thomhurst/TUnit#6827
* chore(deps): update dependency messagepack to 3.1.9 by @​thomhurst in
thomhurst/TUnit#6828
* chore(deps): update dependency stackexchange.redis to 3.3.0 by
@​thomhurst in thomhurst/TUnit#6831
* chore(deps): update opentelemetry to 1.19.0 by @​thomhurst in
thomhurst/TUnit#6832


**Full Changelog**:
thomhurst/TUnit@v1.68.4...v1.68.17

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

Updated [TUnit.AspNetCore](https://github.com/thomhurst/TUnit) from
1.68.4 to 1.69.0.

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

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

## 1.69.0

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

## What's Changed
### Other Changes
* feat(templates): add enableDotCover flag (#​6714) by @​ForNeVeR in
thomhurst/TUnit#6844
* fix: don't request semantic models for attribute syntax from other
compilations (DevKit crash) by @​thomhurst in
thomhurst/TUnit#6855
* fix(ci): restore net472 PublicAPI tests on Windows by @​thomhurst in
thomhurst/TUnit#6857
* perf(html-report): stream report JSON through pooled chunks and
overlap sidecar serialization by @​thomhurst in
thomhurst/TUnit#6860
* chore(renovate): cap Microsoft.Build packages below 18.10.0 by
@​thomhurst in thomhurst/TUnit#6863
* perf: shrink generated per-class test source static constructors (~40%
less startup JIT) by @​thomhurst in
thomhurst/TUnit#6859
* refactor: remove unreachable decimal source-text path from
GenerateAttributeInstantiation by @​thomhurst in
thomhurst/TUnit#6856
* perf: cut per-test allocations in discovery and execution (-61% at 10k
tests) by @​thomhurst in thomhurst/TUnit#6861
* perf: stop hashing per-test event receivers during registration
(data-driven tests 2.9x faster at 10k) by @​thomhurst in
thomhurst/TUnit#6858
* perf(analyzers): cut TUnit analyzer build time ~60% on large test
projects by @​thomhurst in thomhurst/TUnit#6862
### Dependencies
* chore(deps): update opentelemetry to 1.19.0 by @​thomhurst in
thomhurst/TUnit#6838
* chore(deps): update dependency opentelemetry.instrumentation.runtime
to 1.19.0 by @​thomhurst in thomhurst/TUnit#6840
* chore(deps): update tunit to 1.68.17 by @​thomhurst in
thomhurst/TUnit#6839
* chore(deps): update verify to 33.1.0 by @​thomhurst in
thomhurst/TUnit#6843
* chore(deps): update verify to 33.1.1 by @​thomhurst in
thomhurst/TUnit#6847
* chore(deps): update opentelemetry to 1.19.1 by @​thomhurst in
thomhurst/TUnit#6850
* chore(deps): update dependency grpc.core.api to 2.84.0 by @​thomhurst
in thomhurst/TUnit#6851
* chore(deps): update dependency stackexchange.redis to 3.3.1 by
@​thomhurst in thomhurst/TUnit#6853
* chore(deps): update dependency polyfill to 11.4.0 by @​thomhurst in
thomhurst/TUnit#6841
* chore(deps): update dependency polyfill to 11.4.0 by @​thomhurst in
thomhurst/TUnit#6842

## New Contributors
* @​ForNeVeR made their first contribution in
thomhurst/TUnit#6844

**Full Changelog**:
thomhurst/TUnit@v1.68.17...v1.69.0

## 1.68.17

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

## What's Changed
### Other Changes
* fix(mocks): emit init accessors for init-only properties and indexers
by @​thomhurst in thomhurst/TUnit#6833
* fix(mocks): let one type be mocked regularly and wrapped in one
compilation by @​thomhurst in
thomhurst/TUnit#6835
* fix(mocks): keep editors in sync with publicized project references
(#​6836) by @​thomhurst in thomhurst/TUnit#6837
### Dependencies
* chore(deps): update tunit to 1.68.4 by @​thomhurst in
thomhurst/TUnit#6824
* chore(deps): update mstest to 4.4.1 by @​thomhurst in
thomhurst/TUnit#6825
* chore(deps): update microsoft.testing by @​thomhurst in
thomhurst/TUnit#6717
* chore(deps): update verify to v33 by @​thomhurst in
thomhurst/TUnit#6794
* chore(deps): update dependency stackexchange.redis to 3.2.15 by
@​thomhurst in thomhurst/TUnit#6827
* chore(deps): update dependency messagepack to 3.1.9 by @​thomhurst in
thomhurst/TUnit#6828
* chore(deps): update dependency stackexchange.redis to 3.3.0 by
@​thomhurst in thomhurst/TUnit#6831
* chore(deps): update opentelemetry to 1.19.0 by @​thomhurst in
thomhurst/TUnit#6832


**Full Changelog**:
thomhurst/TUnit@v1.68.4...v1.68.17

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

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>

This branch was successfully deployed

1 active deployment
Pull Requests — 1ae9a707 Deployed Sep 22, 2026 by thomhurst via modularpipeline (ubuntu-latest) #19461
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.

1 participant