Search code examples
c#testingacceptance-testing

How to write out acceptance based tests (from a code point of view)


I have been studying acceptance based tests and they look quite nice as they fit more naturally with feature based development.

The problem is that I do not know how to lay them out in code. I would like to try and avoid pulling in another framework to handle this so I am just looking for a simple way to get these tests up and running.

I am open to any changes needed to the code structure. I am also using specs to build up complex acceptance criteria.

Sample of what I am trying to do:

public class When_a_get_request_is_created
{
    private readonly IHttpRequest _request;

    public When_a_get_request_is_created()
    {
        _request = new HttpRequest();
    }

    // How to call this?
    public void Given_the_method_assigned_is_get()
    {
        _request = _request.AsGet();
    }

    // What about this?
    public void Given_the_method_assigned_is_not_get()
    {
        _request = _request.AsPost();
    }

    // It would be great to test different assumptions.
    public void Assuming_default_headers_have_been_added()
    {
        _request = _request.WithDefaultHeaders();
    }

    [Fact]
    public void It_Should_Satisfy_RequestIsGetSpec()
    {
        Assert.True(new RequestUsesGetMethodSpec().IsSatisfiedBy(_request));
    }
}

I may be completely off the mark here but essentially I would like to be able to run tests with different assumptions and givens. I don't mind if I have to make more classes or minor duplication as long as I can point someone to the test to validate a given criteria.


Solution

  • I would strongly recommend using an ATDD framework like SpecFlow or even MSpec for creating tests of this nature. Implementing SpecFlow is then a case of writing your specification using domain specific language, in collaboration with domain expert(s) if that's approriate, and then satisfying the scenario steps defined in the feature through code. It's difficult to pad out the code aspect without understanding more about your exact requirements, but a sample feature might look something like this:

    Feature: HTTP Requests
        In order to validate that HTTP requests use the correct methods
        As a client application
        I want specific requests to use specific methods
    
    Scenario Outline: Making HTTP Requests
        Given I am making a request
        When the method assigned is <Method>
        And the <Header> header is sent
        Then it should satisfy the requirement for a <Method> request
    
    Examples:
    | Method | Header   |
    | Get    | Header 1 |
    | Get    | Header 2 |
    | Get    | Header 3 |
    | Post   | Header 1 |
    

    Then in your steps that are bound to the feature you can write the code that satisfies the specification steps. Here's one example:

    [Binding]
    public class HttpRequestSteps
    {
        [When(@"the method assigned is (.*)")]
        public void WhenTheMethodAssignedIs(string method)
        {
            // not sure what this should be returning, but you can store it in ScenarioContext and retrieve it in a later step binding by casting back based on key
            // e.g. var request = (HttpRequest)ScenarioContext.Current["Request"]
            ScenarioContent.Current["Request"] = _request.AsGet();
        }
    }