Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: thomhurst/TUnit
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.48.6
Choose a base ref
...
head repository: thomhurst/TUnit
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.49.0
Choose a head ref
  • 13 commits
  • 93 files changed
  • 2 contributors

Commits on Jun 1, 2026

  1. chore(deps): update tunit to 1.48.6 (#6142)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 1, 2026
    Configuration menu
    Copy the full SHA
    96ce3c5 View commit details
    Browse the repository at this point in the history
  2. docs: benchmark page descriptions + promote Benchmarks in sidebar (#6143

    )
    
    * docs: add a short description to each benchmark page
    
    Each runtime, build, and mock benchmark page now opens with a one-line blockquote describing what the benchmark measures, placed under the title.
    
    The descriptions are emitted by the generator scripts (sourced from the existing RUNTIME_DESCRIPTIONS and categoryDescriptions maps), so they persist across the weekly CI regeneration. The already-generated .md files are updated to match so the descriptions show before the next run.
    
    * docs: promote Benchmarks to a top-level sidebar entry
    
    Benchmarks was nested two levels deep under 'About TUnit'. Move it to a top-level entry placed just before 'Comparing & Migrating' so it's discoverable in the natural decision path before migrating from another framework.
    
    * docs: move Benchmark Methodology above the result pages
    
    Methodology was at sidebar_position 3, colliding with the auto-generated result pages (2-8) and getting buried mid-list. Move it to position 2 so it sits right after the overview pages, and bump the generated result pages to start at 3 (in both the generator script and the existing files) so the ordering survives the weekly regeneration.
    
    * docs: group engine benchmarks into an 'Engine Benchmarks' sub-list
    
    The non-mock result pages (AsyncTests, DataDrivenTests, etc.) sat flat in the benchmarks list while mock benchmarks were grouped under 'Mock Library Benchmarks'. Move them into a benchmarks/engine/ subfolder with a _category_.json so they render as an 'Engine Benchmarks' sub-list sitting next to Mock Library Benchmarks.
    
    The overview (index.md) stays at /docs/benchmarks so existing inbound links keep working; its links now point into ./engine/. Generator scripts updated to emit result pages into engine/ and write the _category_.json, so the structure survives weekly regeneration. Verified with a full docs build (no broken links).
    thomhurst authored Jun 1, 2026
    Configuration menu
    Copy the full SHA
    e91aa01 View commit details
    Browse the repository at this point in the history
  3. chore(deps): update react to ^19.2.7 (#6144)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 1, 2026
    Configuration menu
    Copy the full SHA
    9bfd9f6 View commit details
    Browse the repository at this point in the history
  4. chore(deps): update aspire to 13.4.0 (#6145)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 1, 2026
    Configuration menu
    Copy the full SHA
    034b6fc View commit details
    Browse the repository at this point in the history
  5. chore(deps): update dependency nunit.analyzers to 4.14.0 (#6146)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 1, 2026
    Configuration menu
    Copy the full SHA
    44c6cac View commit details
    Browse the repository at this point in the history

Commits on Jun 2, 2026

  1. Configuration menu
    Copy the full SHA
    cbcbdd0 View commit details
    Browse the repository at this point in the history
  2. chore(deps): update dependency polyfill to 10.7.2 (#6148)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 2, 2026
    Configuration menu
    Copy the full SHA
    3fdfbdd View commit details
    Browse the repository at this point in the history
  3. chore(deps): update dependency polyfill to 10.7.2 (#6149)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 2, 2026
    Configuration menu
    Copy the full SHA
    261e095 View commit details
    Browse the repository at this point in the history

Commits on Jun 3, 2026

  1. Configuration menu
    Copy the full SHA
    dc0bfe0 View commit details
    Browse the repository at this point in the history
  2. chore(deps): update dependency dompurify to v3.4.8 (#6155)

    Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>
    thomhurst and renovate-bot authored Jun 3, 2026
    Configuration menu
    Copy the full SHA
    3f7920a View commit details
    Browse the repository at this point in the history
  3. feat(mocks): discriminate generic-method mocks by type argument (#6153)

    * feat(mocks): discriminate generic-method mocks by type argument
    
    TUnit.Mocks recorded only (memberId, arg-matchers) as the match key, so a
    generic method's type arguments were dropped at the runtime boundary. Setups
    that differ only by type argument (e.g. Greet<Class1>() vs Greet<Class2>(),
    discussion #4981) collided and the last one always won.
    
    Thread an optional Type[]? typeArguments (closed typeof(T) at the call site)
    through setup registration, call dispatch, and verification:
    
    - MethodSetup/CallRecord carry the type arguments; MockEngine gains object[]+Type[]
      HandleCall/HandleCallWithReturn overloads and a TypeArgumentsMatch gate in
      FindMatchingSetup. CallVerificationBuilder filters recorded calls by type argument.
    - The source generator emits `new Type[] { typeof(T), ... }` for generic methods,
      routing them through the fallback dispatch (typed dispatch can't carry type args)
      while preserving any auto-mock factory.
    - Add AnyType/AnyValueType wildcard markers (TUnit.Mocks.Arguments) so a setup can
      match any type argument. Base/interface-constrained type params support exact
      matching only; partial/wrap virtual methods record no type args and are not
      discriminated (documented graceful degradation).
    
    Non-generic methods carry null and behave exactly as before.
    
    Note: FindMatchingSetup keeps a no-default (int, object?[]) overload distinct from
    the type-arg overload so it still wins resolution over generic FindMatchingSetup<T1>.
    
    Adds regression + wildcard + verification tests; updates generic-method snapshots.
    
    * test(mocks): add multi-type-parameter generic-method tests
    
    Cover discrimination by the full ordered type-argument list (T1,T2 order
    sensitivity), partial wildcards (one AnyType + one concrete), exact-wins-over-
    partial-wildcard, and multi-type-param verification including wildcard counts.
    
    * refactor(mocks): dedup type-args literal + collapse redundant ctors
    
    - Reuse MockImplBuilder.TypeArgumentsArrayLiteral from MockMembersBuilder instead
      of re-building the 'new Type[] { typeof(T), ... }' string inline.
    - Collapse MockMethodCall (2->1) and VoidMockMethodCall (4->2) constructors using
      optional parameters; overload resolution and call sites unchanged.
    
    No behavior or generated-output change (snapshots unchanged).
    
    * perf(mocks): cache generic type-arg arrays + show type args in verify failures
    
    Review feedback on PR #6153:
    - Cache a generic method's type-argument array per closed instantiation
      (TypeArguments.Of<T>.Value) for the common 1-2 type-param cases, so dispatch no
      longer allocates a new Type[] on every generic call. Higher arities still emit a
      per-call literal. (Codacy perf finding #1.)
    - Include type arguments in MockVerificationException's expected-call text, so a
      failed Greet<Class1>() verification reads 'Greet<Class1>(...)' not 'Greet(...)'.
      Adds a regression test. (Review finding #5.)
    
    * perf+dx(mocks): extend type-arg cache to arity 3-4, friendlier verify names, AnyValueType test
    
    Follow-up to PR #6153 review:
    - Extend TypeArguments.Of<> cache to 3 and 4 type parameters (was 1-2), so 3-4
      type-param generic methods also avoid per-call Type[] allocation. Doc the
      shared arrays as read-only / never-mutate.
    - Strip the CLR arity suffix in verification failure messages (List, not List`1).
    - Add tests proving AnyValueType works as a wildcard for 'where T : struct'
      parameters (not dead code) and that struct-constrained methods discriminate
      by exact type argument.
    
    * fix(mocks): keep generic type-arg support fully backwards compatible
    
    Earlier commits in this PR introduced two breaking changes to pre-existing public
    types. Reverted while keeping the feature:
    
    - IMockEngineAccess: removed the added CreateVerification overload (a source break
      for any external implementer of this public interface). Generic type-argument
      verification now routes through a new internal ITypeArgumentVerificationFactory,
      implemented only by MockEngine and reached via an internal cast. Non-generic
      verification stays on the unchanged public surface.
    - MockMethodCall / VoidMockMethodCall: restored the original constructor signatures
      that the simplify pass had collapsed into optional-parameter ctors (a binary
      break), adding the type-argument overloads alongside instead of replacing them.
    
    The public API delta for the whole PR is now additions-only: new constructor
    overloads plus the new public types AnyType, AnyValueType and TypeArguments. No
    generated-code or snapshot changes. 1013 integration, 62 snapshot and 30 analyzer
    tests pass; runtime builds on all TFMs including netstandard2.0.
    
    * docs(mocks): consolidate repeated read-only note in TypeArguments
    
    Fold the identical per-field 'shared, read-only' comment on the four Of<>.Value
    fields into the class-level doc. Comment-only.
    
    * fix(mocks): degrade gracefully instead of casting when engine lacks type-arg verification
    
    A custom IMockEngineAccess implementation passed to a generic MockMethodCall/
    VoidMockMethodCall previously hit a hard InvalidCastException at verification
    time. Replace the cast with a type test that falls back to the public,
    non-filtering verification surface. A default interface method on
    IMockEngineAccess is not viable while the library targets netstandard2.0.
    
    * fix(mocks): thread type args through ordered verification + immutable type-arg arrays
    
    Round 7 review fixes:
    
    - OrderedVerification now records and matches a generic expectation's type
      arguments, so VerifyInOrder discriminates Greet<Class1>() from
      Greet<Class2>() like unordered verification does. Failure messages include
      the type arguments. Regression tests added.
    
    - Type-argument arrays are now ImmutableArray<Type> end-to-end
      (TypeArguments.Of<T>.Value, MethodSetup, CallRecord, engine dispatch,
      verification), closing the mutable-shared-array corruption risk while
      keeping array-speed indexed access on the hot matching path. The arity-5+
      generator fallback emits ImmutableArray.Create. All affected signatures
      were introduced on this branch, so no released surface changes.
    
    - CreateVerification routing deduped into MockCallVerification.Create,
      shared by MockMethodCall and VoidMockMethodCall.
    
    - Documented why the typed FindMatchingSetup<T1..T8> family omits a
      TypeArgumentsMatch check: typed dispatch never carries call-side type
      arguments, so the check would be a constant true (non-generic setups have
      none; virtual/partial generic methods use the documented degradation path).
    
    * docs(mocks): note AnyValueType is exact-match-only under additional struct constraints
    thomhurst authored Jun 3, 2026
    Configuration menu
    Copy the full SHA
    e3f8573 View commit details
    Browse the repository at this point in the history
  4. fix(source-gen): emit Array.Empty<T>() for empty array args (#6150) (#…

    …6152)
    
    Jagged-array test data such as `IEnumerable<Func<byte[][]>>` feeding a
    `byte[][]` parameter produced uncompilable generated code (CS1586 + CS0178).
    
    `CollectsTrailingArguments()` treats every array-typed parameter as a
    trailing/collecting array, so `TupleArgumentHelper` built the empty-array
    fallback as `new {elementType}[0]`. For a `byte[][]` parameter the element
    type is `byte[]`, yielding `new byte[][0]` - the `[0]` rank specifier cannot
    follow an array element type. The runtime arm compiled fine; the break was in
    the unreachable case 0 / default arms that still must compile.
    
    Emit `global::System.Array.Empty<T>()` instead, which is valid for both scalar
    and array element types and is allocation-free.
    
    Adds a compile/runtime guard (TUnit.TestProject/Bugs/6150) passing in both
    source-gen and reflection modes, plus a source-gen snapshot test. Regenerates
    the affected snapshots (new X[0] -> Array.Empty<X>()).
    thomhurst authored Jun 3, 2026
    Configuration menu
    Copy the full SHA
    7f1634a View commit details
    Browse the repository at this point in the history
  5. +semver:minor - fix: dispose shared fixtures when only a subset of co…

    …nsuming tests runs (#6156)
    
    * fix: dispose shared fixtures when only a subset of consuming tests runs
    
    Shared-object reference counts were incremented at build time for every
    built test, but only decremented when a test executed. Any test that was
    built but filtered out post-build (an [Explicit] sibling, a single
    [Arguments] case selected by an IDE uid filter, or all tests during a
    discovery-only request) left the count above zero, so PerTestSession /
    PerClass / PerAssembly / Keyed fixtures never had DisposeAsync called.
    
    - Move argument registration (shared-object creation + ref counting) from
      TestBuilder.BuildTestAsync to the post-filter TestFilterService.RegisterTest,
      so counts only include tests that will execute
    - Skip argument registration entirely for discovery-only requests; discovery
      no longer constructs fixtures as a side effect
    - Register dynamic tests (AddDynamicTest / CreateTestVariant) explicitly,
      since they bypass the discovery pipeline registration
    - Sweep-dispose any still-tracked objects and reset TestDataContainer at
      run-session end, so a later run request in the same process (IDE server
      mode) gets fresh fixtures instead of disposed ones
    
    Fixes #6151
    
    * refactor: remove dead ClearStaticTracking superseded by DisposeAndClearStaticTrackingAsync
    
    * fix: route static property disposal through ObjectTracker to prevent double-dispose
    
    Review feedback on #6156: DisposeStaticPropertiesAsync disposed directly via
    Disposer, leaving the +1 tracking entry from TrackStaticProperties in
    s_trackedObjects — the new session-end sweep would then dispose the same
    object a second time. Untracking instead decrements to zero, disposes once,
    and removes the entry.
    
    Also: reset Bug6151 fixture static counters after writing the marker (per-run
    counts in long-lived server processes), document why
    DisposeAndClearStaticTrackingAsync is an instance method, and add a warning
    comment on the unregistered DiscoverTestsFullyStreamingAsync path.
    thomhurst authored Jun 3, 2026
    Configuration menu
    Copy the full SHA
    ad66357 View commit details
    Browse the repository at this point in the history
Loading