Skip to content

Release v5.0.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 20:05
36208fd

Summary

Cratis Specifications 5.0 makes every package behave the same way: one specification lifecycle per class, one set of assertions with the same failure messages, readable names, and one switch for the analyzers. It targets .NET 10 only. Read the upgrade guide before upgrading.

Added

  • Shared resources and isolation leases (experimental): start a database or container once per test session and give each specification its own lease. Opt in with CratisSpecificationsSharedResources=true. See Shared resources. (#75)
  • Phase timings: report how long Establish, Because and Destroy take, flag slow phases and write a JSON timings file. See Phase timings. (#76)
  • The native runner prints a readable console tree and writes Markdown, JSON and GitHub summary reports. See Runner output and reports. (#79)
  • CratisSpecificationsRuntimeDefaults=true opts into runtime settings tuned for specification runs, and CratisSpecificationsParallelFixtures=true runs NUnit fixtures in parallel. Both are off by default. See Running specifications fast. (part of #74)
  • [PerFactSpecificationLifecycle] can be applied to a single class. (part of #74)
  • The native runner reports CRSPEC0011 as a warning when it has to call a lifecycle method through reflection, which is not trim or AOT safe. (part of #77)

Changed

  • All packages target net10.0 only. Specification projects on .NET 8 or .NET 9 stay on 4.x. (part of #74)
  • xUnit v2 and v3 run Establish and Because once per specification class by default, as NUnit, TUnit and the native runner already did. Remove any hand-written [assembly: Xunit.TestFramework(...)] that registers Cratis Specifications; opt a class, assembly or project out with [PerFactSpecificationLifecycle] or CratisSpecificationsSharedLifecycle=false. (part of #74)
  • CRSPEC0008 (a fact modifies the shared specification context) is an error. Move the change into Establish or Because, or opt the class out of the shared lifecycle. (part of #74)
  • Specifications show readable names in every package (Author › when registering › should keep the name). Set CratisSpecificationsReadableNames=false to keep the original names. (part of #74)
  • The Should* assertions and SpecificationAssertionException live in Cratis.Specifications and behave the same in every package; types are forwarded, so recompile against 5.0. Keep Cratis.Specifications and the framework package on the same version. (part of #74)
  • Assertions taking Predicate<T> take Func<T, bool>, and NUnit 4 ShouldEqual(params) compares in order; use ShouldEqualInAnyOrder for any order. (part of #74)
  • The public API carries nullable annotations, and the NUnit dictionary assertions require non-nullable key types. (part of #74)
  • The native runner's CRSPEC0010 (async void fact or lifecycle method) is an error. (part of #74)
  • The CRSPEC analyzers ship only in Cratis.Specifications; turn them off for every package with CratisSpecificationsAnalyzers. ExcludeAssets="analyzers" on a framework package no longer removes them. (part of #74)
  • Assertion failures are created without reflection, so the assertions work in trimmed and AOT-compiled test hosts. (part of #74)

Removed

  • The CratisSpecificationsWarnOnSharedContextMutation MSBuild property. Set the CRSPEC0008 severity in .editorconfig instead. (part of #74)