Table of Contents

YAML Scenario Format Reference

Complete guide to using YAML format for test scenarios with TinyBDD's File-Based DSL extension.

Overview

YAML provides an alternative to Gherkin for defining test scenarios with structured parameter passing and programmatic generation capabilities.

When to Use YAML

Use YAML when:

  • Scenarios are generated by tools or scripts
  • Complex parameter values need structured representation
  • Tooling integration requires machine-readable format

Use Gherkin when:

  • Scenarios are written by humans
  • Business readability is priority
  • Leveraging existing Gherkin knowledge

Basic Structure

feature: Feature Name
description: Optional feature description
scenarios:
  - name: Scenario Name
    description: Optional scenario description
    tags:
      - tag1
      - tag2
    steps:
      - keyword: Given
        text: step description
      - keyword: When
        text: action description
      - keyword: Then
        text: expectation description

Schema Reference

Feature Object

feature: string (required)
description: string (optional)
tags: string[] (optional)
scenarios: Scenario[] (required)

Example:

feature: Calculator Operations
description: |
  Testing basic arithmetic operations
  to ensure calculator works correctly
tags:
  - calculator
  - arithmetic
scenarios:
  - # scenario definitions

Scenario Object

name: string (required)
description: string (optional)
tags: string[] (optional)
steps: Step[] (required)

Example:

scenarios:
  - name: Add two numbers
    description: Verify addition operation
    tags:
      - smoke
      - addition
    steps:
      - # step definitions

Step Object

keyword: Given|When|Then|And|But (required)
text: string (required)
parameters: object (optional)

Example:

steps:
  - keyword: Given
    text: a calculator

  - keyword: When
    text: I add two numbers
    parameters:
      a: 5
      b: 3

  - keyword: Then
    text: the result should be expected value
    parameters:
      expected: 8

Parameter Passing

YAML excels at structured parameter passing through the parameters section.

Simple Parameters

steps:
  - keyword: When
    text: I add two numbers
    parameters:
      a: 5
      b: 3

Maps to:

[DriverMethod("I add two numbers")]
public Task Add(int a, int b)

Complex Values

steps:
  - keyword: When
    text: I login with credentials
    parameters:
      username: "john.doe@example.com"
      password: "P@ssw0rd with spaces!"
      rememberMe: true

Maps to:

[DriverMethod("I login with credentials")]
public Task Login(string username, string password, bool rememberMe)

Mixed Sources

Parameters can come from both pattern placeholders and YAML parameters:

steps:
  - keyword: When
    text: I process value 123
    parameters:
      mode: "advanced"
      retries: 3
[DriverMethod("I process value {value}")]
public Task Process(int value, string mode, int retries)
{
    // value = 123 (from text)
    // mode = "advanced" (from parameters)
    // retries = 3 (from parameters)
}

Complete Example

feature: User Management
description: Testing user registration and authentication flows
tags:
  - user-management
  - authentication

scenarios:
  - name: Register new user
    tags:
      - registration
      - smoke
    steps:
      - keyword: Given
        text: the registration page is open

      - keyword: When
        text: I submit registration form
        parameters:
          username: "newuser123"
          email: "newuser@example.com"
          password: "SecureP@ssw0rd!"

      - keyword: Then
        text: account should be created

      - keyword: And
        text: I should receive confirmation email
        parameters:
          to: "newuser@example.com"

  - name: Login with valid credentials
    tags:
      - authentication
      - smoke
    steps:
      - keyword: Given
        text: a registered user
        parameters:
          username: "existinguser"
          password: "P@ssw0rd123"

      - keyword: When
        text: I provide credentials
        parameters:
          username: "existinguser"
          password: "P@ssw0rd123"

      - keyword: Then
        text: I should be authenticated

      - keyword: And
        text: I should see the dashboard

  - name: Login with invalid password
    tags:
      - authentication
      - error-handling
    steps:
      - keyword: Given
        text: a registered user
        parameters:
          username: "testuser"
          password: "correct-password"

      - keyword: When
        text: I provide wrong password
        parameters:
          username: "testuser"
          password: "wrong-password"

      - keyword: Then
        text: authentication should fail

      - keyword: And
        text: I should see error message
        parameters:
          message: "Invalid credentials"

Usage in Tests

using TinyBDD.Extensions.FileBased;

public class UserManagementTests : FileBasedTestBase<UserManagementDriver>
{
    [Fact]
    public async Task ExecuteUserManagementScenarios()
    {
        await ExecuteScenariosAsync(options =>
        {
            options.AddYamlFiles("Features/UserManagement.yml")
                   .WithBaseDirectory(Directory.GetCurrentDirectory());
        });
    }
}

Driver Implementation

public class UserManagementDriver : IApplicationDriver
{
    private string? _currentUser;
    private bool _isAuthenticated;

    [DriverMethod("the registration page is open")]
    public Task OpenRegistrationPage()
    {
        // Implementation
        return Task.CompletedTask;
    }

    [DriverMethod("I submit registration form")]
    public async Task SubmitRegistration(
        string username,
        string email,
        string password)
    {
        // Parameters come from YAML parameters section
        await _userService.RegisterAsync(username, email, password);
        _currentUser = username;
    }

    [DriverMethod("account should be created")]
    public async Task<bool> AccountExists()
    {
        var user = await _userService.GetUserAsync(_currentUser!);
        return user != null;
    }

    [DriverMethod("I provide credentials")]
    public async Task Login(string username, string password)
    {
        _isAuthenticated = await _authService.LoginAsync(username, password);
    }

    [DriverMethod("I should be authenticated")]
    public Task<bool> IsAuthenticated()
    {
        return Task.FromResult(_isAuthenticated);
    }

    public Task InitializeAsync(CancellationToken ct = default) => Task.CompletedTask;
    public Task CleanupAsync(CancellationToken ct = default) => Task.CompletedTask;
}

Parameter Type Conversion

YAML parameters are automatically converted to method parameter types:

YAML Type C# Type Example
string string username: "john"
number int, long, double, decimal count: 42
boolean bool enabled: true
null nullable types value: null

Custom Type Conversion

For complex types, use string parameters and convert in the driver method:

parameters:
  birthDate: "1990-01-15"
[DriverMethod("I register user")]
public Task RegisterUser(string birthDate)
{
    var date = DateTime.Parse(birthDate);
    // Use converted value
}

Best Practices

Use Gherkin Keywords Appropriately

# Good: Follows Gherkin semantics
steps:
  - keyword: Given
    text: initial state
  - keyword: When
    text: action
  - keyword: Then
    text: expectation

# Avoid: Misusing keywords
steps:
  - keyword: Then
    text: set up database  # Should be Given
  - keyword: Given
    text: result is valid  # Should be Then

Leverage Parameters for Complex Data

# Good: Complex values in parameters
steps:
  - keyword: When
    text: I process order
    parameters:
      customerId: "CUST-12345"
      items:
        - "ITEM-001"
        - "ITEM-002"
      shippingAddress: "123 Main St, City, State 12345"

# Avoid: Trying to encode in text
steps:
  - keyword: When
    text: I process order CUST-12345 with items ITEM-001,ITEM-002 to 123 Main St, City, State 12345

Keep Step Text Readable

# Good: Text describes intent
steps:
  - keyword: When
    text: I create user account
    parameters:
      username: "john.doe"
      email: "john@example.com"

# Avoid: Parameter names in text
steps:
  - keyword: When
    text: I create user with username and email
    parameters:
      username: "john.doe"
      email: "john@example.com"

Programmatic Generation

YAML format is ideal for generating scenarios programmatically:

var scenarios = new List<object>();

foreach (var testCase in testCases)
{
    scenarios.Add(new
    {
        name = $"Test {testCase.Name}",
        tags = new[] { "generated", testCase.Category },
        steps = new[]
        {
            new { keyword = "Given", text = "system is ready" },
            new
            {
                keyword = "When",
                text = "I execute test case",
                parameters = new { input = testCase.Input }
            },
            new
            {
                keyword = "Then",
                text = "output should match expected",
                parameters = new { expected = testCase.Expected }
            }
        }
    });
}

var yaml = new
{
    feature = "Generated Test Cases",
    scenarios = scenarios
};

File.WriteAllText("generated-tests.yml",
    new SerializerBuilder().Build().Serialize(yaml));

Validation

YAML files are validated at parse time:

  • Required fields: feature, scenarios, name, keyword, text
  • Valid keywords: Given, When, Then, And, But
  • Structure: Proper nesting and types

Example error:

feature: Test
scenarios:
  - name: Invalid Scenario
    steps:
      - keyword: Invalid  # ERROR: Invalid keyword
        text: something

Throws: InvalidOperationException: Invalid step keyword 'Invalid'

Limitations

No Scenario Outlines

YAML format does not support Scenario Outline syntax. Use multiple scenarios or programmatic generation:

# Instead of Scenario Outline with Examples:
scenarios:
  - name: Add 2 and 3
    steps:
      - keyword: When
        text: I add numbers
        parameters: { a: 2, b: 3 }
      - keyword: Then
        text: result is value
        parameters: { expected: 5 }

  - name: Add 4 and 5
    steps:
      - keyword: When
        text: I add numbers
        parameters: { a: 4, b: 5 }
      - keyword: Then
        text: result is value
        parameters: { expected: 9 }

No Background

Background sections are not supported. Include setup steps in each scenario or use driver initialization.

Return to: File-Based DSL | Extensions