DraftSpec 0.4.0-alpha.1

This is a prerelease version of DraftSpec.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package DraftSpec --version 0.4.0-alpha.1
                    
NuGet\Install-Package DraftSpec -Version 0.4.0-alpha.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DraftSpec" Version="0.4.0-alpha.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DraftSpec" Version="0.4.0-alpha.1" />
                    
Directory.Packages.props
<PackageReference Include="DraftSpec" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DraftSpec --version 0.4.0-alpha.1
                    
#r "nuget: DraftSpec, 0.4.0-alpha.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DraftSpec@0.4.0-alpha.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DraftSpec&version=0.4.0-alpha.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=DraftSpec&version=0.4.0-alpha.1&prerelease
                    
Install as a Cake Tool

DraftSpec

CI codecov

⚠️ Alpha - Experimental, expect breaking changes

RSpec-inspired testing for .NET.

DraftSpec brings the elegant describe/it/expect syntax to .NET, filling the gap left by abandoned BDD frameworks like NSpec. Write expressive specs as scripts or traditional test classes.

Requires .NET 8+ for CSX scripts via dotnet-script, or .NET 10+ for file-based apps.

Quick Start

1. Install dotnet-script:

dotnet tool install -g dotnet-script

2. Create a spec file (Calculator.spec.csx):

#r "nuget: DraftSpec, *"
using static DraftSpec.Dsl;

describe("Calculator", () =>
{
    it("adds numbers", () =>
    {
        expect(1 + 1).toBe(2);
    });

    it("handles negatives", () =>
    {
        expect(-1 + -1).toBe(-2);
    });
});

run();

3. Run it:

dotnet script Calculator.spec.csx

Output:

Calculator
  ✓ adds numbers
  ✓ handles negatives

2 passed

Features

Nested Contexts

describe("User", () =>
{
    describe("when logged in", () =>
    {
        it("can view dashboard", () => { /* ... */ });
        it("can update profile", () => { /* ... */ });
    });

    describe("when logged out", () =>
    {
        it("redirects to login", () => { /* ... */ });
    });
});

Hooks

describe("Database", () =>
{
    beforeAll(() => { /* open connection once */ });
    afterAll(() => { /* close connection */ });

    before(() => { /* begin transaction */ });
    after(() => { /* rollback transaction */ });

    it("inserts record", () => { /* ... */ });
});

Async Support

it("fetches data", async () =>
{
    var result = await httpClient.GetAsync("/api/users");
    expect(result.StatusCode).toBe(HttpStatusCode.OK);
});

Focus & Skip

fit("only this runs", () => { });     // Focus: only focused specs run
xit("this is skipped", () => { });    // Skip: explicitly disabled
it("this is pending");                 // Pending: no body = pending

Assertions

// Equality
expect(value).toBe(expected);
expect(value).toBeNull();
expect(value).toNotBeNull();

// Numbers
expect(count).toBeGreaterThan(0);
expect(count).toBeLessThan(100);
expect(price).toBeCloseTo(19.99, 0.01);

// Strings
expect(name).toContain("Smith");
expect(email).toStartWith("user@");
expect(path).toEndWith(".txt");

// Booleans
expect(isValid).toBeTrue();
expect(isEmpty).toBeFalse();

// Collections
expect(items).toContain("apple");
expect(items).toHaveCount(3);
expect(items).toBeEmpty();

// Exceptions
expect(() => Divide(1, 0)).toThrow<DivideByZeroException>();
expect(() => SafeOperation()).toNotThrow();

CLI Tool

# Run specs
draftspec run .                       # Run all *.spec.csx in current directory
draftspec run ./specs                 # Run specs in directory
draftspec run MySpec.spec.csx         # Run single file

# Output formats
draftspec run . --format json         # JSON output
draftspec run . --format html -o report.html

# Watch mode
draftspec watch .                     # Re-run on file changes

# Parallel execution and filtering
draftspec run . --parallel            # Run spec files in parallel
draftspec run . --tags unit,fast      # Only run specs with these tags
draftspec run . --exclude-tags slow   # Exclude specs with these tags
draftspec run . --bail                # Stop on first failure

dotnet test Integration (MTP)

Run specs via dotnet test with full IDE Test Explorer support:

# Create a test project
dotnet new classlib -n MyProject.Specs
cd MyProject.Specs
dotnet add package DraftSpec.TestingPlatform

# Add spec files (*.spec.csx)
# Run tests
dotnet test

# With coverage
dotnet test --collect:"XPlat Code Coverage"

Features:

  • Visual Studio / VS Code / Rider Test Explorer integration
  • Click-to-navigate from test results to source
  • Built-in code coverage collection
  • Standard dotnet test CI/CD integration

See MTP Integration Guide for full documentation.

Configuration File

Create a draftspec.json in your project for persistent settings:

{
  "parallel": true,
  "timeout": 10000,
  "bail": false,
  "tags": {
    "include": ["unit", "fast"],
    "exclude": ["slow", "integration"]
  },
  "reporters": ["console", "json"],
  "noCache": false
}

CLI options override config file values.

MCP Server (AI Integration)

DraftSpec includes an MCP server for AI-assisted testing:

# Add to Claude Desktop, VS Code, etc.
dotnet run --project src/DraftSpec.Mcp

⚠️ Security Warning: The MCP server executes arbitrary C# code with full process privileges. See SECURITY.md for:

  • Security model and trust assumptions
  • Deployment recommendations
  • Container isolation guidance

Tools:

Tool Description
run_spec Execute spec code and return structured JSON results
scaffold_specs Generate pending specs from a structured description
parse_assertion Convert natural language to expect() syntax

parse_assertion - Convert natural language assertions to DraftSpec code:

// Input
{ "naturalLanguage": "should be greater than 5", "variableName": "count" }

// Output
{ "success": true, "code": "expect(count).toBeGreaterThan(5)", "confidence": 0.95 }

Supported patterns:

  • "should not be null"expect(x).toNotBeNull()
  • "should contain 'hello'"expect(x).toContain("hello")
  • "should have 3 items"expect(x).toHaveCount(3)
  • "should throw ArgumentException"expect(() => x).toThrow<ArgumentException>()

scaffold_specs - Generate spec scaffolds for BDD (behavior-first) or characterisation (code-first) workflows:

{
  "description": "UserService",
  "contexts": [
    { "description": "Create", "specs": ["creates user", "hashes password"] },
    { "description": "GetById", "specs": ["returns user when found", "returns null when not found"] }
  ]
}

Output:

describe("UserService", () =>
{
    describe("Create", () =>
    {
        it("creates user");
        it("hashes password");
    });

    describe("GetById", () =>
    {
        it("returns user when found");
        it("returns null when not found");
    });
});

Agents can scaffold specs, then fill in assertions using run_spec to verify.

Middleware & Plugins

configure(runner => runner
    .WithRetry(3)                     // Retry failed specs
    .WithTimeout(5000)                // 5 second timeout
    .WithParallelExecution()          // Run specs in parallel
);

Documentation

Contributing

We use a PR-based workflow with branch protection on main.

Development

# Clone and build
git clone https://github.com/juvistr/draftspec.git
cd draftspec
dotnet build

# Run tests
dotnet run --project tests/DraftSpec.Tests

# Create a branch for your changes
git checkout -b feature/your-feature

Pull Request Process

  1. Create a feature branch from main
  2. Make your changes with tests
  3. Push and open a PR
  4. CI runs automatically (build, test, pack)
  5. After review and approval, squash-merge to main

Releases

Releases are triggered by pushing version tags:

git tag v0.1.0-alpha.1
git push origin v0.1.0-alpha.1

This triggers the publish workflow which:

  • Builds and tests the code
  • Packs NuGet packages (version from tag via MinVer)
  • Publishes to nuget.org
  • Creates a GitHub Release with auto-generated notes

Branch Protection (Maintainers)

Recommended settings for main:

  • Require PR reviews before merging
  • Require status checks (CI workflow)
  • Require linear history (squash merging)
  • No direct pushes to main

Status

Alpha - This is an early experiment, built in roughly a day with AI assistance. It works, but expect rough edges, missing features, and breaking changes.

If you try it and hit issues, feedback is welcome via GitHub issues.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on DraftSpec:

Package Downloads
DraftSpec.Mcp

MCP server for DraftSpec - run specs from AI assistants

DraftSpec.Scripting

Roslyn-based CSX script host for DraftSpec spec execution

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.1-alpha.1 66 1/4/2026
0.8.0-alpha.1 63 1/3/2026
0.7.1-alpha.1 63 1/2/2026
0.7.0-alpha.2 64 1/2/2026
0.7.0-alpha.1 57 1/1/2026
0.6.3-alpha.1 68 12/31/2025
0.6.2-alpha.1 65 12/31/2025
0.6.1-alpha.1 67 12/30/2025
0.6.0-alpha.1 63 12/30/2025
0.5.0-alpha.3 59 12/29/2025
0.5.0-alpha.2 58 12/29/2025
0.5.0-alpha.1 60 12/29/2025
0.4.0-alpha.6 63 12/29/2025
0.4.0-alpha.5 57 12/29/2025
0.4.0-alpha.4 63 12/28/2025
0.4.0-alpha.3 59 12/28/2025
0.4.0-alpha.2 55 12/28/2025
0.4.0-alpha.1 60 12/28/2025
0.3.0-alpha.8 66 12/28/2025
Loading failed