Skip to content

GivePenny/GherkinSpec.SpecFlowBindingsExample

Repository files navigation

GherkinSpec.SpecFlowBindingsExample

Overview

The simplest sensible example of a test written in Gherkin using the GherkinSpec test adapter for test discovery and execution, and SpecFlow for IDE integration. See the GherkinSpec repository for more information.

In the absence of GherkinSpec specific IDE integration (see GherkinSpec Issue 13), this example describes configuring GherkinSpec to use SpecFlow binding types when finding step bindings. As the SpecFlow IDE integrations use these binding types to support features such as step-to-definition navigation, this allows us to lean on the SpecFlow IDE integrations while still relying on GherkinSpec for test discovery and execution.

Please note that this example functions as described here at the time of writing, and that GherkinSpec can not guarantee this usage with SpecFlow for IDE integration. Future changes to SpecFlow or the SpecFlow IDE integrations may result in this example no longer achieving the results described here.

Configuration

This example uses MSTest, however similar results may be achieved using the SpecFlow.xUnit or SpecFlow.NUnit packages.

The following packages are installed in GherkinSpec.SpecFlowBindingsExample.Tests.csproj.

<ItemGroup>
    <PackageReference Include="GivePenny.GherkinSpec.TestAdapter" Version="3.0.6" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
    <PackageReference Include="SpecFlow.MSTest" Version="3.9.74" />
</ItemGroup>

Since SpecFlow.MSTest (or SpecFlow.xUnit / SpecFlow.NUnit) results in *.feature.cs files being code-generated, the following sections are also present in the csproj:

<ItemGroup>
    <Compile Remove="Features/**/*.feature.cs" />
</ItemGroup>

<Target Name="DeleteSpecFlowCodeGeneratedFiles" AfterTargets="Build">
    <ItemGroup>
        <FilesToDelete Include="Features/**/*.feature.cs" />
    </ItemGroup>
    <Message Text="Deleting @(FilesToDelete)" />
    <Delete Files="@(FilesToDelete)" />
</Target>

These sections result in the .feature.cs files being deleted after build, preventing duplicate tests from appearing (those in the SpecFlow generated .feature.cs files as well as the same discovered from the .feature files by GherkinSpec).

It may also be preferable to use the following snippet (or similar) from .gitignore:

# Files generated by SpecFlow
**/*.feature.cs

To indicate to GherkinSpec that the SpecFlow binding attributes should be used, the following is added in AssemblyAttributes.cs:

[assembly: BindingTypes(
    typeof(BindingAttribute),
    typeof(GivenAttribute),
    typeof(WhenAttribute),
    typeof(ThenAttribute),
    typeof(SpecFlowStepAttributeMatchExpressionSelector))]

As can be seen, an additional type is provided SpecFlowStepAttributeMatchExpressionSelector, which can be found in SpecFlowStepAttributeMatchExpressionSelector.cs. This class tells GherkinSpec how to get to a step match expression from e.g. a [Given(...)] attribute.

IDE Integration Features

The majority of the IDE integration features described in the SpecFlow documentation for Rider and Visual Studio work with the configuration in this example.

This includes step-to-binding navigation, step generation, syntax highlighting and auto-completion across both IDEs, as well as step renaming in Visual Studio.

A notable feature that does not work in either IDE with the configuration in this example is the ability to run / debug scenarios from within feature files.

Gotchas

It may be noted that BindingTypes does not allow for custom types to be used in place of BeforeRunAttribute and AfterRunAttribute. This decision was made due to the fact that the methods decorated with these attributes are required to accept a single parameter of type TestRunContext. Since these methods are more tightly coupled to GherkinSpec specifics (versus step bindings whose parameters are defined in the match expression), it didn't seem to make sense to support selection of these methods using different attribute types.

That being said, when using the [BeforeRun] and [AfterRun] hooks (for example as shown in GherkinSpec.ComplexExample.Tests/Configuration/Dependencies.cs) in combination with a custom steps class binding attribute type (for example SpecFlow's BindingAttribute as shown in this example), then [BeforeRun] and [AfterRun] hook methods should be contained in a class decorated with the custom steps class binding attribute, e.g.:

[assembly: BindingTypes(
    typeof(BindingAttribute))]

namespace GherkinSpec.ComplexExample.Tests.Configuration
{
    // We can't use [Steps] here
    [Binding]
    public static class Dependencies
    {
        [BeforeRun]
        public static void Setup(TestRunContext testRunContext)
        {
            // ...
        }

        [AfterRun]
        public static void Teardown(TestRunContext testRunContext)
        {
            // ...
        }
    }
}

About

Example demonstrating Gherkin tests using GherkinSpec with SpecFlow binding types for IDE integration.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published