Skip to content

Repository files navigation

Ensure.Generator

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

NuGetNuGetLicense.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
# Options:# -s, --specs : Path to specs directory (default: "Specs" for C#, "specs" for TypeScript)# -o, --output : Output directory for generated tests (default: "Generated" for C#, "tests" for TypeScript)# -n, --namespace : Namespace for generated C# tests (required for C#)# -p, --preserve-location : Generate test files in the same location as spec files

The generator will:

  • Recursively search for spec files in the specs directory and its subdirectories
  • By default, generate all test files in the output directory with namespace YourNamespace.Generated
  • With -p, generate test files alongside their corresponding spec files
  • When using -p with C#, the namespace will reflect the exact folder structure (e.g., if your folders are Features/Auth/OAuth, the namespace will be YourNamespace.Features.Auth.OAuth without the .Generated suffix)

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 ClasspublicabstractclassLoginFeatureStepsBase{/// <summary>/// Navigate to "/login"/// </summary>publicabstractTaskNavigateTo(stringparam1);/// <summary>/// Enter "test@example.com" into "email" field/// </summary>publicabstractTaskEnterIntoField(stringparam1,stringparam2);/// <summary>/// Click "Sign In" button/// </summary>publicabstractTaskClickButton(stringparam1);/// <summary>/// Verify text "Welcome back" is shown/// </summary>publicabstractTaskVerifyTextIsShown(stringparam1);}// Generated Tests Base ClasspublicabstractclassLoginFeatureTestsBase{protectedabstractLoginFeatureStepsBaseSteps{get;}[Fact]publicasyncTaskSuccessfulLogin(){awaitSteps.NavigateTo("/login");awaitSteps.EnterIntoField("test@example.com","email");awaitSteps.EnterIntoField("password123","password");awaitSteps.ClickButton("Sign In");awaitSteps.VerifyTextIsShown("Welcome back");}// ... other test methods}

TypeScript Generated Code (Playwright)

// Generated Steps Base ClassexportabstractclassLoginFeatureStepsBase{/** * Navigate to "/login" */abstractnavigateTo(param1: string): Promise<void>;/** * Enter "test@example.com" into "email" field */abstractenterIntoField(param1: string,param2: string): Promise<void>;/** * Click "Sign In" button */abstractclickButton(param1: string): Promise<void>;/** * Verify text "Welcome back" is shown */abstractverifyTextIsShown(param1: string): Promise<void>;}// Generated Tests Base ClassexportabstractclassLoginFeatureTestsBase{protectedabstractgetSteps(page: Page): LoginFeatureStepsBase;test('Successful Login',async({ page })=>{conststeps=this.getSteps(page);awaitsteps.navigateTo('/login');awaitsteps.enterIntoField('test@example.com','email');awaitsteps.enterIntoField('password123','password');awaitsteps.clickButton('Sign In');awaitsteps.verifyTextIsShown('Welcome back');});// ... other test methods}

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

C# Implementation (xUnit)

publicclassLoginFeatureTests:LoginFeatureTestsBase{protectedoverrideLoginFeatureStepsBaseSteps=>new();}publicclassLoginFeatureSteps:LoginFeatureStepsBase{publicoverrideasyncTaskNavigateTo(stringurl){// Your implementation here}publicoverrideasyncTaskEnterIntoField(stringtext,stringfield){// Your implementation here}publicoverrideasyncTaskClickButton(stringbutton){// Your implementation here}publicoverrideasyncTaskVerifyTextIsShown(stringtext){// Your implementation here}}

TypeScript Implementation (Playwright)

classLoginFeatureStepsextendsLoginFeatureStepsBase{constructor(privatepage: Page){super();}asyncnavigateTo(url: string): Promise<void>{// Your implementation here}asyncenterIntoField(text: string,field: string): Promise<void>{// Your implementation here}asyncclickButton(button: string): Promise<void>{// Your implementation here}asyncverifyTextIsShown(text: string): Promise<void>{// Your implementation here}}exportclassLoginFeatureTestsextendsLoginFeatureTestsBase{protectedgetSteps(page: Page): LoginFeatureStepsBase{returnnewLoginFeatureSteps(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 with folder structure support
  • Recursive spec file search in subdirectories
  • Option to generate test files alongside spec files

License

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

About

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

Resources

Stars

4 stars

Watchers

2 watching

Forks

Contributors

Languages