Skip to content
JasperFxPublic

About

Ready for the hardest integration testing jobs in .NET!

Resources

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

Bobcat — author, supervise, and run integration tests in .NET

Bobcat

Author, Supervise, and Run Integration Tests in .NET

Discord tests Nuget Package Nuget

Bobcat is a spec-driven integration testing framework for .NET and the successor to Storyteller. It is built for the hardest integration testing jobs: systems with databases, message brokers, background processing, and many moving parts.

  • Author specifications as ordinary xUnit.net, TUnit, NUnit or MSTest tests, and let Bobcat render them as readable specifications. A Roslyn source generator turns your step helpers and marker comments into recorded steps at compile time, with no runtime reflection.
  • Supervise a large suite so its results can be trusted. It can split the suite across worker processes, isolate resources per lane, retry within budgets, and report flakiness honestly instead of burying it. A suite can also stay resident, running the specifications a run console asks for.
  • Specify end to end. Executable specifications still read as requirements, and they can be scaffolded slice by slice from an Event Model. Bobcat has first-class support for the Critter Stack (Wolverine, Marten, Polecat and Fisher) through WolverineFx.Bobcat (Testing with Bobcat), while Bobcat itself takes no JasperFx or Wolverine dependency.

Your specifications are your test framework's own tests, so they show up in dotnet test, your IDE's Test Explorer, and CI like any other test.

Access the docs here. For any of your questions, including about the rest of the Critter Stack, join our Discord channel. It is the best way to reach us quickly. You can also raise questions or report problems through GitHub Issues.

Support Plans

JasperFx logo

While Bobcat is open source, JasperFx Software offers paid support and consulting contracts for Bobcat.

Help us keep working on this project 💚

Become a Sponsor on GitHub by sponsoring monthly or one time.

Packages

Package What it is for
Bobcat The runtime: the projected specification engine, verification, rendering, the monitor wire and the resilience vocabulary. No JasperFx or Wolverine dependency; the Critter Stack vocabulary (CritterStackScenario) ships in WolverineFx.Bobcat from the Wolverine repository
Bobcat.Generators The source generator: step interceptors, marker-comment steps, the Event Model fold and compile-time table checks
Bobcat.Supervisor Drives any MTP test host as worker processes, with retry, isolation, and parallel lanes
WolverineFx.Bobcat Published from the Wolverine repository: Given/When/Then for Wolverine handlers and event-sourced slices, documented at Testing with Bobcat. Replaces the retired Bobcat.Wolverine
Bobcat.Xunit / Bobcat.TUnit / Bobcat.NUnit / Bobcat.MSTest Renders an existing xUnit.net v3, TUnit, NUnit or MSTest suite as specifications, without changing how it runs
Bobcat.EventModel Imports the Event Modeling platform's own format and writes it as C# stub types plus an EventModelDefinition
Bobcat.Console The bobcat global tool: reads, validates, and converts Event Model files, and keeps a suite Bobcat does not own available to a run console
dotnet add package Bobcat

See Getting Started for wiring up a first spec project.

Working with the Code

Before getting started you will need the following in your environment:

1. .NET SDK 10.0+

Available here. The repository builds with the .NET 10 SDK. Most packages target both net9.0 and net10.0; Bobcat.Generators targets netstandard2.0 because it is a Roslyn analyzer.

2. Docker

A few integration tests need a real PostgreSQL database. The fastest way to get one is the docker-compose.yml at the repository root:

docker compose up -d

or, through the build (see below), ./build.sh Docker. Postgres is published on 5445, so it will not collide with one you may already run.

To use your own database instead, set BOBCAT_POSTGRES to its connection string. Without a database, the tests that need one skip locally and say so. On CI they never skip, so a missing database fails the build instead of passing silently.

3. Node.js (only for the documentation)

A current LTS release (the docs workflow uses Node 24), to run the VitePress documentation site locally. See Documentation.

The Solution

bobcat.slnx at the repository root is the solution for everything under src/. It is the only solution file at the root, so dotnet build and dotnet test pick it up without being told.

  • src/ contains the packages, their test projects, and the sample hosts the tests drive (Bobcat.Xunit.Samples, Bobcat.Supervisor.ProjectedWorker).
  • The sample applications moved to the Wolverine repository with the Critter Stack vocabulary in 1.0.0-rc.2 (#744).
  • spikes/ contains throwaway research code, kept for reproducibility, with its own solution.
  • build/ is the Nuke build project described below.
  • docs/ is the documentation site.

Package versions are managed centrally with NuGet's Central Package Management: src/Directory.Packages.props holds every version, and a PackageReference never carries its own Version. Its header comment says which projects may reference JasperFx (only the tools).

Tooling

  • Tests use xUnit.net v3, Shouldly, and NSubstitute, and run on Microsoft.Testing.Platform rather than VSTest. Every test project is a self-executing test host.
  • Nuke is used for build automation.
  • VitePress builds the documentation site.

Build Commands

The Nuke build is the single definition of what CI does. Every GitHub Actions workflow calls it, so a green ./build.sh CI on your machine means the same thing as a green push.

Description Windows Commandline PowerShell Linux / macOS Shell DotNet CLI
Restore, build and test (the default) build.cmd build.ps1 ./build.sh dotnet run --project build/Build.csproj
Start the Docker services build.cmd docker build.ps1 docker ./build.sh docker dotnet run --project build/Build.csproj -- docker
Everything the tests workflow runs build.cmd ci build.ps1 ci ./build.sh ci dotnet run --project build/Build.csproj -- ci
The TUnit-hosted tests CI leaves out for now (#521) build.cmd tunittests build.ps1 tunittests ./build.sh tunittests dotnet run --project build/Build.csproj -- tunittests
Pack every package to artifacts/packages build.cmd pack build.ps1 pack ./build.sh pack dotnet run --project build/Build.csproj -- pack
List every target and parameter build.cmd --help build.ps1 --help ./build.sh --help dotnet run --project build/Build.csproj -- --help

Targets combine, so ./build.sh docker ci starts the services and then runs the full CI build. The build uses the Debug configuration locally and Release on a CI server. Override it with --configuration Release.

You can also work with the solution directly using the dotnet CLI:

dotnet build
dotnet test

# Tests run on Microsoft.Testing.Platform; global.json puts `dotnet test` in its MTP mode, so the
# project is `--project` and test-host options go straight on the command line (no `--`)
dotnet test --project src/Bobcat.Tests/ --filter-class "*PipelineTests"

Note: ./build.sh docker starts the compose services. The Marten-backed tests and the samples that needed Postgres moved to the Wolverine repository (#744).

Continuous Integration

CI is GitHub Actions only, and each workflow is a thin wrapper around the Nuke build:

Workflow Runs When
tests.yml ./build.sh CI, with a Postgres service: the suite, then the results schema checked against the last release's every push
ui-smoke.yml ./build.sh UiSmoke: packs the bobcat tool with its UI, starts bobcat ui and checks it, Chromium included pushes touching src/ or build/
ui-frontend.yml ./build.sh UiContracts, then typecheck, Vitest and the Vite build of the bobcat ui page pushes touching src/Bobcat.Ui.FrontEnd/, src/Bobcat.Ui/Contracts/ or build/
publish.yml ./build.sh CI Pack, then pushes to nuget.org v* tags, or manually
docs.yml builds and deploys the documentation site manually

To change what CI does, change build/Build.cs, build/UiSmoke.cs or build/Contracts.cs, not the workflows.

Two files are generated and never committed, so that parallel branches touching the wire do not conflict on them: the frontend's TypeScript contracts (src/Bobcat.Ui.FrontEnd/src/messages/monitor-events.ts and relayRoutes.ts) and the results file's JSON Schema. After one dotnet build, the frontend's npm ci, npm run dev, npm test and npm run build generate the TypeScript themselves; so does ./build.sh UiContracts. ./build.sh Pack generates both.

Documentation

All the documentation is written in Markdown in the docs/ directory and published as a static site at bobcat.jasperfx.net using VitePress. The Markdown in docs/ is the site. Navigation and sidebars are defined in docs/.vitepress/config.mjs.

To run the docs locally, with auto-refresh on any changes:

npm install
npm run docs

To check a production build before publishing:

npm run docs:build     # builds to docs/.vitepress/dist
npm run docs:preview   # serves that build locally

The site is deployed by running the docs.yml workflow manually from the Actions tab. Nothing deploys the documentation automatically on push.

Brand

Project graphics and the "Ember on Ink" color tokens live in docs/public/ and docs/.vitepress/theme/style.css.

License

Copyright © Jeremy D. Miller and contributors.

Bobcat is provided as-is under the MIT license. For more information see LICENSE.

Code of Conduct

This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.

About

Ready for the hardest integration testing jobs in .NET!

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages