Alpha - API stabilizing, expect some breaking changes
RSpec-inspired BDD testing framework for .NET 10.
DraftSpec brings the elegant describe/it/expect syntax to .NET, filling the gap left by abandoned BDD frameworks like NSpec.
- .NET 10 SDK
1. Install the CLI:
dotnet tool install -g DraftSpec.Cli --prerelease2. 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);
});
});3. Run it:
draftspec run Calculator.spec.csxOutput:
Calculator
adds numbers
handles negatives
2 passed
Run specs via dotnet test with full IDE Test Explorer support:
# Add package to your test project
dotnet add package DraftSpec.TestingPlatform --prerelease
# Add spec files (*.spec.csx) to your project
# Run tests
dotnet testFeatures:
- Visual Studio / VS Code / Rider Test Explorer integration
- Click-to-navigate from test results to source
- Built-in code coverage collection
- Standard
dotnet testCI/CD integration
See MTP Integration Guide for full documentation.
describe("User", () =>
{
describe("when logged in", () =>
{
it("can view dashboard", () => { /* ... */ });
it("can update profile", () => { /* ... */ });
});
describe("when logged out", () =>
{
it("redirects to login", () => { /* ... */ });
});
});describe("Database", () =>
{
beforeAll(() => { /* open connection once */ });
afterAll(() => { /* close connection */ });
before(() => { /* begin transaction */ });
after(() => { /* rollback transaction */ });
it("inserts record", () => { /* ... */ });
});Hook execution order: beforeAll -> before (parent to child) -> spec -> after (child to parent) -> afterAll
it("fetches data", async () =>
{
var result = await httpClient.GetAsync("/api/users");
expect(result.StatusCode).toBe(HttpStatusCode.OK);
});fit("only this runs", () => { }); // Focus: only focused specs run
xit("this is skipped", () => { }); // Skip: explicitly disabled
it("this is pending"); // Pending: no body = pending// 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();# 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 failureCreate 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.
- Console - Human-readable output (default)
- JSON - Structured results for tooling
- HTML - Visual report for browsers
- Markdown - For documentation and GitHub
- JUnit - For CI/CD integration
DraftSpec includes an MCP server for AI-assisted testing workflows:
dotnet run --project src/DraftSpec.McpSecurity Warning: The MCP server executes arbitrary C# code with full process privileges. See SECURITY.md for deployment recommendations and 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 |
See MCP documentation for detailed usage.
DraftSpec includes ready-to-use workflow templates for GitHub Actions, GitLab CI, and Azure Pipelines.
Quick start (GitHub Actions):
# .github/workflows/tests.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- run: dotnet tool install -g DraftSpec.Cli --prerelease
- run: draftspec validate --static --strict # Fast structural check
- run: draftspec run . # Run all specsAdd a badge to your README:
[](https://github.com/USER/REPO/actions/workflows/tests.yml)See CI/CD Integration Guide for workflow templates including parallel testing, incremental PR tests, and coverage reporting.
- Getting Started - Installation and first spec
- DSL Reference - Complete API for describe/it/hooks
- Assertions - Full expect() API reference
- CLI Reference - Command-line options
- CI/CD Integration - Workflow templates and best practices
- MTP Integration - dotnet test and IDE integration
- Configuration - Settings and customization
Alpha (v0.4.x) - Core functionality is stable with 2000+ tests and 80%+ code coverage. API is stabilizing but may have breaking changes before v1.0.
We use a PR-based workflow with branch protection on main.
# 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 feat/your-featureSee CONTRIBUTING.md for the full development guide.
Julia 💻 🤔 🚧 |