Skip to main content

Context

Context objects carry metadata and extracted values through test execution. LiveDocContext is passed to step lambdas. FeatureContext, ScenarioContext, StepContext, SpecificationContext, and RuleContext provide typed access to the current test's title, description, tags, and values.

Given("a user with '100' credits", ctx =>
{
// Step-level context
var credits = ctx.Step!.Values[0].AsInt();
var stepTitle = ctx.Step!.Title;

// Feature-level context
var featureTitle = ctx.Feature?.Title;
var featureDesc = ctx.Feature?.Description;

// Scenario-level context
var scenarioName = ctx.Scenario?.Name;
});

Reference

LiveDocContext

The primary context object passed to step lambdas via the Action<LiveDocContext> and Func<LiveDocContext, Task> overloads.

public class LiveDocContext

Properties

PropertyTypeDescription
FeatureFeatureContext?Feature metadata (BDD tests only).
SpecificationSpecificationContext?Specification metadata (MSpec tests only).
ScenarioScenarioContext?Current scenario metadata (BDD tests only).
RuleRuleContext?Current rule metadata (MSpec tests only).
StepStepContext?Current step metadata with extracted values.
Exampledynamic?Current example row data (outlines only).
TestCaseobject?Base test case context.
Null safety

Properties are nullable. In a [Scenario] method, Feature and Scenario are populated but Specification and Rule are null. In a [Rule] method, the reverse is true. Step is populated inside step lambdas.

StepContext

Contains metadata about the currently executing step, including extracted values and parameters.

public class StepContext

Properties

PropertyTypeDescription
TitlestringThe original step title as written in code.
DisplayTitlestringThe rendered title with placeholders replaced and quotes removed.
TypestringThe step keyword: "Given", "When", "Then", "And", or "But".
ValuesLiveDocValueArrayOrdered array of quoted values ('value').
ValuesRawstring[]Quoted values as raw strings.
ParamsLiveDocValueDictionaryNamed parameters (<name:value>).
ParamsRawIReadOnlyDictionary<string, string>Named parameters as raw strings.
Given("transferring '250.00' from <account:checking>", ctx =>
{
// Values: ordered quoted values
var amount = ctx.Step!.Values[0].AsDecimal(); // 250.00m

// Params: named parameters
var account = ctx.Step!.Params["account"].AsString(); // "checking"

// Metadata
var title = ctx.Step!.Title; // "transferring '250.00' from <account:checking>"
var display = ctx.Step!.DisplayTitle; // "transferring 250.00 from checking"
var type = ctx.Step!.Type; // "Given"
});

FeatureContext

Metadata about the current BDD feature, populated from the [Feature] attribute.

public class FeatureContext

Properties

PropertyTypeDescription
TitlestringThe feature title from [Feature("title")].
Descriptionstring?The description from Description = "...".
Tagsstring[]Tags associated with the feature.
[Feature("Shopping Cart", Description = "Cart checkout rules")]
public class CartTests : FeatureTest
{
public CartTests(ITestOutputHelper output) : base(output) { }

[Scenario]
public void Access_feature_context()
{
Given("context is available", ctx =>
{
Assert.Equal("Shopping Cart", ctx.Feature!.Title);
Assert.Equal("Cart checkout rules", ctx.Feature!.Description);
});
}
}

ScenarioContext

Metadata about the current BDD scenario, populated from the [Scenario] or [ScenarioOutline] attribute.

public class ScenarioContext

Properties

PropertyTypeDescription
NamestringThe scenario title/display name.
Descriptionstring?The scenario description.
Tagsstring[]Tags associated with the scenario.
StepsList<StepExecution>List of executed steps with results.
[Scenario("Login with valid credentials", Description = "Happy path")]
public void Login()
{
Given("a registered user", ctx =>
{
Assert.Equal("Login with valid credentials", ctx.Scenario!.Name);
Assert.Equal("Happy path", ctx.Scenario!.Description);
});
}

SpecificationContext

Metadata about the current MSpec specification, populated from the [Specification] attribute.

public class SpecificationContext

Properties

PropertyTypeDescription
TitlestringThe specification title.
Descriptionstring?The specification description.
Tagsstring[]Tags associated with the specification.

RuleContext

Metadata and values for the currently executing MSpec rule. This is the primary API for value extraction in SpecificationTest.

public class RuleContext

Properties

PropertyTypeDescription
NamestringThe rule title.
Descriptionstring?The rule description.
Tagsstring[]Tags associated with the rule.
ValuesLiveDocValueArrayOrdered array of quoted values from the rule title.
ValuesRawstring[]Quoted values as raw strings.
ParamsLiveDocValueDictionaryNamed parameters from the rule title.
ParamsRawIReadOnlyDictionary<string, string>Named parameters as raw strings.
[Specification("Calculator")]
public class CalcSpec : SpecificationTest
{
public CalcSpec(ITestOutputHelper output) : base(output) { }

[Rule("Multiplying '6' by '7' returns '42'")]
public void Multiplication()
{
var (a, b, expected) = Rule.Values.As<int, int, int>();
Assert.Equal(expected, a * b);

// Also available:
Assert.Equal("Multiplying '6' by '7' returns '42'", Rule.Name);
}
}

EnsureContext()

// On FeatureTest
protected LiveDocContext EnsureContext()

// On SpecificationTest
protected LiveDocContext EnsureContext()

Returns the current LiveDocContext, initializing it if it hasn't been created yet. Normally the context is created automatically when the first step executes, but EnsureContext() can be called explicitly if you need context before any steps run.

[Scenario]
public void Verify_feature_metadata()
{
var ctx = EnsureContext();
Assert.Equal("Shopping Cart", ctx.Feature?.Title);
}

Context Flow

BDD / FeatureTest

[Feature] attribute
└── FeatureContext (title, description, tags)

[Scenario] / [ScenarioOutline] attribute
└── ScenarioContext (name, description, tags, steps)

Given/When/Then/And/But step method
└── StepContext (title, type, values, params)

LiveDocContext (aggregates all above)
└── Passed to: Action<LiveDocContext> lambda
[Feature("Checkout", Description = "Payment flow")]
public class CheckoutTests : FeatureTest
{
public CheckoutTests(ITestOutputHelper output) : base(output) { }

[Scenario("Process payment")]
public void Process_payment()
{
// ctx has: Feature, Scenario, Step
Given("a valid credit card with number '4111111111111111'", ctx =>
{
Assert.Equal("Checkout", ctx.Feature!.Title);
Assert.Equal("Process payment", ctx.Scenario!.Name);
Assert.Equal("Given", ctx.Step!.Type);
Assert.Equal("4111111111111111", ctx.Step!.Values[0].AsString());
});
}
}

MSpec / SpecificationTest

[Specification] attribute
└── SpecificationContext (title, description, tags)

[Rule] / [RuleOutline] attribute
└── RuleContext (name, description, tags, values, params)

Rule property on SpecificationTest
└── Provides: Values, Params, ValuesRaw, ParamsRaw
[Specification("Math", Description = "Core arithmetic rules")]
public class MathSpec : SpecificationTest
{
public MathSpec(ITestOutputHelper output) : base(output) { }

[Rule("Adding '2' and '3' returns '5'")]
public void Addition()
{
// Specification context
Assert.Equal("Math", Specification.Title);
Assert.Equal("Core arithmetic rules", Specification.Description);

// Rule context with values
Assert.Equal("Adding '2' and '3' returns '5'", Rule.Name);
var (a, b, expected) = Rule.Values.As<int, int, int>();
Assert.Equal(expected, a + b);
}
}

ScenarioOutline / RuleOutline

In outline methods, the Example dynamic property provides access to the current row's data:

[ScenarioOutline]
[Example("Alice", 25)]
public void Test(string name, int age)
{
Given("user <name> aged <age>", ctx =>
{
// Method parameters (typed)
Assert.Equal("Alice", name);
Assert.Equal(25, age);

// Dynamic Example property
Assert.Equal("Alice", (string)ctx.Example!.name);
Assert.Equal(25, (int)ctx.Example!.age);
});
}

Caveats

  • ctx.Step is only populated inside step lambdas that use the Action<LiveDocContext> or Func<LiveDocContext, Task> overload. It is null if you use Action (no context).
  • Feature / Specification are mutually exclusive — one is always null depending on the base class.
  • Scenario / Rule are mutually exclusive — one is always null depending on the test attribute.
  • Example is null unless the test is a [ScenarioOutline] or [RuleOutline].
  • RuleContext on SpecificationTest provides Values and Params directly — you don't need a step lambda to access them.

See Also