TinyBDD.NUnit
0.1.13
dotnet add package TinyBDD.NUnit --version 0.1.13
NuGet\Install-Package TinyBDD.NUnit -Version 0.1.13
<PackageReference Include="TinyBDD.NUnit" Version="0.1.13" />
<PackageVersion Include="TinyBDD.NUnit" Version="0.1.13" />
<PackageReference Include="TinyBDD.NUnit" />
paket add TinyBDD.NUnit --version 0.1.13
#r "nuget: TinyBDD.NUnit, 0.1.13"
#:package TinyBDD.NUnit@0.1.13
#addin nuget:?package=TinyBDD.NUnit&version=0.1.13
#tool nuget:?package=TinyBDD.NUnit&version=0.1.13
TinyBDD
NuGet Packages:
Package | Version | Downloads |
---|---|---|
TinyBDD | ||
TinyBDD.MSTest | ||
TinyBDD.Xunit | ||
TinyBDD.NUnit |
TinyBDD is a minimal, fluent Behavior-Driven Development library for .NET.
It provides a lightweight Given
/ When
/ Then
syntax with optional And
/ But
chaining, supporting both sync and async steps.
It is designed to:
- Be framework-agnostic (works with MSTest, xUnit, NUnit, etc.).
- Keep scenarios clear and concise without heavy DSLs or external tooling.
- Support async and sync predicates for maximum flexibility.
- Integrate with existing test runners’ output for easy step visibility.
Features
Readable BDD syntax:
await Given("a number", () => 5) .When("doubled", x => x * 2) .Then(">= 10", v => v >= 10) .And("<= 20", v => v <= 20) .But("!= 15", v => v != 15) .AssertPassed();
Sync & Async Support:
Func<T>
/Func<T, bool>
Func<Task<T>>
/Func<T, Task<bool>>
- Token-aware variants for advanced control.
And
/But
chaining with correct step names in output:Given start [OK] When double [OK] Then >= 10 [OK] And <= 20 (async) [OK] But != 11 [OK]
Test framework adapters:
- MSTest:
TinyBddMsTestBase
,MSTestBddReporter
,MSTestTraitBridge
- xUnit:
TinyBddXunitBase
,XunitTraitBridge
,XunitBddReporter
- NUnit:
TinyBddNUnitBase
,NUnitTraitBridge
,NUnitBddReporter
- Automatically logs steps and tags to the test output.
- MSTest:
Installation
Add TinyBDD via NuGet:
dotnet add package TinyBDD
For MSTest:
dotnet add package TinyBDD.MSTest
For NUnit:
dotnet add package TinyBDD.NUnit
For xUnit:
dotnet add package TinyBDD.Xunit
Basic Usage
MSTest Example
using TinyBDD.MSTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[Feature("Math")]
[TestClass]
public class MathTests : TinyBddMsTestBase
{
[Scenario("Doubling numbers")]
[TestMethod]
public async Task DoublingScenario()
{
await Given("start with 5", () => 5)
.When("doubled", x => x * 2)
.Then("should be 10", v => v == 10)
.AssertPassed();
}
}
NUnit Example
using TinyBDD.NUnit;
using NUnit.Framework;
[Feature("Math")]
public class MathTests : TinyBddNUnitBase
{
[Scenario("Doubling numbers")]
[Test]
public async Task DoublingScenario()
{
await Given("start with 5", () => 5)
.When("doubled", x => x * 2)
.Then("should be 10", v => v == 10)
.AssertPassed();
}
}
xUnit Example
using TinyBDD.Xunit;
using Xunit;
[Feature("Math")]
public class MathTests : TinyBddXunitBase
{
[Scenario("Doubling numbers")]
[Fact]
public async Task DoublingScenario()
{
await Given("start with 5", () => 5)
.When("doubled", x => x * 2)
.Then("should be 10", v => v == 10)
.AssertPassed();
}
}
Step Types
Step | Purpose | Example |
---|---|---|
Given |
Initial state / setup | .Given("start", () => 5) |
When |
Action / event | .When("doubled", x => x * 2) |
Then |
Assertion | .Then(">= 10", v => v >= 10) |
And |
Additional assertion after Then or When |
.And("<= 20", v => v <= 20) |
But |
Additional assertion phrased negatively | .But("!= 15", v => v != 15) |
All step types have sync and async overloads.
Tags
Tags can be added for reporting and filtering:
ctx.AddTag("smoke");
ctx.AddTag("fast");
In xUnit, tags are logged to the test output:
[TinyBDD] Tag: smoke
[TinyBDD] Tag: fast
Asserting Pass/Fail
TinyBDD tracks step results internally. At the end of the scenario, call one of the following methods:
Scenario.AssertPassed();
Scenario.AssertFailed();
// or use the fluent syntax:
await Given("one", () => 1)
.When("add one", x => x + 1)
.Then("equals two", v => v == 2)
.AssertPassed();
await Given("one", () => 1)
.When("add one", x => x + 1)
.Then("equals elevent", v => v == 11)
.AssertFailed();
This ensures that all steps passed and throws if any failed.
Philosophy
TinyBDD was created with a few guiding principles:
Focus on readability, not ceremony
Steps should read like plain English and map directly to Gherkin-style thinking, but without requiring.feature
files, extra compilers, or DSL preprocessors.Code is the spec
Instead of writing a separate Gherkin text file, you write directly in C# using a fluent API that mirrorsGiven
→When
→Then
→And
→But
.
Your unit test runner output is the human-readable spec.Stay out of your way
TinyBDD is not an opinionated test framework; it’s a syntax layer that integrates with MSTest, xUnit, or NUnit and leaves assertions, test discovery, and reporting to them.
Gherkin-Style Output
When running a scenario, TinyBDD prints structured step output similar to Gherkin formatting.
For example:
await Given("start", () => 5)
.When("double", x => x * 2)
.Then(">= 10", v => v >= 10)
.And("<= 20 (async)", v => Task.FromResult(v <= 20))
.But("!= 11", v => v != 11)
.AssertPassed();
Test output:
Feature: Math
Scenario: Doubling numbers
Given start [OK] 0 ms
When double [OK] 0 ms
Then >= 10 [OK] 0 ms
And <= 20 (async) [OK] 0 ms
But != 11 [OK] 0 ms
If a step fails, you’ll see exactly which step failed, how long it took, and the exception message.
Why Not Use SpecFlow / Cucumber?
SpecFlow, Cucumber, and similar tools are powerful for large-scale BDD, but they:
- Require separate
.feature
files and a parser/runner. - Often introduce a disconnect between the feature file and the code that actually runs.
- Come with heavier setup and slower test discovery.
TinyBDD keeps everything in one place—your test class—while still producing clear, human-readable steps.
Minimal Example
For the smallest possible test:
await Given("one", () => 1)
.When("add one", x => x + 1)
.Then("equals two", v => v == 2)
.AssertPassed();
Output:
Given one [OK]
When add one [OK]
Then equals two [OK]
Async Philosophy
In TinyBDD, sync and async steps are equally first-class citizens.
If your step is synchronous, write it synchronously:
.When("double", x => x * 2) .Then("is 10", v => v == 10)
If your step needs async work:
.When("fetch from DB", async x => await db.GetAsync(x)) .Then("result exists", async v => Assert.NotNull(v))
You can even mix sync and async steps freely in the same scenario.
Output Style
TinyBDD always prints the BDD keyword for the step type (Given
, When
, Then
, And
, But
), the step title, the
result [OK]
/ [FAIL]
, and the elapsed time in milliseconds.
For failed steps, TinyBDD stops the scenario immediately and prints the exception:
Then equals two [FAIL] 1 ms
Expected: 2
Actual: 3
Recommended Usage
- One scenario per test method.
- Keep each step single-purpose—avoid hiding multiple unrelated actions in one step.
- Prefer creating functions, even local ones, to avoid unnecessary allocations, closure creation, garbage collection, and code cleanliness.
- Use
Scenario.AssertPassed()
or the fluentThenChain.AssertPassed()
at the end of each test to ensure every step was explicitly checked. - Use tags to group and filter tests.
License
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.