SpecFlow in een DevOps project

SpecFlow

Ivo Breukers, oktober 2021.


Deze blogpost heeft als hoofdvraag: "Hoe kan je SpecFlow inzetten in een kortlopend DevOps project?"

Het doel van dit onderzoek is uitsluitsel geven of SpecFlow gebruikt zal worden in het beroepsproduct van de minor DevOps. De deelvragen beantwoorden de hoofdvraag van dit onderzoek. De deelvragen zijn:

    1. Wat is SpecFlow?
    1. Hoe past SpecFlow binnen BDD?
    1. Hoe werkt SpecFlow in de praktijk?

Ik onderzoek n.a.v. de eerste twee deelvragen middels literature study uit de ICT Research Methods van Bonestroo et al. (2018), de gekozen technologie respectievelijk hoe deze binnen BDD past. In de laatste deelvraag toets ik de technologie in de praktijk, middels de onderzoeksmethode prototype. De drie hierop volgende hoofdstukken beantwoorden de deelvragen in de volgorde zoals hierboven staat. Tot slot beantwoordt de conclusie de hoofdvraag van dit blog.

1. SpecFlow

SpecFlow is een opensource framework dat een testautomatiseringsoplossing biedt voor .NET, gebaseerd op het BDD-paradigma. SpecFlow definieert, beheert en voert voor mensen leesbare acceptatietests uit in .NET-projecten (SpecFlow, z.d.-a). Eenvoudig gezegd is SpecFlow Cucumber voor .NET (CODEDEC, z.d.).

SpecFlow biedt een mechanisme om specificatie om te zetten in uitvoerbare code. Dit kan je vervolgens gebruiken om geautomatiseerde tests te maken, die je kan uitvoeren met applicatie code om te controleren of deze het gedrag vertoont zoals beschreven in de specificaties (Dijkstra, 2020).

SpecFlow tests schrijf je met behulp van Gherkin, waarmee je test cases kunt schrijven in natuurlijke talen. SpecFlow gebruikt de officiële Gherkin parser, die meer dan 70 talen ondersteunt. Met SpecFlow koppel je deze tests met zogenaamde bindings aan de applicatiecode, waarna je deze tests kunt uitvoeren met behulp van een test framework naar keuze (SpecFlow, z.d.-a). SpecFlow zet de specificaties die zijn geschreven in de Gherkin Given / When / Then syntax, als scenario's in feature files om in uitvoerbare code, ook wel 'step definitions' genoemd (Dijkstra, 2020).

Nadat deze stappen zijn omgezet in uitvoerbare code, houdt de verantwoordelijkheid van SpecFlow op. Om de testautomatisering verder te implementeren, zodat deze daadwerkelijk communiceert met de te testen applicatie, moet je een andere tool toevoegen aan de testautomatseringsoplossing. Enkele tools die vaak in combinatie met SpecFlow worden gebruikt om een testautomatiserings framework te vormen zijn NUnit, MSTest en xUnit (Dijkstra, 2020).

Het SpecFlow ecosysteem

Dijkstra (2020) schrijft dat naast het kernproject ook enkele tools beschikbaar zijn van SpecFlow, die gezamenlijk bekend staan als SpecFlow+. Onderdeel van deze collectie zijn:

  • SpecFlow+ Runner, een test runner specifiek geschreven voor SpecFlow
  • SpecFlow+ Excel, hiermee kan de kracht van Microsoft Excel gebruikt worden om functies en scenario's te maken.
  • SpecFlow+ LivingDoc, voor het maken van documentatie van feature files

2. SpecFlow in BDD

De YouTube video 'Getting Started with SpecFlow' (2020) legt uit dat behavior-driven development (BDD) bestaat uit vier fasen:

  1. Illustration/discovery fase
  2. Formulation fase
  3. Automation fase
  4. Validation fase

Dijkstra (2020) schrijft dat een van de belangrijkste doelen van BDD is om een gedeeld begrip te creëren van hoe een applicatie zich zou moeten gedragen, door discussie te vergemakkelijken en met concrete voorbeelden te komen. Dit wordt uitgedrukt in een Domain Specific Language (DSL), met behulp van de Given / When / Then syntax, dat bekend staat als Gherkin. Het andere onderdeel van BDD houdt zich bezig met het omzetten van deze specificaties in geautomatiseerde acceptatietests, en dat is waar SpecFlow in het spel komt.

SpecFlow kan je (normaliter) alleen gebruiken in de automation fase, zoals onderstaand figuur toont. SpecFlow is een tool die BDD ondersteunt, dus door alleen SpecFlow te gebruiken ben je niet automatisch BDD aan het toepassen. Het is mogelijk BDD te doen zonder SpecFlow en het is ook mogelijk SpecFlow te gebruiken zonder BDD (SpecFlow, 2020).

SpecFlow binnen BDD Bron: SpecFlow (2020)

3. SpecFlow in de praktijk

Stap nul, alvorens we beginnen met de realisatie van het prototype, is het installeren van een SpecFlow plugin voor de IDE. SpecFlow biedt een extensie voor Visual Studio en een plugin voor JetBrains Rider. Deze zijn eenvoudig te installeren binnen de gekozen IDE.

Dit prototype gebruikt JetBrains Rider, in voorbeelden zal deze IDE ook zichtbaar zijn. De stappen voor Visual Studio zullen vrij hetzelfde zijn, het is dus mogelijk om de stappen binnen Visual Studio te volgen.

De eerste stap is het aanmaken van een solution met een "Class library", beide genaamd SpecFlowCalculator. Dit prototype gebruikt SDK: 5.0, taal: C# en framework: net5.0, zoals in het onderstaand figuur zichtbaar is.

Create SpecFlowCalculator solution and Class library

Na het aanmaken van de solution en het project hernoemen we Class1.cs naar Calculator.cs en vervangen zijn content met de volgende code:

using System;

namespace SpecFlowCalculator
{
    public class Calculator
    {
        public int FirstNumber { get; set; }
        public int SecondNumber { get; set; }

        public int Add()
        {
            throw new NotImplementedException();
        }
    }
}

Vervolgens maken we een nieuw project aan binnen de solution. Dit project is van het type SpecFlow Project, heet SpecFlowCalculator.Specs , maakt gebruik van het net5.0 framework en gebruikt xUnit als test framework, zie de onderstaande afbeelding voor de uitwerking.

Create SpecFlow Project

Na het aanmaken van het SpecFlow Project voegen we de class library toe als dependency, binnen JetBrains Rider kan het op de onderstaande manier.

Add dependency

Na het toevoegen van de dependency maken we een feature file aan in de map Features, dit bestand noemen we Calculator.feature.

Add feature file

Deze feature file vullen we met een scenario in Gherkin, dit scenario neemt twee getallen, geeft aan dat ze bij elkaar opgeteld moet worden en geeft een verwacht resultaat.

Feature: Calculator
Simple calculator for adding **two** numbers

@mytag
Scenario: Add two numbers
  Given the first number is 50
  And the second number is 70
  When the two numbers are added
  Then the result should be 120

Na het aanmaken van de feature file en het schrijven van het eerste scenario is het tijd om de step definitions aan te maken. We plaatsen dit bestand in de Steps folder, noemen het CalculatorStepDefinitions.cs en vullen het met de step definitions, gebaseerd op de bovenstaande Gherkin code.

Add step definition

Binnen deze klasse maken we een instantie van Calculator en een variabele _result aan. Tot slot implementeren we de step definitions, het resultaat is:

using TechTalk.SpecFlow;
using Xunit;

namespace SpecFlowCalculator.Specs.Steps
{
    [Binding]
    public sealed class CalculatorStepDefinitions
    {
        private readonly ScenarioContext _scenarioContext;
        private readonly Calculator _calculator = new();
        private int _result;

        public CalculatorStepDefinitions(ScenarioContext scenarioContext)
        {
            _scenarioContext = scenarioContext;
        }

        [Given("the first number is (.*)")]
        public void GivenTheFirstNumberIs(int number)
        {
            _calculator.FirstNumber = number;
        }

        [Given("the second number is (.*)")]
        public void GivenTheSecondNumberIs(int number)
        {
            _calculator.SecondNumber = number;
        }

        [When("the two numbers are added")]
        public void WhenTheTwoNumbersAreAdded()
        {
            _result = _calculator.Add();
        }

        [Then("the result should be (.*)")]
        public void ThenTheResultShouldBe(int result)
        {
            Assert.Equal(result, _result);
        }
    }
}

Na het implementeren van de step definitions kunnen we de tests draaien. Het resultaat is falende tests, met als melding dat er een NotImplementedException optreedt, dit komt omdat de Add methode van Calculator nog niet geïmplementeerd is.

Test result: NotImplementedException

Nu is het tijd om de Add methode van Calculator te implementeren op de volgende manier:

public int Add()
{
    return FirstNumber + SecondNumber;
}

Na deze implementatie runnen we de tests opnieuw, met als resultaat dat alle steps slagen.

Test result: Success

Bij de realisatie is gebruik gemaakt van: SpecFlow (z.d.-b).

Living Documentation

Door gebruik te maken van de SpecFlow+ LivingDoc tool kan er living documentation gegenereerd van alle test resultaten, zodat deze gemakkelijk gedeeld kunnen worden met het team.

De LivingDoc CLI tool kan je installeren met het volgende commando:

dotnet tool install --global SpecFlow.Plus.LivingDoc.CLI

Na de installatie moet je naar de output directory van het SpecFlow project navigeren. Hier kan je komen door het volgende commando uit te voeren, vanuit de root van deze repository.:

cd SpecFlowCalculator/SpecFlowCalculator.Specs/bin/Debug/net5.0/

Binnen deze map kan je living documentation genereren met het onderstaande commando:

livingdoc test-assembly SpecFlowCalculator.Specs.dll -t TestExecution.json

Dit genereert een HTML bestand met alle scenario's en resultaten op de volgende locatie:

SpecFlowCalculator/SpecFlowCalculator.Specs/bin/Debug/net5.0/LivingDoc.html

Conclusie

SpecFlow is een opensource framework dat je kan gebruiken om voor mensen leesbare acceptatietests te definiëren, beheren en automatisch uit te voeren in .NET-projecten. SpecFlow zet specificaties, scenario's in feature files, die zijn geschreven in Gherkin om in uitvoerbare code, ook wel step definitions genoemd.

SpecFlow is een tool die BDD ondersteunt, op zichzelf is het geen BDD. Wanneer je SpecFlow binnen BDD gebruikt komt het aanbodt in de automation fase, de derde van de vier fasen binnen BDD.

Het gebruik van SpecFlow is in de praktijk prettig, dit komt doordat de documentatie voor het framework duidelijk en uitgebreid is. Ook zijn er verschillende guides en voorbeeldprojecten te vinden. De extensie die SpecFlow biedt draagt eraan bij dat dat SpecFlow prettig in gebruik is. SpecFlow zelf biedt ook nog aanvullende SpecFlow+ tools die het werken met SpecFlow bevorderen.

De eindconclusie is dat SpecFlow een ideale tool is voor een DevOps project dat gebruik maakt van services die je realiseert in .NET en volgens behavior-driven development.

Bronnen

Last change: 2025-01-13