Featured image of post Testing C# and Python with Behavior-Driven Development (BDD)

Testing C# and Python with Behavior-Driven Development (BDD)

Quick Intro to BDD

This is the C# and Python Version of this Article

The Angular and React Version of this Article is here:
Testing Angular and React with Behavior-Driven Development (BDD)

Also check out

All Testing Articles here:
https://brianbraatz.github.io/search/?keyword=testing

A Brief History of BDD

Once upon a time, in the dark ages of software development (a.k.a the early 2000s), developers and testers were at war.
Developers wrote code that they thought made sense, while testers wrote test cases that developers barely understood. Chaos ensued.

Then, in 2003, Dan North had a revelation: “What if developers and testers spoke the same language?” And thus, Behavior-Driven Development (BDD) was born.

BDD took inspiration from Test-Driven Development (TDD) but aimed to make tests more human-readable, so that business people, testers, and developers could all be on the same page. Instead of cryptic unit test names, BDD focused on describing behavior in plain English using a structured format called Gherkin (yep, like the pickle).

The idea? Tests should be human-readable and describe what the system actually does. That way, even non-tech people (gasp!) could understand what was going on. So instead of writing a test that checks if 2 + 2 === 4, you’d write:

1
2
3
4
Scenario: Adding two numbers
  Given I have a calculator
  When I add 2 and 2
  Then the result should be 4

Now the Non-Engineers and the Engineers have a common way to communicate features and how to test them .

And this plain language, can be used directly- or semi-directly to actually “be” the test!

How Does BDD Compare to Other Testing Approaches?

ApproachWhat It Focuses OnProsCons
TDDWriting tests before codeEnsures code correctnessHarder for non-devs to understand
BDDDefining behavior in human-readable scenariosImproves collaborationMore setup required
Unit TestingTesting small, isolated pieces of codeFast feedback loopDoesn’t test full behavior
Integration TestingEnsuring multiple components work togetherCatches system-wide issuesSlower and more complex

BDD is like TDD’s more extroverted cousin—it wants everyone involved, not just developers.

How to Do BDD: The Gherkin Language

As introduced above, BDD scenarios are written in Gherkin, a simple syntax that follows a Given-When-Then structure:

1
2
3
4
Feature: Login System
  Scenario: Successful Login
    Given a registered user "Alice"\    When they enter valid credentials
    Then they should see the dashboard

Readable, right? Even your non-technical boss can understand that.

Now, let’s implement this in C# and Python!


BDD Example in C# (Using SpecFlow)

Step 1: Install SpecFlow via NuGet:

1
Install-Package SpecFlow

Step 2: Write a Gherkin feature file (Login.feature):

1
2
3
4
5
Feature: Login System
  Scenario: Successful Login
    Given a registered user "Alice"
    When they enter valid credentials
    Then they should see the dashboard

Step 3: Implement step definitions in C#:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[Binding]
public class LoginSteps
{
    private string _username;
    private bool _isLoggedIn;

    [Given("a registered user \"(.*)\"")]
    public void GivenARegisteredUser(string username)
    {
        _username = username;
    }

    [When("they enter valid credentials")]
    public void WhenTheyEnterValidCredentials()
    {
        _isLoggedIn = (_username == "Alice");
    }

    [Then("they should see the dashboard")]
    public void ThenTheyShouldSeeTheDashboard()
    {
        Assert.IsTrue(_isLoggedIn);
    }
}

BDD Example in Python (Using Behave)

Step 1: Install Behave:

1
pip install behave

Step 2: Write a Gherkin feature file (login.feature):

1
2
3
4
5
Feature: Login System
  Scenario: Successful Login
    Given a registered user "Alice"
    When they enter valid credentials
    Then they should see the dashboard

Step 3: Implement step definitions in Python (steps/login_steps.py):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from behave import given, when, then

users = {"Alice": "password123"}

@given('a registered user "{username}"')
def step_given_registered_user(context, username):
    context.username = username

@when("they enter valid credentials")
def step_when_enter_credentials(context):
    context.is_logged_in = context.username in users

@then("they should see the dashboard")
def step_then_see_dashboard(context):
    assert context.is_logged_in

BDD Tools by Language

LanguagePopular BDD Tools
C#SpecFlow, xBehave.NET
PythonBehave, pytest-bdd
JavaCucumber, JBehave
JavaScript/TypeScriptCucumber.js, Jest with Gherkin
RubyCucumber

Yes, you CAN test JavaScript and TypeScript with BDD! Cucumber.js lets you write tests in Gherkin just like in Python or C#.


Key Ideas

ConceptDescription
BDD OriginCreated by Dan North in 2003 to improve collaboration
GherkinA human-readable language for writing test scenarios
C# BDDUses SpecFlow for Gherkin-based tests
Python BDDUses Behave to implement Gherkin tests
ToolsSpecFlow, Behave, Cucumber, and more
JS/TS SupportYes! Cucumber.js makes it possible

References

  1. Dan North on Introducing BDD
  2. SpecFlow Documentation
  3. Behave Documentation
  4. Cucumber.js
  5. Jest with Gherkin