1616| ** TinyBDD.Xunit.v3** | [ ![ NuGet] ( https://img.shields.io/nuget/v/TinyBDD.Xunit.v3.svg )] ( https://www.nuget.org/packages/TinyBDD.Xunit.v3/ ) | [ ![ NuGet Downloads] ( https://img.shields.io/nuget/dt/TinyBDD.Xunit.v3.svg )] ( https://www.nuget.org/packages/TinyBDD.Xunit.v3/ ) |
1717| ** TinyBDD.NUnit** | [ ![ NuGet] ( https://img.shields.io/nuget/v/TinyBDD.NUnit.svg )] ( https://www.nuget.org/packages/TinyBDD.NUnit/ ) | [ ![ NuGet Downloads] ( https://img.shields.io/nuget/dt/TinyBDD.NUnit.svg )] ( https://www.nuget.org/packages/TinyBDD.NUnit/ ) |
1818| ** TinyBDD.Extensions.DependencyInjection** | [ ![ NuGet] ( https://img.shields.io/nuget/v/TinyBDD.Extensions.DependencyInjection.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.DependencyInjection/ ) | [ ![ NuGet Downloads] ( https://img.shields.io/nuget/dt/TinyBDD.Extensions.DependencyInjection.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.DependencyInjection/ ) |
19+ | ** TinyBDD.Extensions.FileBased** | [ ![ NuGet] ( https://img.shields.io/nuget/v/TinyBDD.Extensions.FileBased.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.FileBased/ ) | [ ![ NuGet Downloads] ( https://img.shields.io/nuget/dt/TinyBDD.Extensions.FileBased.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.FileBased/ ) |
1920| ** TinyBDD.Extensions.Hosting** | [ ![ NuGet] ( https://img.shields.io/nuget/v/TinyBDD.Extensions.Hosting.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.Hosting/ ) | [ ![ NuGet Downloads] ( https://img.shields.io/nuget/dt/TinyBDD.Extensions.Hosting.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.Hosting/ ) |
2021| ** TinyBDD.Extensions.Reporting** | [ ![ NuGet] ( https://img.shields.io/nuget/v/TinyBDD.Extensions.Reporting.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.Reporting/ ) | [ ![ NuGet Downloads] ( https://img.shields.io/nuget/dt/TinyBDD.Extensions.Reporting.svg )] ( https://www.nuget.org/packages/TinyBDD.Extensions.Reporting/ ) |
2122
2223---
2324
24- ** TinyBDD** is a minimal, fluent ** Behavior-Driven Development** library for .NET.
25- It provides a lightweight ` Given ` / ` When ` / ` Then ` syntax with optional ` And ` / ` But ` chaining, supporting both ** sync** and ** async** steps.
25+ ** TinyBDD** is a minimal, fluent ** Behavior-Driven Development** library for .NET.
26+ It supports two complementary approaches:
27+ - ** Code-first** : Fluent ` Given ` / ` When ` / ` Then ` syntax directly in C#
28+ - ** File-based** : Gherkin ` .feature ` files and YAML scenarios with convention-based drivers
2629
27- It is designed to:
30+ Both approaches are designed to:
2831
2932- Be ** framework-agnostic** (works with MSTest, xUnit, NUnit, etc.).
30- - Keep scenarios ** clear and concise** without heavy DSLs or external tooling .
31- - Support ** async and sync predicates ** for maximum flexibility.
32- - Integrate with existing test runners’ output for easy step visibility.
33+ - Keep scenarios ** clear and concise** with readable syntax .
34+ - Support ** async and sync** operations for maximum flexibility.
35+ - Integrate with existing test runners' output for easy step visibility.
3336
3437
3538---
3639
3740## Features
3841
42+ ### Code-First Approach
43+
3944- ** Readable BDD syntax** :
4045 ``` csharp
4146 await Given (" a number" , () => 5 )
@@ -61,6 +66,33 @@ It is designed to:
6166 But != 11 [OK]
6267 ```
6368
69+ ### File-Based Approach
70+
71+ - ** Gherkin .feature files** :
72+ ``` gherkin
73+ Feature: Calculator Operations
74+
75+ Scenario: Add two numbers
76+ Given a calculator
77+ When I add 5 and 3
78+ Then the result should be 8
79+ ```
80+
81+ - ** Convention-based driver methods** :
82+ ``` csharp
83+ [DriverMethod (" I add {a} and {b}" )]
84+ public Task Add (int a , int b )
85+ {
86+ _calculator .Add (a , b );
87+ return Task .CompletedTask ;
88+ }
89+ ```
90+
91+ - ** Scenario Outlines** with Examples tables for parameterized tests
92+ - ** YAML format** as alternative to Gherkin for tooling integration
93+
94+ ### Framework Integration
95+
6496- ** Test framework adapters** :
6597
6698 * ** MSTest** : ` TinyBddMsTestBase ` , ` MSTestBddReporter ` , ` MSTestTraitBridge `
@@ -105,6 +137,9 @@ dotnet add package TinyBDD.Xunit.v3
105137For Extensions:
106138
107139``` powershell
140+ # File-Based DSL (Gherkin and YAML)
141+ dotnet add package TinyBDD.Extensions.FileBased
142+
108143# Dependency Injection
109144dotnet add package TinyBDD.Extensions.DependencyInjection
110145
@@ -233,6 +268,109 @@ public class MathTests : TinyBddXunitBase
233268
234269---
235270
271+ ## File-Based Usage
272+
273+ ### Gherkin Feature File
274+
275+ Create ` Features/Calculator.feature ` :
276+
277+ ``` gherkin
278+ Feature: Calculator Operations
279+
280+ @calculator @smoke
281+ Scenario: Add two numbers
282+ Given a calculator
283+ When I add 5 and 3
284+ Then the result should be 8
285+
286+ Scenario Outline: Multiply numbers
287+ Given a calculator
288+ When I multiply <a> and <b>
289+ Then the result should be <expected>
290+
291+ Examples:
292+ | a | b | expected |
293+ | 2 | 3 | 6 |
294+ | 4 | 5 | 20 |
295+ ```
296+
297+ ### Driver Implementation
298+
299+ ``` csharp
300+ using TinyBDD .Extensions .FileBased .Core ;
301+
302+ public class CalculatorDriver : IApplicationDriver
303+ {
304+ private readonly Calculator _calculator = new ();
305+
306+ [DriverMethod (" a calculator" )]
307+ public Task Initialize ()
308+ {
309+ _calculator .Clear ();
310+ return Task .CompletedTask ;
311+ }
312+
313+ [DriverMethod (" I add {a} and {b}" )]
314+ public Task Add (int a , int b )
315+ {
316+ _calculator .Add (a , b );
317+ return Task .CompletedTask ;
318+ }
319+
320+ [DriverMethod (" I multiply {a} and {b}" )]
321+ public Task Multiply (int a , int b )
322+ {
323+ _calculator .Multiply (a , b );
324+ return Task .CompletedTask ;
325+ }
326+
327+ [DriverMethod (" the result should be {expected}" )]
328+ public Task <bool > VerifyResult (int expected )
329+ {
330+ return Task .FromResult (_calculator .GetResult () == expected );
331+ }
332+
333+ public Task InitializeAsync (CancellationToken ct = default ) => Task .CompletedTask ;
334+ public Task CleanupAsync (CancellationToken ct = default ) => Task .CompletedTask ;
335+ }
336+ ```
337+
338+ ### Test Class
339+
340+ ``` csharp
341+ using TinyBDD .Extensions .FileBased ;
342+
343+ public class CalculatorTests : FileBasedTestBase <CalculatorDriver >
344+ {
345+ [Fact ]
346+ public async Task ExecuteCalculatorScenarios ()
347+ {
348+ await ExecuteScenariosAsync (options =>
349+ {
350+ options .AddFeatureFiles (" Features/**/*.feature" )
351+ .WithBaseDirectory (Directory .GetCurrentDirectory ());
352+ });
353+ }
354+ }
355+ ```
356+
357+ Output:
358+
359+ ```
360+ Feature: Calculator Operations
361+ Scenario: Add two numbers
362+ Given a calculator [OK] 0 ms
363+ When I add 5 and 3 [OK] 0 ms
364+ Then the result should be 8 [OK] 1 ms
365+
366+ Scenario Outline: Multiply numbers (Example 1: a=2, b=3, expected=6)
367+ Given a calculator [OK] 0 ms
368+ When I multiply 2 and 3 [OK] 0 ms
369+ Then the result should be 6 [OK] 0 ms
370+ ```
371+
372+ ---
373+
236374## Step Types
237375
238376| Step | Purpose | Example |
@@ -328,18 +466,22 @@ This ensures that all steps passed and throws if any failed.
328466
329467TinyBDD was created with a few guiding principles:
330468
331- 1 . ** Focus on readability, not ceremony**
332- Steps should read like plain English and map directly to Gherkin-style thinking, but without requiring ` .feature `
333- files, extra compilers, or DSL preprocessors.
469+ 1 . ** Focus on readability, not ceremony**
470+ Steps should read like plain English and map directly to Gherkin-style thinking. Choose the approach that best fits your team:
471+ - ** Code-first** : Write BDD tests directly in C# with fluent API
472+ - ** File-based** : Use standard Gherkin ` .feature ` files or YAML for business-readable specifications
473+
474+ 2 . ** Flexible specification approach**
475+ Both approaches produce the same readable output:
476+ - ** Code-first** : Your C# code using the fluent API serves as the executable specification
477+ - ** File-based** : Separate ` .feature ` or YAML files define scenarios, implemented through driver methods
334478
335- 2 . ** Code is the spec**
336- Instead of writing a separate Gherkin text file, you write directly in C# using a fluent API that mirrors ` Given ` →
337- ` When ` → ` Then ` → ` And ` → ` But ` .
338- Your unit test runner output ** is** the human-readable spec.
479+ Your test runner output ** is** the human-readable spec in both cases.
339480
340- 3 . ** Stay out of your way**
341- TinyBDD is not an opinionated test framework; it’s a syntax layer that integrates with MSTest, xUnit, or NUnit and
342- leaves assertions, test discovery, and reporting to them.
481+ 3 . ** Stay out of your way**
482+ TinyBDD is not an opinionated test framework; it's a syntax layer that integrates with MSTest, xUnit, or NUnit and
483+ leaves assertions, test discovery, and reporting to them. Choose code-first for flexibility and complex logic, or
484+ file-based when business analysts need to author test specifications.
343485
344486---
345487
@@ -373,15 +515,23 @@ If a step fails, you’ll see exactly which step failed, how long it took, and t
373515
374516---
375517
376- ## Why Not Use SpecFlow / Cucumber ?
518+ ## Why Use TinyBDD ?
377519
378- SpecFlow, Cucumber, and similar tools are powerful for large-scale BDD, but they :
520+ TinyBDD offers flexibility that traditional BDD tools don't :
379521
380- * Require separate ` .feature ` files and a parser/runner.
381- * Often introduce a disconnect between the feature file and the code that actually runs.
382- * Come with heavier setup and slower test discovery.
522+ ** Compared to SpecFlow / Cucumber:**
523+ * ** Choose your approach** : Start code-first, add ` .feature ` files later when business analysts join, or vice versa
524+ * ** No runtime overhead** : File-based DSL uses convention-based matching without reflection or runtime parsing
525+ * ** Lighter setup** : Works directly with standard test frameworks (xUnit, NUnit, MSTest)
526+ * ** Better IDE support** : Code-first approach gets full IntelliSense, refactoring, and debugging
527+ * ** Simpler integration** : No separate test runners, no complex step binding configurations
383528
384- TinyBDD keeps ** everything in one place** —your test class—while still producing clear, human-readable steps.
529+ ** Unique advantages:**
530+ * Seamlessly switch between approaches as your team's needs evolve
531+ * Both approaches produce identical readable Gherkin-style output
532+ * Test framework agnostic - use the test runner you already know
533+ * Performance-optimized with automatic source generation (code-first)
534+ * Convention-based driver methods for file-based tests (no attribute soup)
385535
386536---
387537
0 commit comments