Ensure.Generator 0.4.0

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global Ensure.Generator --version 0.4.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Ensure.Generator --version 0.4.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Ensure.Generator&version=0.4.0
                    
nuke :add-package Ensure.Generator --version 0.4.0
                    

Ensure.Generator

A .NET tool for generating test code from specification files.

NuGet NuGet License .NET

Inspired by SpecFlow and Gauge, but with a focus on simplicity and modern features. Ensure.Generator takes a lightweight approach by focusing solely on generating clean, typed test code from simple markdown specifications.

Why Executable Specifications?

In today's rapidly evolving software landscape, acceptance tests and executable specifications are becoming increasingly crucial. They serve as living documentation that evolves with your codebase, ensuring that your tests always reflect the current business requirements. Learn more about why this approach is gaining traction in this detailed overview video.

Installation

dotnet tool install --global Ensure.Generator

Usage

  1. Create a specification file (e.g., login.spec.md) in your test project
  2. Run the generator:
# For C#
ensure csharp -s path/to/specs -o path/to/output -n YourNamespace

# For TypeScript
ensure typescript -s path/to/specs -o path/to/output

Examples

Login Feature Specification

# Login Feature

## Successful Login
- Navigate to "/login"
- Enter "test@example.com" into "email" field
- Enter "password123" into "password" field
- Click "Sign In" button
- Verify text "Welcome back" is shown

## Invalid Credentials
- Navigate to "/login"
- Enter "wrong@example.com" into "email" field
- Enter "wrongpass" into "password" field
- Click "Sign In" button
- Verify text "Invalid credentials" is shown

Table-Driven Tests

# User Data Validation

## Validate Multiple Users
- Load test users
| Name  | Age | Email           |
|-------|-----|-----------------|
| John  | 25  | john@email.com  |
| Alice | 30  | alice@email.com |
- Validate all users
- Check validation results

Generated Code

The tool generates both test classes and step definitions in C# or TypeScript.

C# Generated Code (xUnit)

// Generated Steps Base Class
public abstract class LoginFeatureStepsBase
{
    /// <summary>
    /// Navigate to "/login"
    /// </summary>
    public abstract Task NavigateTo(string param1);

    /// <summary>
    /// Enter "test@example.com" into "email" field
    /// </summary>
    public abstract Task EnterIntoField(string param1, string param2);

    /// <summary>
    /// Click "Sign In" button
    /// </summary>
    public abstract Task ClickButton(string param1);

    /// <summary>
    /// Verify text "Welcome back" is shown
    /// </summary>
    public abstract Task VerifyTextIsShown(string param1);
}

// Generated Tests Base Class
public abstract class LoginFeatureTestsBase
{
    protected abstract LoginFeatureStepsBase Steps { get; }

    [Fact]
    public async Task SuccessfulLogin()
    {
        await Steps.NavigateTo("/login");
        await Steps.EnterIntoField("test@example.com", "email");
        await Steps.EnterIntoField("password123", "password");
        await Steps.ClickButton("Sign In");
        await Steps.VerifyTextIsShown("Welcome back");
    }

    // ... other test methods
}

TypeScript Generated Code (Playwright)

// Generated Steps Base Class
export abstract class LoginFeatureStepsBase {
    /**
     * Navigate to "/login"
     */
    abstract navigateTo(param1: string): Promise<void>;

    /**
     * Enter "test@example.com" into "email" field
     */
    abstract enterIntoField(param1: string, param2: string): Promise<void>;

    /**
     * Click "Sign In" button
     */
    abstract clickButton(param1: string): Promise<void>;

    /**
     * Verify text "Welcome back" is shown
     */
    abstract verifyTextIsShown(param1: string): Promise<void>;
}

// Generated Tests Base Class
export abstract class LoginFeatureTestsBase {
    protected abstract getSteps(page: Page): LoginFeatureStepsBase;

    test('Successful Login', async ({ page }) => {
        const steps = this.getSteps(page);

        await steps.navigateTo('/login');
        await steps.enterIntoField('test@example.com', 'email');
        await steps.enterIntoField('password123', 'password');
        await steps.clickButton('Sign In');
        await steps.verifyTextIsShown('Welcome back');
    });

    // ... other test methods
}

To implement the tests, create concrete classes that inherit from the generated base classes:

C# Implementation (xUnit)

public class LoginFeatureTests : LoginFeatureTestsBase
{
    protected override LoginFeatureSteps Steps => new();
}

public class LoginFeatureSteps : LoginFeatureStepsBase
{
    public override async Task NavigateTo(string url)
    {
        // Your implementation here
    }

    public override async Task EnterIntoField(string text, string field)
    {
        // Your implementation here
    }

    public override async Task ClickButton(string button)
    {
        // Your implementation here
    }

    public override async Task VerifyTextIsShown(string text)
    {
        // Your implementation here
    }
}

TypeScript Implementation (Playwright)

class LoginFeatureSteps extends LoginFeatureStepsBase {
    constructor(private page: Page) {
        super();
    }

    async navigateTo(url: string): Promise<void> {
        // Your implementation here
    }

    async enterIntoField(text: string, field: string): Promise<void> {
        // Your implementation here
    }

    async clickButton(button: string): Promise<void> {
        // Your implementation here
    }

    async verifyTextIsShown(text: string): Promise<void> {
        // Your implementation here
    }
}

export class LoginFeatureTests extends LoginFeatureTestsBase {
    protected getSteps(page: Page): LoginFeatureStepsBase {
        return new LoginFeatureSteps(page);
    }
}

Features

  • Generates test code from markdown specification files
  • Supports both C# (xUnit) and TypeScript (Playwright) output
  • Clean, typed step definitions
  • Simple bullet-point style steps
  • Table-driven test scenarios
  • Automatic parameter extraction from quoted strings
  • No Gherkin/Cucumber syntax - just plain English
  • First-class Playwright support for TypeScript output
  • Proper namespace handling for C# output

License

This project is licensed under the MIT License - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.4.3 766 2/23/2025
0.4.2 111 2/23/2025
0.4.1 123 2/23/2025
0.4.0 100 2/23/2025
0.3.2 110 1/31/2025
0.3.1 99 1/31/2025
0.3.0 106 1/31/2025
0.2.1 108 1/25/2025
0.2.0 109 1/25/2025
0.1.0 113 1/25/2025