DEV Community

Cover image for Given When Then
Adam Lewis
Adam Lewis

Posted on

Given When Then

Today I'm happy to announce that I have released my first public Nuget package today! And in true Christmas fashion, I'd like to share it with you dear reader as a potential way to improve the quality of your testing code :)

nuget
Source

Motivation

Writing tests under the "Given When Then" approach is something I've come to appreciate these last few years for its ability to produce clear and easy to follow test cases. This style of test writing is covered extensively elsewhere, but speaking generally the base concept is:

  • Given an initial state
  • When something happens
  • Then the result is/these things happen

Where I work there is a heavy focus on making test names as close to plain English as possible. The benefits of this are two fold:
1) Code is easier to maintain as a developer
2) Code is easier for less technical testers to evaluate whether there is sufficient coverage

But when writing tests however I noticed that I was starting to feel minor annoyances with the quality of code being produced. Naming could quickly get out of hand when trying to follow the given-when-then pattern:

public void Given_the_database_is_empty_when_searching_for_open_orders_then_it_returns_no_orders_found()
{
    ...
}
Enter fullscreen mode Exit fullscreen mode

Spurred on by this problem, I did what any good Software Engineer should - apply some creative thinking. GivenWhenThen is the result and it aims to make writing tests in this style as simple as:

[TestCaseSource(nameof(TestCases))]
public void TestThat(
    GivenWhenThenTestCase toRun)
{
    toRun.RunTestCase();
}

public static IEnumerable<GivenWhenThenTestCaseData> TestCases
{
    get
    {
        yield return GivenWhenThen.Create(
            Given.UsernameValidationFails,
            When.FredTriesToLogOn,
            Then.LogOnFailsBecauseTheUserIsNotValid);
        yield return GivenWhenThen.Create(
            Given.NoUsersExist,
            When.FredTriesToLogOn,
            Then.LogOnFailsBecauseTheUserDidNotExist);
        yield return GivenWhenThen.Create(
            Given.FredExists,
            When.FredTriesToLogOn,
            Then.LogOnSucceeds);
    }
}
Enter fullscreen mode Exit fullscreen mode

Which to my eyes reads beautifully and renders wonderfully in a test runner too:

Runner Example

Thoughts?

More detail

Top comments (0)