Troubleshooting
Docs for xUnit SDK v0.4.0
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("...", () => { });
}
| Pattern | Single test attribute | Data-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:
| Pattern | Correct Base Class | Attributes |
|---|---|---|
| BDD | FeatureTest | [Feature], [Scenario], [ScenarioOutline] |
| Specification | SpecificationTest | [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;
});
}
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:
- Attribute present? —
[Scenario],[Rule], etc. - Base class correct? —
FeatureTestorSpecificationTest - Constructor correct? — Accepts
ITestOutputHelper, passes tobase(output) - Example counts match? — Same number of
[Example]values as method parameters - Placeholders match? —
<name>in step titles matches parameter names - Value quotes correct? — Single quotes around values:
'100', not"100" - Index in range? —
Values[N]doesn't exceed the number of quoted values
Related
- Attributes — full attribute reference
- Value Extraction API —
Values,Params, and type conversion - Debugging — step-by-step debugging techniques
- Best Practices — patterns that prevent common issues