### Quick Start Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/hosting.html A basic example demonstrating how to set up and run a workflow hosted service. ```APIDOC ## Quick Start ```csharp // Program.cs var builder = Host.CreateApplicationBuilder(args); builder.Services.AddTinyBddHosting(); builder.Services.AddWorkflowHostedService(); var host = builder.Build(); await host.RunAsync(); // StartupWorkflow.cs public class StartupWorkflow : IWorkflowDefinition { public string FeatureName => "Application Startup"; public string ScenarioName => "Initialize all services"; public string? FeatureDescription => "Ensures all dependencies are ready"; public async ValueTask ExecuteAsync(ScenarioContext context, CancellationToken ct) { await Bdd.Given(context, "configuration loaded", () => LoadConfig()) .When("database migrated", cfg => MigrateDatabase(cfg, ct)) .And("cache initialized", cfg => InitializeCache(cfg, ct)) .Then("system ready", _ => true); } } ``` ``` -------------------------------- ### Given with Synchronous Setup Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Use this overload to start a Given step with an explicit title and a synchronous setup function. ```csharp public static ScenarioChain Given(string title, Func setup)__ ``` -------------------------------- ### Quick Start Example Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/dependency-injection.html Demonstrates how to register TinyBDD services and use the IScenarioContextFactory within a service. ```APIDOC ## Quick Start ```csharp // In Startup.cs or Program.cs services.AddTinyBdd(); // In your service or controller public class OrderService { private readonly IScenarioContextFactory _contextFactory; public OrderService(IScenarioContextFactory contextFactory) { _contextFactory = contextFactory; } public async Task ProcessOrder(Order order) { var context = _factory.Create("Order Processing", "Process single order"); await Bdd.Given(context, "order received", () => order) .When("validated", o => ValidateOrder(o)) .When("saved to database", o => SaveOrder(o)) .Then("confirmation sent", o => SendConfirmation(o)); return new OrderResult { Success = context.Steps.All(s => s.Error == null) }; } } ``` ``` -------------------------------- ### Given with Async Task Setup Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Use this overload to start a Given step with an explicit title and an asynchronous setup function that returns a Task. ```csharp public static ScenarioChain Given(string title, Func> setup)__ ``` -------------------------------- ### Given with Synchronous Setup and State Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Starts a Given step with explicit state, using a synchronous setup function to avoid closure allocation. ```csharp public static ScenarioChain Given(string title, TState state, Func setup)__ ``` -------------------------------- ### Quick Start: Program.cs and StartupWorkflow.cs Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/hosting.html Configure the host builder to use TinyBDD and register a workflow hosted service. This example demonstrates a basic startup workflow. ```csharp // Program.cs var builder = Host.CreateApplicationBuilder(args); builder.Services.AddTinyBddHosting(); builder.Services.AddWorkflowHostedService(); var host = builder.Build(); await host.RunAsync(); // StartupWorkflow.cs public class StartupWorkflow : IWorkflowDefinition { public string FeatureName => "Application Startup"; public string ScenarioName => "Initialize all services"; public string? FeatureDescription => "Ensures all dependencies are ready"; public async ValueTask ExecuteAsync(ScenarioContext context, CancellationToken ct) { await Bdd.Given(context, "configuration loaded", () => LoadConfig()) .When("database migrated", cfg => MigrateDatabase(cfg, ct)) .And("cache initialized", cfg => InitializeCache(cfg, ct)) .Then("system ready", _ => true); } } ``` -------------------------------- ### Setup() Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Benchmarks.MultipleAssertionsBenchmark.html The Setup method is a global setup routine for the benchmark, likely used for initialization. ```APIDOC ## Method: Setup ### Description Global setup method for the benchmark. ### Method GET ### Endpoint N/A (Benchmark method) ``` -------------------------------- ### Implement NUnit TestBase Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Example implementation for NUnit using SetUp and TearDown attributes. ```csharp 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(); }__ ``` -------------------------------- ### Setup Method Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Benchmarks.StepPipelineBenchmark.html Global setup method for the benchmark. ```APIDOC ## Method Setup ### Attributes - `[GlobalSetup]` ### Signature `public void Setup()` ``` -------------------------------- ### Given with Async ValueTask Setup Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Starts a Given step with an explicit title and ValueTask setup. This is suitable for asynchronous operations that can complete synchronously. ```csharp protected ScenarioChain Given(string title, Func> setup)__ ``` -------------------------------- ### Given step methods Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.FromContext.html Methods for starting Given chains with various setup configurations, including synchronous/asynchronous execution and optional titles. ```csharp public ScenarioChain Given(Func> setup)__ ``` ```csharp public ScenarioChain Given(Func setup)__ ``` ```csharp public ScenarioChain Given(string title, Func> setup)__ ``` ```csharp public ScenarioChain Given(string title, Func setup)__ ``` -------------------------------- ### Setup Method Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Benchmarks.PipelineOptimizationBenchmark.html Global setup method for the benchmark class. ```APIDOC ## Setup ### Description Performs global setup operations required before running the benchmarks. ``` -------------------------------- ### Examples Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.AssemblySetupAttribute.html Examples demonstrating how to use the AssemblySetupAttribute. ```APIDOC ## Examples Example: Register a database fixture ```csharp using TinyBDD; [assembly: AssemblySetup(typeof(DatabaseFixture))] public class DatabaseFixture : AssemblyFixture { private TestDatabase? _db; public TestDatabase Database => _db!; protected override async Task SetupAsync(CancellationToken ct) { _db = new TestDatabase(); await _db.StartAsync(ct); } protected override async Task TeardownAsync(CancellationToken ct) { if (_db is not null) await _db.DisposeAsync(); } } ``` Example: Register multiple fixtures ```csharp [assembly: AssemblySetup(typeof(DatabaseFixture))] [assembly: AssemblySetup(typeof(WebServerFixture))] [assembly: AssemblySetup(typeof(MessageQueueFixture))] ``` ``` -------------------------------- ### Define Asynchronous Given Step with Example Data Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ScenarioOutlineBuilder-1.html Starts a scenario outline with an asynchronous Given step. This method accepts a title and an asynchronous setup function that receives example data and returns an initial value. ```csharp public ScenarioOutlineChain Given(string title, Func> setup) ``` -------------------------------- ### Given with Async Task Setup and State Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Starts a Given step with explicit state, using an asynchronous Task setup function to avoid closure allocation. ```csharp public static ScenarioChain Given(string title, TState state, Func> setup)__ ``` -------------------------------- ### Define Synchronous Given Step with Example Data Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ScenarioOutlineBuilder-1.html Starts a scenario outline with a synchronous Given step. This method accepts a title and a setup function that receives example data and returns an initial value. ```csharp public ScenarioOutlineChain Given(string title, Func setup) ``` -------------------------------- ### Implement xUnit TestBase Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Example implementation for xUnit using IAsyncLifetime for setup and teardown. ```csharp 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(); } }__ ``` -------------------------------- ### Global Setup Method Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Benchmarks.ExceptionHandlingBenchmark.html The global setup method for the benchmark class. This method is executed once before all benchmarks. ```csharp [GlobalSetup] public void Setup()__ ``` -------------------------------- ### Given step with seed value Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Bdd.html Signature for starting a Given step with a synchronous setup action and a seed value. ```csharp public static ScenarioChain Given(ScenarioContext ctx, Action setup, T seed)__ ``` -------------------------------- ### Given with Token-Aware Async Task Setup and State Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Starts a token-aware Given step with explicit state, using an asynchronous Task setup function to avoid closure allocation. ```csharp public static ScenarioChain Given(string title, TState state, Func> setup)__ ``` -------------------------------- ### Given Setup Overloads Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Various method signatures for initializing a Given step with different asynchronous, synchronous, and token-aware setup functions. ```csharp protected ScenarioChain Given(Func> setup) ``` ```csharp protected ScenarioChain Given(Func> setup) ``` ```csharp protected ScenarioChain Given(Func> setup) ``` ```csharp protected ScenarioChain Given(Func> setup) ``` ```csharp protected ScenarioChain Given(Func setup) ``` ```csharp protected ScenarioChain Given(string title, Func> setup) ``` ```csharp protected ScenarioChain Given(string title, Func> setup) ``` -------------------------------- ### MSTest Integration Example Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.AmbientTestMethodResolver.html Example showing how to register and set the ambient test method within MSTest setup and cleanup hooks. ```csharp // MSTest example [TestInitialize] public void Init() { Bdd.Register(AmbientTestMethodResolver.Instance); var mi = typeof(MyTests).GetMethod(TestContext.TestName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); AmbientTestMethodResolver.Set(mi); Ambient.Current.Value = Bdd.CreateContext(this, traits: new MsTestTraitBridge(TestContext)); } [TestCleanup] public void Cleanup() { Ambient.Current.Value = null; AmbientTestMethodResolver.Set(null); }__ ``` -------------------------------- ### Given Method (Action, T) Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Bdd.html Starts a `Given` step with an auto-generated title using a synchronous setup action plus a seed value. ```APIDOC ## Given(ScenarioContext, Action, T) Starts a `Given` step with an auto-generated title using a synchronous setup action plus a seed value. ### Method ```csharp public static ScenarioChain Given(ScenarioContext ctx, Action setup, T seed) ``` #### Parameters `ctx` ScenarioContext Scenario context created by CreateContext(object, string?, ITraitBridge?, ScenarioOptions?). `setup` Action Synchronous action that performs setup side-effects. `seed` T Value seeded into the chain after performing `setup`. #### Returns ScenarioChain A ScenarioChain for further chaining. #### Type Parameters `T` The type produced by the seed value. ``` -------------------------------- ### Hello World Example with xUnit v3 Source: https://jerrettdavis.github.io/TinyBDD/user-guide/samples-index.html A 'Hello World' example using TinyBDD with xUnit v3. Requires TinyBDD.Xunit.v3. ```csharp using TinyBDD.Xunit.v3; using Xunit; [Feature("Hello World")] public class HelloWorldTests : TinyBddXunitBase { [Scenario("Greeting message"), Fact] public async Task GreetingMessage() { await Given("name", () => "World") .When("creating greeting", name => $"Hello, {name}!") .Then("greeting is correct", greeting => greeting == "Hello, World!") .AssertPassed(); } } ``` -------------------------------- ### Given with Async ValueTask Setup and State Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Starts a Given step with explicit state, using an asynchronous ValueTask setup function to avoid closure allocation. ```csharp public static ScenarioChain Given(string title, TState state, Func> setup)__ ``` -------------------------------- ### Hello World Example with xUnit v2 Source: https://jerrettdavis.github.io/TinyBDD/user-guide/samples-index.html A 'Hello World' example using TinyBDD with xUnit v2. Ensure TinyBDD.Xunit and Xunit.Abstractions are included. ```csharp using TinyBDD.Xunit; using Xunit; using Xunit.Abstractions; [Feature("Hello World")] public class HelloWorldTests : TinyBddXunitBase { public HelloWorldTests(ITestOutputHelper output) : base(output) { } [Scenario("Greeting message"), Fact] public async Task GreetingMessage() { await Given("name", () => "World") .When("creating greeting", name => $"Hello, {name}!") .Then("greeting is correct", greeting => greeting == "Hello, World!") .AssertPassed(); } } ``` -------------------------------- ### Given with Token-Aware Async ValueTask Setup and State Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Starts a token-aware Given step with explicit state, using an asynchronous ValueTask setup function to avoid closure allocation. ```csharp public static ScenarioChain Given(string title, TState state, Func> setup)__ ``` -------------------------------- ### Hello World Example with MSTest Source: https://jerrettdavis.github.io/TinyBDD/user-guide/samples-index.html Shows a 'Hello World' example with TinyBDD and MSTest. Requires TinyBDD.MSTest. ```csharp using Microsoft.VisualStudio.TestTools.UnitTesting; using TinyBDD.MSTest; [TestClass] [Feature("Hello World")] public class HelloWorldTests : TinyBddMsTestBase { [Scenario("Greeting message"), TestMethod] public async Task GreetingMessage() { await Given("name", () => "World") .When("creating greeting", name => $"Hello, {name}!") .Then("greeting is correct", greeting => greeting == "Hello, World!") .AssertPassed(); } } ``` -------------------------------- ### Given(string, Func) Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Starts a `Given` step with an explicit title and synchronous setup. ```APIDOC ## Given(string, Func) ### Description Starts a `Given` step with an explicit title and synchronous setup. ### Method protected ### Endpoint N/A (Method Signature) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example N/A ### Response #### Success Response (200) N/A #### Response Example N/A ### Remarks Returns a `ScenarioChain` for chaining `When`/`Then`. ``` -------------------------------- ### Example Implementation Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Extensions.FileBased.Core.IApplicationDriver.html An example of how to implement the IApplicationDriver interface. ```APIDOC ## Example Implementation ### Description An example of how to implement the IApplicationDriver interface. ### Code ```csharp public partial class MyApplicationDriver : IApplicationDriver { [DriverMethod("register user")] public async Task RegisterUser(string email) { // Implementation } } ``` ``` -------------------------------- ### GivenBackground Usage Example Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Demonstrates using GivenBackground to chain steps starting from a database connection state. ```csharp [Test] public async Task TestWithBackground() { await GivenBackground() .When("querying users", conn => conn.Query("SELECT * FROM Users")) .Then("users exist", users => users.Any()) .AssertPassed(); } ``` -------------------------------- ### Implement xUnit Lifecycle Setup and Teardown Source: https://jerrettdavis.github.io/TinyBDD/user-guide/hooks-and-lifecycle.html Uses the class constructor for setup and IDisposable for cleanup, ensuring resources are managed per test method. ```csharp [Feature("Resource Management")] public class ResourceTests : TinyBddXunitBase, IDisposable { private readonly TestDatabase _db; private readonly ILogger _logger; // Setup: Runs before each test method public ResourceTests(ITestOutputHelper output) : base(output) { _logger = CreateLogger(); _logger.LogInformation("Test starting"); _db = new TestDatabase(); _db.Initialize(); } [Scenario("Database operations"), Fact] public async Task DatabaseOperations() { await Given("database connection", () => _db) .When("executing query", db => db.Query("SELECT * FROM Users")) .Then("query succeeds", users => users != null) .AssertPassed(); } // Cleanup: Runs after each test method public void Dispose() { _logger?.LogInformation("Test completed"); _db?.Dispose(); } } ``` -------------------------------- ### Given Step Overloads Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Various overloads for starting a Given step with different setup types and optional titles. ```csharp public static ScenarioChain Given(Func> setup) ``` ```csharp public static ScenarioChain Given(Func> setup) ``` ```csharp public static ScenarioChain Given(Func> setup) ``` ```csharp public static ScenarioChain Given(Func> setup) ``` ```csharp public static ScenarioChain Given(Func setup) ``` ```csharp public static ScenarioChain Given(string title, Func> setup) ``` ```csharp public static ScenarioChain Given(string title, Func> setup) ``` -------------------------------- ### Given(string, Func) Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ScenarioOutlineBuilder-1.html Starts a scenario outline with a synchronous Given step that utilizes example data. ```APIDOC ## Given(string, Func) ### Description Starts the scenario outline with a Given step that uses example data. ### Parameters - **title** (string) - Required - The step title. - **setup** (Func) - Required - A function that receives the example and returns the initial value. ### Returns - **ScenarioOutlineChain** - A chain builder for continuing the scenario outline. ``` -------------------------------- ### TinyBdd_SetUp Method Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.NUnit.TinyBddNUnitBase.html Initializes the TinyBDD ambient context and trait bridge. If ConfigureBackground() is overridden, call ExecuteBackgroundAsync(CancellationToken) at the start of your test or in a derived [SetUp] method. ```APIDOC #### TinyBdd_SetUp() Initializes the TinyBDD ambient context and trait bridge. ```csharp [SetUp] public void TinyBdd_SetUp() ``` #### Remarks If you override ConfigureBackground(), call ExecuteBackgroundAsync(CancellationToken) at the start of your test or in a derived `[SetUp]` method. ``` -------------------------------- ### Given Methods Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.FromContext.html Methods for starting Given steps within a scenario chain, with options for asynchronous or synchronous setup and explicit or default titles. ```APIDOC ## Given(Func>) ### Description Starts a token-aware `Given` step with a default title and asynchronous setup. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **setup** (Func>) - Required - Asynchronous factory that observes a CancellationToken. ### Request Example N/A ### Response #### Success Response (200) - **ScenarioChain** (ScenarioChain) - A ScenarioChain that can be continued with `When`/`Then`. #### Response Example N/A ``` ```APIDOC ## Given(Func) ### Description Starts a `Given` step with a default title and synchronous setup. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **setup** (Func) - Required - Synchronous factory for the initial value. ### Request Example N/A ### Response #### Success Response (200) - **ScenarioChain** (ScenarioChain) - A ScenarioChain that can be continued with `When`/`Then`. #### Response Example N/A ``` ```APIDOC ## Given(string, Func>) ### Description Starts a token-aware `Given` step with an explicit title and asynchronous setup. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **title** (string) - Required - Human-friendly step title. - **setup** (Func>) - Required - Asynchronous factory that observes a CancellationToken. ### Request Example N/A ### Response #### Success Response (200) - **ScenarioChain** (ScenarioChain) - A ScenarioChain that can be continued with `When`/`Then`. #### Response Example N/A ``` ```APIDOC ## Given(string, Func) ### Description Starts a `Given` step with an explicit title and synchronous setup. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **title** (string) - Required - Human-friendly step title. - **setup** (Func) - Required - Synchronous factory for the initial value. ### Request Example N/A ### Response #### Success Response (200) - **ScenarioChain** (ScenarioChain) - A ScenarioChain that can be continued with `When`/`Then`. #### Response Example N/A ``` -------------------------------- ### Installation Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/hosting.html Add the TinyBDD.Extensions.Hosting package to your project. ```APIDOC ## Installation ``` dotnet add package TinyBDD.Extensions.Hosting ``` This package includes `TinyBDD.Extensions.DependencyInjection` as a dependency. ``` -------------------------------- ### Execute Scenario Outline with Examples Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ScenarioOutlineBuilder-1.html Demonstrates how to define and execute a scenario outline with multiple example rows using the ScenarioOutlineBuilder. Each example row provides data for the scenario steps. ```csharp await Bdd.ScenarioOutline<(int a, int b, int expected)>(ctx, "Addition") .Given("first number", ex => ex.a) .And("second number", (_, ex) => ex.b) .When("added", (a, b) => a + b) .Then("result matches expected", (sum, ex) => sum == ex.expected) .Examples( (a: 1, b: 2, expected: 3), (a: 5, b: 5, expected: 10)) .AssertAllPassedAsync(); ``` -------------------------------- ### From Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Creates a helper for starting chains. ```APIDOC ## From() ### Description Creates a helper bound to the current ambient Scenario for starting chains without relying on static Flow methods in downstream helpers. ### Returns - **FromContext** - A FromContext tied to Scenario. ## From(ScenarioContext) ### Description Creates a helper for starting chains from an explicit ScenarioContext. ### Parameters - **ctx** (ScenarioContext) - Required - The scenario context. ``` -------------------------------- ### Given Methods Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Methods to initialize a ScenarioChain with various setup configurations. ```APIDOC ## Given(string, Func>) ### Description Starts a Given step with an explicit title and asynchronous Task setup. ### Parameters - **title** (string) - Required - Human-friendly step title. - **setup** (Func>) - Required - Asynchronous factory for the initial value. ### Returns - **ScenarioChain** - A chain that can be continued with When/Then. ## Given(string, Func>) ### Description Starts a Given step with an explicit title and asynchronous ValueTask setup. ### Parameters - **title** (string) - Required - Human-friendly step title. - **setup** (Func>) - Required - ValueTask-producing factory for the initial value. ## Given(string, Func) ### Description Starts a Given step with an explicit title and synchronous setup. ### Parameters - **title** (string) - Required - Human-friendly step title. - **setup** (Func) - Required - Synchronous factory for the initial value. ## Given(string, TState, Func>) ### Description Starts a token-aware Given step with state, avoiding closure allocation using Task. ## Given(string, TState, Func>) ### Description Starts a token-aware Given step with state, avoiding closure allocation using ValueTask. ## Given(string, TState, Func>) ### Description Starts a Given step with state using async Task, avoiding closure allocation. ## Given(string, TState, Func>) ### Description Starts a Given step with state using async ValueTask, avoiding closure allocation. ## Given(string, TState, Func) ### Description Starts a Given step with state, avoiding closure allocation using a synchronous factory. ``` -------------------------------- ### Installation Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/dependency-injection.html Install the TinyBDD.Extensions.DependencyInjection package using the .NET CLI. ```APIDOC ## Installation ```csharp dotnet add package TinyBDD.Extensions.DependencyInjection ``` ``` -------------------------------- ### Given(string, Func>) Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Starts a `Given` step with an explicit title and asynchronous setup using `Task`. ```APIDOC ## Given(string, Func>) ### Description Starts a `Given` step with an explicit title and asynchronous setup. ### Method protected ### Endpoint N/A (Method Signature) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example N/A ### Response #### Success Response (200) N/A #### Response Example N/A ### Remarks Use this overload when the initial value requires async I/O. ``` -------------------------------- ### ScenarioOptions: ShowFeatureSetup Property Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ScenarioOptions.html If true, feature setup steps will be shown in the Gherkin output. Defaults to false (feature setup is typically internal and not shown). ```csharp public bool ShowFeatureSetup { get; init; } ``` -------------------------------- ### Given(string, Func>) Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ScenarioOutlineBuilder-1.html Starts a scenario outline with an asynchronous Given step that utilizes example data. ```APIDOC ## Given(string, Func>) ### Description Starts the scenario outline with a Given step that uses example data asynchronously. ### Parameters - **title** (string) - Required - The step title. - **setup** (Func>) - Required - An async function that receives the example and returns the initial value. ### Returns - **ScenarioOutlineChain** - A chain builder for continuing the scenario outline. ``` -------------------------------- ### Given with Async ValueTask Setup Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Flow.html Use this overload for a Given step with an explicit title and an asynchronous setup function returning a ValueTask. ```csharp public static ScenarioChain Given(string title, Func> setup)__ ``` -------------------------------- ### TinyBdd_OneTimeSetUp Method Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.NUnit.TinyBddNUnitBase.html Executes feature setup once before any tests in the fixture. Override ConfigureFeatureSetup() to define feature-level setup steps. ```APIDOC ### Methods #### TinyBdd_OneTimeSetUp() Executes feature setup once before any tests in the fixture. ```csharp [OneTimeSetUp] public void TinyBdd_OneTimeSetUp() ``` #### Remarks This method is called by NUnit before any test methods run in the fixture. Override ConfigureFeatureSetup() to define feature-level setup steps. ``` -------------------------------- ### Given Step Methods with State Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Bdd.html Methods to start a Given step while passing state to avoid closure allocations. Choose the variant matching your setup function's return type (ValueTask, Task, or synchronous). ```csharp public static ScenarioChain Given(ScenarioContext ctx, string title, TState state, Func> setup)__ ``` ```csharp public static ScenarioChain Given(ScenarioContext ctx, string title, TState state, Func> setup)__ ``` ```csharp public static ScenarioChain Given(ScenarioContext ctx, string title, TState state, Func> setup)__ ``` ```csharp public static ScenarioChain Given(ScenarioContext ctx, string title, TState state, Func setup)__ ``` -------------------------------- ### ExamplesResult Results Property Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ExamplesResult.html Gets the list of individual example results. Allows detailed inspection of each scenario's outcome. ```csharp public IReadOnlyList Results { get; } ``` -------------------------------- ### Database Fixture Example Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.AssemblyFixture.html An example demonstrating how to use AssemblyFixture to set up and tear down a database for an entire test assembly. ```APIDOC ## Example: Database fixture for an assembly ```csharp using TinyBDD; [assembly: AssemblySetup(typeof(DatabaseFixture))] public class DatabaseFixture : AssemblyFixture { private TestDatabase? _db; public TestDatabase Database => _db ?? throw new InvalidOperationException("Database not initialized"); protected override async Task SetupAsync(CancellationToken ct) { _db = new TestDatabase(); await _db.StartAsync(ct); await _db.SeedTestDataAsync(ct); } protected override async Task TeardownAsync(CancellationToken ct) { if (_db is not null) await _db.DisposeAsync(); } } // In your tests: public class MyTests : TinyBddXunitBase { [Fact] public async Task CanQueryDatabase() { var db = AssemblyFixture.Get().Database; // Use the database... } } ``` ``` -------------------------------- ### Optimize Expensive Operations in Setup Source: https://jerrettdavis.github.io/TinyBDD/user-guide/troubleshooting-faq.html Optimize test setup by avoiding expensive operations in every test. Use `OneTimeSetUp` for shared, less frequent setup and `SetUp` for per-test setup with minimal data. ```csharp // Bad: Expensive operation in every test [SetUp] public void Setup() { _db = new TestDatabase(); _db.SeedWithMillionsOfRecords(); // Very slow } // Good: Use cached or minimal data private static TestDatabase _sharedDb; [OneTimeSetUp] public void OneTimeSetup() { _sharedDb = new TestDatabase(); _sharedDb.SeedWithMinimalData(); } ``` -------------------------------- ### Execute Scenario Outline Examples with AssertAllPassedAsync Source: https://jerrettdavis.github.io/TinyBDD/user-guide/troubleshooting-faq.html Scenario outlines require `AssertAllPassedAsync()` to be called to execute all provided examples. Forgetting this will prevent examples from running. ```csharp // Bad: Examples won't run var outline = await Bdd.ScenarioOutline(ctx, "Test") .Given("number", ex => ex) .Then("positive", n => n > 0) .Examples(1, 2, 3); // Missing AssertAllPassedAsync() or RunAsync() // Good: Examples execute await Bdd.ScenarioOutline(ctx, "Test") .Given("number", ex => ex) .Then("positive", n => n > 0) .Examples(1, 2, 3) .AssertAllPassedAsync(); // Executes all examples ``` -------------------------------- ### Scenario Builder with Examples Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Bdd.html Creates a data-driven scenario builder with the specified examples. ```APIDOC ## Scenario(ScenarioContext, string, params TExample[]) __ ### Description Creates a data-driven scenario builder with the specified examples. ### Method `static ExamplesBuilder Scenario(ScenarioContext ctx, string title, params TExample[] examples)` ### Parameters - **ctx** (ScenarioContext) - The scenario context. - **title** (string) - The scenario title. - **examples** (TExample[]) - The example data values. ### Returns ExamplesBuilder - An ExamplesBuilder for defining the scenario. ### Type Parameters - **TExample** - The type of example data. ``` -------------------------------- ### Configure Feature Setup Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Override to define expensive setup operations that run once before any scenarios in the test class. ```csharp protected virtual ScenarioChain? ConfigureFeatureSetup()__ ``` ```csharp protected override ScenarioChain? ConfigureFeatureSetup() { return Given("test server started", () => new TestServer()) .And("database seeded", server => { server.SeedData(); return server; }); }__ ``` -------------------------------- ### ConfigureFeatureSetup Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Configures feature-level setup steps that run once before any scenarios. ```APIDOC ## ConfigureFeatureSetup() ### Description Override to configure feature-level setup steps that run once before any scenarios. ### Returns - **ScenarioChain** - A ScenarioChain representing the feature setup steps, or null if no feature setup is needed. ``` -------------------------------- ### Provide Examples for Scenario Outlines Source: https://jerrettdavis.github.io/TinyBDD/user-guide/troubleshooting-faq.html A `ScenarioOutline` will throw an `InvalidOperationException` if no examples are provided. Ensure you call `.Examples()` with at least one value. ```csharp // Error: InvalidOperationException await Bdd.ScenarioOutline(ctx, "Test") .Given("number", ex => ex) .Then("positive", n => n > 0) .AssertAllPassedAsync(); // Throws: No examples provided ``` -------------------------------- ### Implement Background Steps with Test Frameworks Source: https://jerrettdavis.github.io/TinyBDD/user-guide/writing-scenarios.html Demonstrates how to handle shared setup and teardown logic across multiple scenarios using native test framework features. ```csharp [Feature("User Authentication")] public class AuthenticationTests : TinyBddXunitBase, IDisposable { private readonly TestDatabase _db; private readonly AuthService _authService; public AuthenticationTests(ITestOutputHelper output) : base(output) { // Background: Initialize test database and services _db = new TestDatabase(); _db.Seed(); _authService = new AuthService(_db); } [Scenario("Valid credentials allow login"), Fact] public async Task ValidCredentialsAllowLogin() { await Given("valid credentials", () => new Credentials("user@example.com", "correct")) .When("attempting login", creds => _authService.LoginAsync(creds)) .Then("login succeeds", result => result.IsSuccess) .AssertPassed(); } [Scenario("Invalid credentials deny login"), Fact] public async Task InvalidCredentialsDenyLogin() { await Given("invalid credentials", () => new Credentials("user@example.com", "wrong")) .When("attempting login", creds => _authService.LoginAsync(creds)) .Then("login fails", result => !result.IsSuccess) .AssertPassed(); } public void Dispose() { // Cleanup after each scenario _db?.Dispose(); } } ``` ```csharp [Feature("User Authentication")] public class AuthenticationTests : TinyBddNUnitBase { private TestDatabase _db; private AuthService _authService; [SetUp] public void BackgroundSetup() { // Background: Initialize test database and services _db = new TestDatabase(); _db.Seed(); _authService = new AuthService(_db); } [Scenario("Valid credentials allow login"), Test] public async Task ValidCredentialsAllowLogin() { await Given("valid credentials", () => new Credentials("user@example.com", "correct")) .When("attempting login", creds => _authService.LoginAsync(creds)) .Then("login succeeds", result => result.IsSuccess) .AssertPassed(); } [TearDown] public void BackgroundCleanup() { _db?.Dispose(); } } ``` ```csharp [TestClass] [Feature("User Authentication")] public class AuthenticationTests : TinyBddMsTestBase { private TestDatabase _db; private AuthService _authService; [TestInitialize] public void BackgroundSetup() { // Background: Initialize test database and services _db = new TestDatabase(); _db.Seed(); _authService = new AuthService(_db); } [Scenario("Valid credentials allow login"), TestMethod] public async Task ValidCredentialsAllowLogin() { await Given("valid credentials", () => new Credentials("user@example.com", "correct")) .When("attempting login", creds => _authService.LoginAsync(creds)) .Then("login succeeds", result => result.IsSuccess) .AssertPassed(); } [TestCleanup] public void BackgroundCleanup() { _db?.Dispose(); } } ``` -------------------------------- ### Hello World Example with NUnit Source: https://jerrettdavis.github.io/TinyBDD/user-guide/samples-index.html Demonstrates a 'Hello World' scenario using TinyBDD with NUnit. Ensure TinyBDD.NUnit is referenced. ```csharp using NUnit.Framework; using TinyBDD.NUnit; [Feature("Hello World")] public class HelloWorldTests : TinyBddNUnitBase { [Scenario("Greeting message"), Test] public async Task GreetingMessage() { await Given("name", () => "World") .When("creating greeting", name => $"Hello, {name}!") .Then("greeting is correct", greeting => greeting == "Hello, World!") .AssertPassed(); } } ``` -------------------------------- ### One-Shot Startup Workflow Example Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/hosting.html Configure TinyBDD to stop the host upon successful workflow completion and register a workflow for database migration. This is useful for one-time startup tasks. ```csharp builder.Services.AddTinyBddHosting(options => { options.StopHostOnCompletion = true; }); builder.Services.AddWorkflowHostedService(); public class DatabaseMigrationWorkflow : IWorkflowDefinition { private readonly IDbContext _db; public DatabaseMigrationWorkflow(IDbContext db) => _db = db; public string FeatureName => "Database Migration"; public string ScenarioName => "Apply pending migrations"; public string? FeatureDescription => null; public async ValueTask ExecuteAsync(ScenarioContext context, CancellationToken ct) { await Bdd.Given(context, "pending migrations", () => _db.GetPendingMigrations()) .When("applied", migrations => ApplyMigrations(migrations, ct)) .Then("database up to date", result => result.Applied == result.Total); } } ``` -------------------------------- ### Implement LoggingObserver Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.IScenarioObserver.html An example implementation of IScenarioObserver that logs scenario start and finish events to the console. ```csharp public class LoggingObserver : IScenarioObserver { public ValueTask OnScenarioStarting(ScenarioContext context) { Console.WriteLine($"Starting: {context.ScenarioName}"); return default; } public ValueTask OnScenarioFinished(ScenarioContext context) { Console.WriteLine($"Finished: {context.ScenarioName}"); return default; } }__ ``` -------------------------------- ### Implement IStepObserver for Step Timing Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.IStepObserver.html An example implementation of IStepObserver that logs the start and finish times of each step. It logs the step kind and title when starting, and includes the elapsed time in milliseconds when finishing. ```csharp public class StepTimingObserver : IStepObserver { public ValueTask OnStepStarting(ScenarioContext context, StepInfo step) { Console.WriteLine($"Starting: {step.Kind} {step.Title}"); return default; } public ValueTask OnStepFinished(ScenarioContext context, StepInfo step, StepResult result, StepIO io) { Console.WriteLine($"Finished: {step.Kind} {step.Title} in {result.Elapsed.TotalMilliseconds}ms"); return default; } } ``` -------------------------------- ### Initialize TinyBDD Context with NUnit SetUp Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.NUnit.TinyBddNUnitBase.html Initializes the TinyBDD ambient context and trait bridge before each test. If overriding ConfigureBackground(), call ExecuteBackgroundAsync(CancellationToken) at the start of your test or in a derived [SetUp] method. ```csharp [SetUp] public void TinyBdd_SetUp() ``` -------------------------------- ### Create Test Project and Add TinyBDD (v3) Source: https://jerrettdavis.github.io/TinyBDD/user-guide/running-with-test-frameworks.html Sets up a new class library project and adds the necessary TinyBDD and xUnit v3 packages. ```bash # Create a new test project dotnet new classlib -n MyApp.Tests # Navigate to the project cd MyApp.Tests # Add required packages dotnet add package TinyBDD dotnet add package TinyBDD.Xunit.v3 dotnet add package xunit.v3 ``` -------------------------------- ### GivenFeature Usage Example Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Demonstrates using GivenFeature to chain steps starting from a test server state. ```csharp [Test] public async Task TestWithFeature() { await GivenFeature() .When("sending request", server => server.Get("/api/users")) .Then("response is ok", response => response.StatusCode == 200) .AssertPassed(); } ``` -------------------------------- ### xUnit Example with TinyBDD Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/reporting.html Demonstrates setting up TinyBDD with xUnit for BDD-style tests, including JSON reporting configuration. ```csharp using TinyBDD.Xunit; using TinyBDD.Extensions.Reporting; using Xunit; [Feature("Calculator")] public class CalculatorTests : TinyBddXunitBase { private static readonly TinyBddExtensibilityOptions Options = TinyBdd.Configure( builder => builder.AddJsonReport("artifacts/calculator-tests.json")); public CalculatorTests(ITestOutputHelper output) : base(output) { // Override ambient context with reporting-enabled options Ambient.Current.Value = Bdd.CreateContext(this, options: Options); } [Scenario("Addition"), Fact] public async Task Addition() { await Given("numbers", () => (2, 3)) .When("added", nums => nums.Item1 + nums.Item2) .Then("equals 5", sum => sum == 5) .AssertPassed(); } } ``` -------------------------------- ### ExamplesResult TotalCount Property Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ExamplesResult.html Gets the total number of examples executed. Provides a count of all scenarios run. ```csharp public int TotalCount { get; } ``` -------------------------------- ### Use Given step keyword Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/file-based-gherkin.html Establishes preconditions and initial state. ```gherkin Given a calculator Given the user is logged in Given the database contains test data ``` -------------------------------- ### ExamplesResult PassedCount Property Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ExamplesResult.html Gets the number of examples that passed. Useful for tracking successful test cases. ```csharp public int PassedCount { get; } ``` -------------------------------- ### ExamplesResult FailedCount Property Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.ExamplesResult.html Gets the number of examples that failed. Useful for reporting or debugging specific failures. ```csharp public int FailedCount { get; } ``` -------------------------------- ### Given(string, Func>) Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Starts a `Given` step with an explicit title and asynchronous setup using `ValueTask`. ```APIDOC ## Given(string, Func>) ### Description Starts a `Given` step with an explicit title and `ValueTask` setup. ### Method protected ### Endpoint N/A (Method Signature) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example N/A ### Response #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Quick Start with TinyBDD DI Source: https://jerrettdavis.github.io/TinyBDD/user-guide/extensions/dependency-injection.html Register services in your startup configuration and inject IScenarioContextFactory into your services to execute BDD scenarios. ```csharp // In Startup.cs or Program.cs services.AddTinyBdd(); // In your service or controller public class OrderService { private readonly IScenarioContextFactory _contextFactory; public OrderService(IScenarioContextFactory contextFactory) { _contextFactory = contextFactory; } public async Task ProcessOrder(Order order) { var context = _contextFactory.Create("Order Processing", "Process single order"); await Bdd.Given(context, "order received", () => order) .When("validated", o => ValidateOrder(o)) .When("saved to database", o => SaveOrder(o)) .Then("confirmation sent", o => SendConfirmation(o)); return new OrderResult { Success = context.Steps.All(s => s.Error == null) }; } } ``` -------------------------------- ### Configure TinyBDD with observers and scenarios Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TinyBddOptionsBuilder.html Example showing how to configure observers and execute a scenario using the fluent API. ```csharp var options = TinyBdd.Configure(builder => builder .AddObserver(new LoggingObserver()) .AddObserver(new TelemetryObserver())); await TinyBddScenario.With(options) .Given("start", () => 1) .When("add", x => x + 1) .Then("is 2", x => x == 2) .AssertPassed();__ ``` -------------------------------- ### Initialize New TinyBDD Project Source: https://jerrettdavis.github.io/TinyBDD/user-guide/samples-index.html CLI commands to create a new xUnit project, install TinyBDD packages, and generate a sample test file. ```bash # Create new xUnit project dotnet new xunit -n MyApp.Tests cd MyApp.Tests # Add TinyBDD dotnet add package TinyBDD dotnet add package TinyBDD.Xunit # Create first test cat > CalculatorTests.cs << 'EOF' using TinyBDD.Xunit; using Xunit; using Xunit.Abstractions; [Feature("Calculator")] public class CalculatorTests : TinyBddXunitBase { public CalculatorTests(ITestOutputHelper output) : base(output) { } [Scenario("Addition"), Fact] public async Task Addition() { await Given("numbers", () => (2, 3)) .When("added", nums => nums.Item1 + nums.Item2) .Then("equals 5", sum => sum == 5) .AssertPassed(); } } EOF # Run tests dotnet test ``` -------------------------------- ### Register a Database Fixture with AssemblySetupAttribute Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.AssemblySetupAttribute.html Example of registering a database fixture that derives from AssemblyFixture. Setup and teardown logic is defined within the fixture. ```csharp using TinyBDD; [assembly: AssemblySetup(typeof(DatabaseFixture))] public class DatabaseFixture : AssemblyFixture { private TestDatabase? _db; public TestDatabase Database => _db!; protected override async Task SetupAsync(CancellationToken ct) { _db = new TestDatabase(); await _db.StartAsync(ct); } protected override async Task TeardownAsync(CancellationToken ct) { if (_db is not null) await _db.DisposeAsync(); } } ``` -------------------------------- ### Implement InitializeAsync Method Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.Extensions.FileBased.Core.IApplicationDriver.html Implement this method to define setup actions that should occur before scenario execution begins. It receives a CancellationToken for managing asynchronous operations. ```csharp Task InitializeAsync(CancellationToken cancellationToken = default) ``` -------------------------------- ### Configure Background Steps Source: https://jerrettdavis.github.io/TinyBDD/api/TinyBDD.TestBase.html Override this method to define shared setup steps that run before each scenario. ```csharp protected virtual ScenarioChain? ConfigureBackground()__ ``` ```csharp protected override ScenarioChain? ConfigureBackground() { return Given("a database connection", () => new DbConnection()) .And("test data seeded", conn => { SeedData(conn); return conn; }); }__ ```