Skip to content

GherXUnit emerges as a viable alternative for those seeking an approach that combines the expressiveness of BDD with the well-established structure of xUnit.

License

Notifications You must be signed in to change notification settings

emergingcode/gherxunit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

71 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

πŸš€ GherXUnit: An Alternative for BDD with xUnit

NuGet

The adoption of Behavior-Driven Development (BDD) has become increasingly common in software development, promoting better communication between technical and non-technical teams. However, its integration with traditional testing frameworks is not always straightforward.

Important: According to the study Behavior Driven Development: A Systematic Literature Review (Farooq et al., 2023, IEEE Access), some recurring difficulties in using BDD include:

  • Complex automation: Integration with external tools can increase configuration and test execution complexity.
  • Difficult maintenance: As the test base grows, Gherkin scenarios can become hard to manage.
  • Learning curve: The need to master new tools can hinder BDD adoption, especially in teams already familiar with traditional frameworks.

GherXunit emerges as a viable alternative for teams looking to explore the benefits of BDD within the xUnit framework, without requiring external tools such as Cucumber or SpecFlow. It acts as a superset of xUnit, allowing tests to be written in Gherkin.


βœ… Where Can GherXunit Help?

  • Using Gherkin syntax directly in xUnit, reducing external dependencies.
  • More modular and organized code, using partial classes to separate scenarios and steps.
  • Better integration with unit tests, allowing a smoother transition between different levels of testing.

πŸ“¦ Getting Started

This package is available through NuGet Packages.

Version Downloads Status
NuGet Nuget .NET

Install via NuGet:

dotnet add package GherXunit

πŸ’‘ How Does It Work?

The core idea of GherXunit is to allow test scenarios to be written in a structure familiar to those already using xUnit. For that, it provides a set of attributes and methods that allow the definition of test scenarios using Gherkin syntax.

πŸ“Œ Example of Scenario Definition

using GherXunit.Annotations;

[Feature("Subscribers see different articles based on their subscription level")]
public partial class SubscriptionTest
{
    [Scenario("Free subscribers see only the free articles")]
    async Task WhenFriedaLogs() => await this.ExecuteAscync(
        refer: WhenFriedaLogsSteps,
        steps: """
               Given Free Frieda has a free subscription
               When Free Frieda logs in with her valid credentials
               Then she sees a Free article
               """);

    [Scenario("Subscriber with a paid subscription can access both free and paid articles")]
    void WhenPattyLogs() => this.Execute(
        refer: WhenPattyLogsSteps,
        steps: """
               Given Paid Patty has a basic-level paid subscription
               When Paid Patty logs in with her valid credentials
               Then she sees a Free article and a Paid article
               """);
}

πŸ“Œ Example of Step Implementation

public partial class SubscriptionTest(ITestOutputHelper output): IGherXunit
{
    public ITestOutputHelper Output { get; } = output;
    private void WhenPattyLogsSteps() => Assert.True(true);
    private async Task WhenFriedaLogsSteps() => await Task.CompletedTask;
}

Tip: In this example, the SubscriptionTest class is split into two files. The first file defines the test scenarios, while the second file defines the step methods. Using partial allows both files to contribute to the definition of the same SubscriptionTest class.

πŸ“Œ Example of Output

TEST RESULT: 🟒 SUCCESS
β€· FEATURE Subscribers see different articles based on their subscription level
  β€· SCENARIO Free subscribers see only the free articles
    | GIVEN β†˜ Free Frieda has a free subscription
    |  WHEN β†˜ Free Frieda logs in with her valid credentials
    |  THEN β†˜ she sees a Free article

TEST RESULT: 🟒 SUCCESS
β€· FEATURE Subscribers see different articles based on their subscription level
  β€· SCENARIO Subscriber with a paid subscription can access both free and paid articles
    | GIVEN β†˜ Paid Patty has a basic-level paid subscription
    |  WHEN β†˜ Paid Patty logs in with her valid credentials
    |  THEN β†˜ she sees a Free article and a Paid article

✏️ Customizing the Lexer

GherXunit allows you to customize the lexical elements of Gherkin, such as Given, When, Then, And, Background, Scenario, and Feature. You can define your custom emojis or symbols to represent these elements. Built-in lexers include Lexers.PtBr (Portuguese) and Lexers.EnUs (English).

Example: Custom Emoji Lexer

public record EmojiGherXunitLexer : IGherXunitLexer
{
    public (string Key, string Value)[] Given => [("Given", "😐")];
    public (string Key, string Value)[] When => [("When", "🎬")];
    public (string Key, string Value)[] Then => [("Then", "πŸ™")];
    public (string Key, string Value)[] And => [("And", "πŸ˜‚")];
    public string Background => "πŸ’€";
    public string Scenario => "πŸ₯’πŸ“•";
    public string Feature => "πŸ“š";
}

🌍 Setting a Global Lexer

From version 1.3.0, you can set a default lexer for all tests in your project or class using GherXunitConfig.DefaultLexer:

public partial class LocalizationTest
{
    static LocalizationTest()
    {
        GherXunitConfig.DefaultLexer = Lexers.PtBr;
    }

    [Scenario("Free articles in Portuguese")]
    async Task WhenFriedaLogs() => await this.ExecuteAscync(
        refer: WhenFriedaLogsSteps,
        steps: """
               Dado Free Frieda possui uma assinatura gratuita
               Quando Free Frieda faz login com suas credenciais vΓ‘lidas
               EntΓ£o ela vΓͺ um artigo gratuito
               """);

    // To override the default lexer for a specific scenario:
    [Scenario("Custom emoji lexer")]
    void WhenPattyLogs() => this.Execute(
        refer: WhenPattyLogsSteps,
        lexer: new EmojiGherXunitLexer(),
        steps: """
               Given Paid Patty has a basic-level paid subscription
               When Paid Patty logs in with her valid credentials
               Then she sees a Free article and a Paid article
               """);
}

Tip: Only specify the lexer parameter if you want to override the global default.


πŸ”Ž Is GherXunit for You?

If your team already uses xUnit and wants to experiment with a BDD approach without drastically changing its workflow, GherXunit may be an option to consider. It does not eliminate all BDD challenges but seeks to facilitate its adoption in environments where xUnit is already widely used. See more usage examples and implementation details for Background, Rule, Features, and other elements in the sample code available in the GherXunit repository.


πŸ“š References

  • Farooq, M. S., et al. (2023). Behavior Driven Development: A Systematic Literature Review. IEEE Access. DOI
  • North, D. (2006). Introducing BDD. DanNorth.net
  • xUnit. (2023). xUnit.net
  • Gherkin. (2023). Gherkin

About

GherXUnit emerges as a viable alternative for those seeking an approach that combines the expressiveness of BDD with the well-established structure of xUnit.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Languages