Skip to main content

Troubleshooting

This page covers the most common issues you'll encounter when working with LiveDoc xUnit tests, along with their causes and fixes.


Test Not Discovered

Symptom: Your test method doesn't appear in Test Explorer or isn't run by dotnet test.

Cause: The method is missing a LiveDoc test attribute. LiveDoc attributes ([Scenario], [ScenarioOutline], [Rule], [RuleOutline]) inherit from xUnit's [Fact] and [Theory] — without them, xUnit doesn't know the method is a test.

Fix: Add the appropriate attribute:

// ❌ Missing attribute — xUnit ignores this method
public void Customer_gets_discount()
{
Given("...", () => { });
}

// ✅ Attribute present — xUnit discovers this test
[Scenario]
public void Customer_gets_discount()
{
Given("...", () => { });
}
PatternSingle test attributeData-driven attribute
BDD[Scenario][ScenarioOutline]
Specification[Rule][RuleOutline]

Output Not Formatted

Symptom: Tests run and pass, but the output in Test Explorer shows plain text instead of Gherkin-formatted results (no indented Given/When/Then steps).

Cause: The test class doesn't inherit from the correct LiveDoc base class. The base class wires up the ITestOutputHelper to produce formatted output.

Fix: Inherit from FeatureTest (for BDD) or SpecificationTest (for MSpec), and pass ITestOutputHelper to the base constructor:

// ❌ No base class — steps execute but output is unformatted
[Feature("Shopping Cart")]
public class CartTests
{
public CartTests(ITestOutputHelper output) { }
}

// ✅ Correct base class — output is Gherkin-formatted
[Feature("Shopping Cart")]
public class CartTests : FeatureTest
{
public CartTests(ITestOutputHelper output) : base(output) { }
}

Wrong Base Class

Symptom: Compilation errors, missing step methods, or incorrect formatted output structure.

Cause: Using FeatureTest with [Specification]/[Rule] attributes, or SpecificationTest with [Feature]/[Scenario] attributes.

Fix: Match the base class to the pattern:

PatternCorrect Base ClassAttributes
BDDFeatureTest[Feature], [Scenario], [ScenarioOutline]
SpecificationSpecificationTest[Specification], [Rule], [RuleOutline]
// ❌ Mismatch: BDD attributes with Specification base class
[Feature("Cart")]
public class CartTests : SpecificationTest { ... } // Wrong!

// ✅ Correct: BDD attributes with FeatureTest
[Feature("Cart")]
public class CartTests : FeatureTest { ... }

// ✅ Correct: Specification attributes with SpecificationTest
[Specification("Calculator")]
public class CalcSpec : SpecificationTest { ... }

ScenarioOutline Parameter Mismatch

Symptom: System.InvalidOperationException or unexpected placeholder text in output (e.g., <country> appears literally instead of being replaced).

Cause: The <placeholder> names in step titles don't match the method parameter names.

Fix: Ensure placeholders match parameter names exactly (case-insensitive):

// ❌ Mismatch: placeholder says "customerCountry", parameter says "country"
[ScenarioOutline]
[Example("Australia", 100.00)]
public void Shipping(string country, decimal total)
{
Given("the customer is from <customerCountry>", () => // Won't be replaced!
{
_cart.Country = country;
});
}

// ✅ Match: placeholder matches parameter name
[ScenarioOutline]
[Example("Australia", 100.00)]
public void Shipping(string country, decimal total)
{
Given("the customer is from <country>", () =>
{
_cart.Country = country;
});
}
tip

Placeholder matching is case-insensitive — <Country> matches a parameter named country.


Example Count Mismatch

Symptom: System.ArgumentException at test discovery, or fewer examples appear in Test Explorer than expected.

Cause: The number of values in an [Example] attribute doesn't match the number of method parameters.

Fix: Ensure every [Example] has exactly the same number of values as the method has parameters:

// ❌ 3 parameters but Example has only 2 values
[ScenarioOutline]
[Example("Australia", 100.00)] // Missing third value!
public void Shipping(string country, decimal total, string expected)
{ ... }

// ✅ 3 parameters, 3 values per Example
[ScenarioOutline]
[Example("Australia", 100.00, "Free")]
[Example("New Zealand", 50.00, "International")]
public void Shipping(string country, decimal total, string expected)
{ ... }

Also verify that the types are compatible — a string parameter won't accept an int value without implicit conversion.


Value Extraction Errors

LiveDocValueIndexException

Symptom: LiveDocValueIndexException: Index N is out of range

Cause: Accessing ctx.Step.Values[N] where there aren't enough quoted values in the step title.

Fix: Count the single-quoted values in your step title and ensure the index is valid:

// ❌ Title has 1 quoted value but code accesses index 1 (second value)
Given("the price is '100'", ctx =>
{
var price = ctx.Step!.Values[0].AsDecimal(); // OK: index 0
var tax = ctx.Step!.Values[1].AsDecimal(); // ERROR: no index 1
});

// ✅ Title has 2 quoted values
Given("the price is '100' with tax '10'", ctx =>
{
var price = ctx.Step!.Values[0].AsDecimal(); // 100
var tax = ctx.Step!.Values[1].AsDecimal(); // 10
});

LiveDocParamNotFoundException

Symptom: LiveDocParamNotFoundException: Parameter 'x' not found

Cause: Accessing ctx.Step.Params["x"] but the step title doesn't contain a <x:value> named parameter.

Fix: Add the named parameter to the step title:

// ❌ No named parameter "tax" in title
Given("the price is <price:100>", ctx =>
{
var tax = ctx.Step!.Params["tax"].AsDecimal(); // ERROR
});

// ✅ Both named parameters present
Given("the price is <price:100> with tax <tax:10>", ctx =>
{
var price = ctx.Step!.Params["price"].AsDecimal();
var tax = ctx.Step!.Params["tax"].AsDecimal();
});

LiveDocConversionException

Symptom: LiveDocConversionException: Cannot convert 'abc' to Int32

Cause: The quoted value in the step title can't be parsed to the requested type.

Fix: Ensure the value in the title matches the expected type:

// ❌ "abc" can't be parsed as int
Given("the quantity is 'abc'", ctx =>
{
var qty = ctx.Step!.Values[0].AsInt(); // ERROR
});

// ✅ "5" can be parsed as int
Given("the quantity is '5'", ctx =>
{
var qty = ctx.Step!.Values[0].AsInt(); // OK: 5
});

xUnit Analyzer Warnings

xUnit1004: Test methods should not be skipped

This warning fires on [Fact(Skip = "...")]. It doesn't apply to LiveDoc attributes, but if you see it on a [Scenario] or [Rule] test, it's likely an xUnit analyzer false positive.

Fix: Suppress the warning for LiveDoc test files if it's noisy:

#pragma warning disable xUnit1004
[Scenario(Skip = "Pending implementation")]
public void Future_feature() { }
#pragma warning restore xUnit1004

xUnit1013: Public method should be marked as test

Symptom: Warning on public helper methods in test classes.

Fix: Make helper methods private or protected, or suppress the warning:

// ✅ Make helpers private
private void SetupCart(string country, decimal total)
{
_cart = new Cart { Country = country, Total = total };
}

xUnit1031: Do not use Assert.Same on value types

This is a standard xUnit warning unrelated to LiveDoc. Follow the xUnit analyzer's guidance — use Assert.Equal for value type comparisons.


Quick Diagnostic Checklist

When a test isn't working as expected, check these in order:

  1. Attribute present?[Scenario], [Rule], etc.
  2. Base class correct?FeatureTest or SpecificationTest
  3. Constructor correct? — Accepts ITestOutputHelper, passes to base(output)
  4. Example counts match? — Same number of [Example] values as method parameters
  5. Placeholders match?<name> in step titles matches parameter names
  6. Value quotes correct? — Single quotes around values: '100', not "100"
  7. Index in range?Values[N] doesn't exceed the number of quoted values