You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make Cratis.Specifications.Runner a supported, non-experimental package so Cratis repositories can move off xUnit where it is faster. #65 evaluated the runner; this tracks what remains before graduating it.
Remaining
IDE support (decided: no manual IDE verification): document the supported IDEs from Microsoft's and JetBrains' Microsoft.Testing.Platform documentation (Visual Studio 2022 17.14+, Visual Studio 2026, Rider with Testing Platform discovery enabled, VS Code C# Dev Kit), and rely on the runner's conformance to the platform's discovery and execution contract, covered by specs.
Lifecycle consistency: identical semantics to the other packages for setup/act/teardown failures, cancellation and Stop, shared contract specs across packages.
Decision on lifecycle consistency (teardown failures): the native runner follows xUnit, xUnit v3, NUnit 4 and NUnit 5. A failure in Destroy or disposal is reported as its own failed result for the specification class and fails the run, and the facts that already completed keep their outcomes. Today the runner rewrites every non-skipped fact to failed; that changes. TUnit differs because its engine attaches after-class hook failures to the last test of the class; that is engine-owned and is documented as a known difference rather than changed. Setup and act failures already match: facts fail, Because and fact bodies do not run, and teardown still runs once.
The Native AOT publish took 32.8 s with 0 AOT or trim warnings. Executed AOT is roughly 10x faster than the runner under JIT.
Under JIT, the runner matches xUnit v3's own console runner on CPU (1.90 s vs 1.90 s) but is about 0.27 s slower on wall time. It beats xUnit v3 on Microsoft.Testing.Platform, the route IDEs and dotnet test use, by about 35% on wall time and 37% on CPU.
Graduation still needs evidence from a real repository: the runner variants of a Fundamentals spec project with identical test identities and outcomes. The experimental marker stays until then.
Second review of the teardown decision (independent GPT-6.1 Sol review against the code): agreed. xUnit (Source/XUnit/SpecificationTestClassRunner.cs:68-75), xUnit v3 (Source/XUnit.v3/SpecificationTestClassRunner.cs:45-51) and NUnit/NUnit5 (Source/NUnit/Specification.cs:63-73, shared by NUnit5) all report a cleanup failure at the class or suite boundary and keep the outcomes of completed facts, and the runner now does the same (Source/Runner/Execution/SpecificationClassRunner.cs:76-88). Precision: the boundary matches, but the result shape differs by framework. xUnit emits cleanup messages, NUnit fails the suite, and the runner adds one test node. TUnit 1.76.0 attaches cleanup errors to the completing test (TestExecutor.cs:697-724). Deciding without a human was appropriate because the runner is experimental.
Same-host Fundamentals trial completed: https://github.com/Cratis/Fundamentals/actions/runs/40183739733 (baseline cadf8e452b, candidates Specifications 5.0.3). Independent review rechecked all 36 TRXs and all 30 raw timing files: 793 Fundamentals and 94 OpenTelemetry identities/outcomes match after theory-row normalization, all passed. Five interleaved repetitions on one host: median wall V0/V4/V6 = 4.13/1.84/1.38 s for Fundamentals and 2.50/1.39/1.13 s for OpenTelemetry. V0 is current mtp-off/VSTest, V4 xUnit v3 MTP, V6 native runner JIT. The runner is 25%/19% faster than xUnit MTP on these workloads, not universally.
Graduation remains blocked: generated/reflection lifecycle cancellation needs alignment and verification; the lifecycle matrix must exercise each adapter; actual MTP Stop needs platform-level coverage. Fundamentals NativeAOT execution also remains blocked by Fundamentals#1217. The experimental marker stays.
Activity
woksin commentedon Oct 25, 2026
Decision on lifecycle consistency (teardown failures): the native runner follows xUnit, xUnit v3, NUnit 4 and NUnit 5. A failure in
Destroyor disposal is reported as its own failed result for the specification class and fails the run, and the facts that already completed keep their outcomes. Today the runner rewrites every non-skipped fact to failed; that changes. TUnit differs because its engine attaches after-class hook failures to the last test of the class; that is engine-owned and is documented as a known difference rather than changed. Setup and act failures already match: facts fail,Becauseand fact bodies do not run, and teardown still runs once.woksin commentedon Oct 25, 2026
Benchmark results for the graduation decision (run 40174768971 on main 1fd416b; GitHub-hosted ubuntu-24.04; 500 classes x 5 facts = 2,500 facts; 5 measured repetitions; default parallelism; Cratis suites). https://github.com/Cratis/Specifications/actions/runs/40174768971
dotnet testuse, by about 35% on wall time and 37% on CPU.Graduation still needs evidence from a real repository: the runner variants of a Fundamentals spec project with identical test identities and outcomes. The experimental marker stays until then.
woksin commentedon Oct 25, 2026
Second review of the teardown decision (independent GPT-6.1 Sol review against the code): agreed. xUnit (
Source/XUnit/SpecificationTestClassRunner.cs:68-75), xUnit v3 (Source/XUnit.v3/SpecificationTestClassRunner.cs:45-51) and NUnit/NUnit5 (Source/NUnit/Specification.cs:63-73, shared by NUnit5) all report a cleanup failure at the class or suite boundary and keep the outcomes of completed facts, and the runner now does the same (Source/Runner/Execution/SpecificationClassRunner.cs:76-88). Precision: the boundary matches, but the result shape differs by framework. xUnit emits cleanup messages, NUnit fails the suite, and the runner adds one test node. TUnit 1.76.0 attaches cleanup errors to the completing test (TestExecutor.cs:697-724). Deciding without a human was appropriate because the runner is experimental.woksin commentedon Oct 25, 2026
Same-host Fundamentals trial completed: https://github.com/Cratis/Fundamentals/actions/runs/40183739733 (baseline cadf8e452b, candidates Specifications 5.0.3). Independent review rechecked all 36 TRXs and all 30 raw timing files: 793 Fundamentals and 94 OpenTelemetry identities/outcomes match after theory-row normalization, all passed. Five interleaved repetitions on one host: median wall V0/V4/V6 = 4.13/1.84/1.38 s for Fundamentals and 2.50/1.39/1.13 s for OpenTelemetry. V0 is current mtp-off/VSTest, V4 xUnit v3 MTP, V6 native runner JIT. The runner is 25%/19% faster than xUnit MTP on these workloads, not universally.
Graduation remains blocked: generated/reflection lifecycle cancellation needs alignment and verification; the lifecycle matrix must exercise each adapter; actual MTP Stop needs platform-level coverage. Fundamentals NativeAOT execution also remains blocked by Fundamentals#1217. The experimental marker stays.
github-actions commentedon Oct 25, 2026
Closed by release v5.1.0.