Introduction

TinyBDD is a tiny, fluent BDD helper for .NET tests. It gives you a clean Given/When/Then style without tying you to a specific test framework.

TinyBDD

Why TinyBDD

  • Tiny: a small core you can read in minutes
  • Fluent: expressive chains for Given, When, Then, And, But
  • Pragmatic: first-class adapters for xUnit, NUnit, and MSTest, but works fine without them

Core ideas

  • Two entry points
    • Explicit: create a ScenarioContext with Bdd.CreateContext and pass it around
    • Ambient: set Ambient.Current (or inherit a TinyBDD base class) and use Flow
  • Cross-framework: adapters only handle output and tag bridging; assertions and flow stay the same
  • Minimal assertions: bring your favorite assertion library; TinyBDD only needs a bool predicate or action per step

What a scenario looks like

  • Explicit (no base class required):
var ctx = Bdd.CreateContext(this); // reads [Feature]/[Scenario] and method/test attributes
await Bdd.Given(ctx, "numbers", () => new[]{1,2,3})
         .When("sum", (arr, _) => Task.FromResult(arr.Sum()))
         .Then("> 0", sum => sum > 0)
         .AssertPassed();
  • Ambient (inherit a base class or set Ambient.Current):
await Given(() => 1)
      .When("double", x => x * 2)
      .Then("== 2", v => v == 2)
      .AssertPassed();

Attributes and tags

  • [Feature] on a class gives a friendly feature name (and optional description)
  • [Scenario] on a test method provides a friendly scenario name and optional tags
  • [Tag] on classes or methods adds tags; adapters forward tags to your test framework’s trait/category output

Assertions made simple

  • Action-based: Then("works", () => Task.CompletedTask)
  • Predicate-based: Then("x == 2", v => v == 2) — throws BddAssertException on false
  • With or without CancellationToken, and available for And/But too

Reporting

  • Base classes emit Gherkin-style output automatically to the framework’s test log
  • Manual reporting: GherkinFormatter.Write(ctx, reporter) with an IBddReporter

Design notes

  • Steps are recorded in ScenarioContext.Steps as they execute
  • Failures are captured and rethrown as BddStepException with the original exception as InnerException
  • Async-friendly by default; chains are Task-based and CancellationToken-friendly where it helps

Where next

  • Read Getting Started to install and set up for your test framework
  • Browse the API reference for details and overloads