Table of Contents

Class TestBase

Namespace
TinyBDD
Assembly
TinyBDD.dll

Minimal, framework-agnostic base class for TinyBDD tests that wires the ambient ScenarioContext and offers convenience Given helpers.

public abstract class TestBase
Inheritance
TestBase
Derived
Inherited Members

Examples

xUnit (call CleanUp() in teardown):

using TinyBDD;
using TinyBDD.Xunit;
using Xunit;

public sealed class MyXunitBase : TestBase, IAsyncLifetime
{
    protected override IBddReporter Reporter { get; } = new XunitReporter();

    public Task InitializeAsync()
    {
        Ambient.Current.Value = Bdd.CreateContext(this, featureName: "Sample Feature");
        return Task.CompletedTask;
    }

    public Task DisposeAsync()
    {
        CleanUp(); // writes Gherkin summary, clears Ambient.Current
        return Task.CompletedTask;
    }
}

public sealed class SampleTests : MyXunitBase
{
    [Fact]
    public async Task Demo()
    {
        await Given("a number", () => 2)
            .When("double it", x => x * 2)
            .Then("equals 4", v => v == 4);

        Scenario.AssertPassed();
    }
}

MSTest (use [TestInitialize]/[TestCleanup]):

using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public sealed class MyMsTestBase : TestBase
{
    protected override IBddReporter Reporter { get; } = new MsTestReporter(TestContext!);
    public TestContext? TestContext { get; set; }

    [TestInitialize]
    public void SetUp()
        => Ambient.Current.Value = Bdd.CreateContext(this, featureName: "Feature");

    [TestCleanup]
    public void TearDown() => CleanUp();
}

NUnit (use [SetUp]/[TearDown]):

using NUnit.Framework;

public sealed class MyNUnitBase : TestBase
{
    protected override IBddReporter Reporter { get; } = new NUnitReporter();

    [SetUp]
    public void SetUp()
        => Ambient.Current.Value = Bdd.CreateContext(this, featureName: "Feature");

    [TearDown]
    public void TearDown() => CleanUp();
}

Remarks

TestBase centralizes TinyBDD test wiring for any unit-test framework (xUnit, NUnit, MSTest). It expects a derived type (or framework-specific base) to set Current to a live ScenarioContext before a test runs, and to call CleanUp() afterward (typically in teardown).

All Given overloads delegate to Flow which in turn forwards to Bdd using the current ambient context. If the ambient context is not set, an InvalidOperationException is thrown when invoking any step.

The base also exposes From() to start chains against an explicit ScenarioContext—useful when composing helper methods that construct sub-chains without relying on global ambient state.

Properties

BackgroundExecuted

Gets a value indicating whether background steps have been executed.

protected bool BackgroundExecuted { get; }

Property Value

bool

BackgroundState

Gets or sets the background state captured after ExecuteBackgroundAsync(CancellationToken) completes.

protected object? BackgroundState { get; }

Property Value

object

Remarks

This property is populated by ExecuteBackgroundAsync(CancellationToken) after running the background steps configured in ConfigureBackground().

FeatureSetupExecuted

Gets a value indicating whether feature setup has been executed.

protected bool FeatureSetupExecuted { get; set; }

Property Value

bool

FeatureState

Gets or sets the feature state captured after ExecuteFeatureSetupAsync(CancellationToken) completes.

protected object? FeatureState { get; set; }

Property Value

object

Remarks

This property is populated by ExecuteFeatureSetupAsync(CancellationToken) after running the feature setup steps configured in ConfigureFeatureSetup(). Feature state is shared across all scenarios in the test class.

Reporter

The reporter used to emit scenario output (e.g., Gherkin-style summaries) at cleanup. Framework-specific base classes should provide an appropriate implementation.

protected abstract IBddReporter Reporter { get; }

Property Value

IBddReporter

Scenario

The current ScenarioContext for the running test, sourced from Current. This is non-null during a properly initialized test.

protected ScenarioContext Scenario { get; }

Property Value

ScenarioContext

Methods

CleanUp()

Writes a concise Gherkin-style run summary (via GherkinFormatter) if a ScenarioContext is present, then clears Current.

protected void CleanUp()

Remarks

Call this from your framework teardown hook (e.g., xUnit DisposeAsync, MSTest [TestCleanup], or NUnit [TearDown]). It is safe to call even if no scenario was started (no-op aside from clearing ambient state).

ConfigureBackground()

Override to configure background steps that run before each scenario.

protected virtual ScenarioChain<object>? ConfigureBackground()

Returns

ScenarioChain<object>

A ScenarioChain<T> representing the background steps, or null if no background is needed.

Examples

protected override ScenarioChain<object>? ConfigureBackground()
{
    return Given("a database connection", () => new DbConnection())
        .And("test data seeded", conn => { SeedData(conn); return conn; });
}

Remarks

Background steps are executed once before each test method by calling ExecuteBackgroundAsync(CancellationToken). The final value from the chain is stored in BackgroundState and can be accessed via GivenBackground<T>().

Override this method in your test class to define shared setup steps. The background chain should not call AssertPassed(); that is handled automatically by ExecuteBackgroundAsync(CancellationToken).

ConfigureFeatureSetup()

Override to configure feature-level setup steps that run once before any scenarios.

protected virtual ScenarioChain<object>? ConfigureFeatureSetup()

Returns

ScenarioChain<object>

A ScenarioChain<T> representing the feature setup steps, or null if no feature setup is needed.

Examples

protected override ScenarioChain<object>? ConfigureFeatureSetup()
{
    return Given("test server started", () => new TestServer())
        .And("database seeded", server => { server.SeedData(); return server; });
}

Remarks

Feature setup steps are executed once before any test method runs in the test class. The final value from the chain is stored in FeatureState and can be accessed from all scenarios.

This is useful for expensive setup operations that can be shared across multiple scenarios, such as creating a test database connection, initializing a web server, or loading test data.

ConfigureFeatureTeardown()

Override to configure feature-level teardown steps that run once after all scenarios complete.

protected virtual ScenarioChain<object>? ConfigureFeatureTeardown()

Returns

ScenarioChain<object>

A ScenarioChain<T> representing the feature teardown steps, or null if no feature teardown is needed.

Examples

protected override ScenarioChain<object>? ConfigureFeatureTeardown()
{
    if (FeatureState is TestServer server)
    {
        return Given("cleanup server", () => server)
            .And("dispose", s => { s.Dispose(); return s; });
    }
    return null;
}

Remarks

Feature teardown steps are executed once after all test methods in the test class complete. Use this to clean up expensive resources initialized in ConfigureFeatureSetup().

ExecuteBackgroundAsync(CancellationToken)

Executes the background steps configured in ConfigureBackground().

protected Task ExecuteBackgroundAsync(CancellationToken ct = default)

Parameters

ct CancellationToken

Optional cancellation token.

Returns

Task

A task representing the asynchronous operation.

Remarks

Call this method from your test framework's initialization hook (e.g., [TestInitialize], [SetUp], or InitializeAsync) after setting up the ambient context.

The final value from the background chain is captured in BackgroundState.

ExecuteFeatureSetupAsync(CancellationToken)

Executes the feature setup steps configured in ConfigureFeatureSetup().

protected Task ExecuteFeatureSetupAsync(CancellationToken ct = default)

Parameters

ct CancellationToken

Optional cancellation token.

Returns

Task

A task representing the asynchronous operation.

Remarks

Call this method from your test framework's one-time initialization hook (e.g., xUnit IAsyncLifetime.InitializeAsync with static state, MSTest [ClassInitialize], or NUnit [OneTimeSetUp]).

The final value from the feature setup chain is captured in FeatureState.

ExecuteFeatureTeardownAsync(CancellationToken)

Executes the feature teardown steps configured in ConfigureFeatureTeardown().

protected Task ExecuteFeatureTeardownAsync(CancellationToken ct = default)

Parameters

ct CancellationToken

Optional cancellation token.

Returns

Task

A task representing the asynchronous operation.

Remarks

Call this method from your test framework's one-time cleanup hook (e.g., xUnit IAsyncLifetime.DisposeAsync with static state, MSTest [ClassCleanup], or NUnit [OneTimeTearDown]).

From()

Creates a helper bound to the current ambient Scenario for starting chains without relying on static Flow methods in downstream helpers.

protected FromContext From()

Returns

FromContext

A FromContext tied to Scenario.

From(ScenarioContext)

Creates a helper for starting chains from an explicit ScenarioContext.

protected FromContext From(ScenarioContext ctx)

Parameters

ctx ScenarioContext

The scenario context to use for subsequent calls.

Returns

FromContext

A FromContext bound to ctx.

GivenBackground<T>()

Starts a Given step that continues from the background state.

protected ScenarioChain<T> GivenBackground<T>() where T : class

Returns

ScenarioChain<T>

A ScenarioChain<T> starting with the background state.

Type Parameters

T

The expected type of the background state.

Examples

[Test]
public async Task TestWithBackground()
{
    await GivenBackground<DbConnection>()
        .When("querying users", conn => conn.Query<User>("SELECT * FROM Users"))
        .Then("users exist", users => users.Any())
        .AssertPassed();
}

Exceptions

InvalidOperationException

Thrown if background steps have not been executed or the state is null.

GivenBackground<T>(string)

Starts a Given step that continues from the background state with a custom title.

protected ScenarioChain<T> GivenBackground<T>(string title) where T : class

Parameters

title string

A custom title for the Given step.

Returns

ScenarioChain<T>

A ScenarioChain<T> starting with the background state.

Type Parameters

T

The expected type of the background state.

GivenFeature<T>()

Starts a Given step that continues from the feature state.

protected ScenarioChain<T> GivenFeature<T>() where T : class

Returns

ScenarioChain<T>

A ScenarioChain<T> starting with the feature state.

Type Parameters

T

The expected type of the feature state.

Examples

[Test]
public async Task TestWithFeature()
{
    await GivenFeature<TestServer>()
        .When("sending request", server => server.Get("/api/users"))
        .Then("response is ok", response => response.StatusCode == 200)
        .AssertPassed();
}

Exceptions

InvalidOperationException

Thrown if feature setup has not been executed or the state is null.

GivenFeature<T>(string)

Starts a Given step that continues from the feature state with a custom title.

protected ScenarioChain<T> GivenFeature<T>(string title) where T : class

Parameters

title string

A custom title for the Given step.

Returns

ScenarioChain<T>

A ScenarioChain<T> starting with the feature state.

Type Parameters

T

The expected type of the feature state.

Given<T>(Func<CancellationToken, Task<T>>)

Starts a token-aware Given step with a default title and asynchronous setup.

protected ScenarioChain<T> Given<T>(Func<CancellationToken, Task<T>> setup)

Parameters

setup Func<CancellationToken, Task<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(Func<CancellationToken, ValueTask<T>>)

Starts a token-aware Given step with a default title and ValueTask<TResult> setup.

protected ScenarioChain<T> Given<T>(Func<CancellationToken, ValueTask<T>> setup)

Parameters

setup Func<CancellationToken, ValueTask<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(Func<Task<T>>)

Starts a Given step with a default title and asynchronous setup.

protected ScenarioChain<T> Given<T>(Func<Task<T>> setup)

Parameters

setup Func<Task<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(Func<ValueTask<T>>)

Starts a Given step with a default title and ValueTask<TResult> setup.

protected ScenarioChain<T> Given<T>(Func<ValueTask<T>> setup)

Parameters

setup Func<ValueTask<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(Func<T>)

Starts a Given step with a default title and synchronous setup.

protected ScenarioChain<T> Given<T>(Func<T> setup)

Parameters

setup Func<T>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(string, Func<CancellationToken, Task<T>>)

Starts a token-aware Given step with an explicit title and asynchronous setup.

protected ScenarioChain<T> Given<T>(string title, Func<CancellationToken, Task<T>> setup)

Parameters

title string
setup Func<CancellationToken, Task<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(string, Func<CancellationToken, ValueTask<T>>)

Starts a token-aware Given step with an explicit title and ValueTask<TResult> setup.

protected ScenarioChain<T> Given<T>(string title, Func<CancellationToken, ValueTask<T>> setup)

Parameters

title string
setup Func<CancellationToken, ValueTask<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(string, Func<Task<T>>)

Starts a Given step with an explicit title and asynchronous setup.

protected ScenarioChain<T> Given<T>(string title, Func<Task<T>> setup)

Parameters

title string
setup Func<Task<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Remarks

Use this overload when the initial value requires async I/O.

Given<T>(string, Func<ValueTask<T>>)

Starts a Given step with an explicit title and ValueTask<TResult> setup.

protected ScenarioChain<T> Given<T>(string title, Func<ValueTask<T>> setup)

Parameters

title string
setup Func<ValueTask<T>>

Returns

ScenarioChain<T>

Type Parameters

T

Given<T>(string, Func<T>)

Starts a Given step with an explicit title and synchronous setup.

protected ScenarioChain<T> Given<T>(string title, Func<T> setup)

Parameters

title string

Human-friendly step title.

setup Func<T>

Synchronous factory for the initial value.

Returns

ScenarioChain<T>

A ScenarioChain<T> for chaining When/Then.

Type Parameters

T

Type produced by the setup function.

See Also