Generate Tests From MsBuild

SpecFlow's generateall function can also be used with MSBuild, allowing you to re-generate the class files before compiling the solution. This can be particularly useful if feature files are regularly modified outside of Visual Studio. More information on the generateall function can be found here.

To be able to use this function, you need to update your project file. There are also a number of other options you can configure.

Edit Your Project File

In order to use the generateall function with MSBuild, you need to update your project file. Add the following lines to the end of the Visual Studio project file of the project containing the feature files (e.g. with notepad):

<PropertyGroup>
    <SpecFlowTasksPath>..\packages\SpecFlow.2.2.0\tools\specflow.exe</SpecFlowTasksPath>
</PropertyGroup>
<Import Project="..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.tasks"  Condition="Exists('..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.tasks')" />
<Import Project="..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.targets')" />

Example:

(Note the example assumes the project is referencing the SpecFlow 2.2.0 NuGet package. The user should replace "..\packages\SpecFlow.2.2.0\tools" with a path relative form the project file that points to the version specific SpecFlow tools folder used by the project. It is important that the element comes before the elements.)

...
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
    <SpecFlowTasksPath>..\packages\SpecFlow.2.2.0\tools\specflow.exe</SpecFlowTasksPath>
</PropertyGroup>
<Import Project="..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.tasks"  Condition="Exists('..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.tasks')" />
<Import Project="..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.targets')" />
...
</Project>

The SpecFlow NuGet package contains all files required by MsBuild to generate the tests in the tools folder. In order to be able to build your application in any environment, we recommend storing the contents of this directory together with your sources and to use a relative path.

Change the Feature File Settings (optional)

When adding a feature file, Visual Studio automatically enters "SpecFlowSingleFileGenerator" as the Custom Tool in the file's properties. This ensures that the class files are re-generated whenever the feature file is saved. You can remove the custom tool to prevent this from occurring, as any class files that are not up-to-date will be generated during the build process anyway:

If you remove the code generator, or are also adding, renaming or deleting feature files outside of Visual Studio, you can include these files in your project dynamically. To do so, add the following lines to your project file (.csproj) in a text editor:

<Target Name="AfterUpdateFeatureFilesInProject">
    <!-- include any files that specflow generated into the compilation of the project -->
    <ItemGroup>
        <Compile Include="@(SpecFlowGeneratedFiles)" />
    </ItemGroup>
</Target>

Define Additional Options (optional)

The TechTalk.SpecFlow.targets file defines a number of default options in the following section:

<PropertyGroup>
    <ShowTrace Condition="'$(ShowTrace)'==''">false</ShowTrace>
    <SpecFlowTasksPath>..\packages\SpecFlow.2.2.0\tools\specflow.exe</SpecFlowTasksPath>
    <OverwriteReadOnlyFiles Condition="'$(OverwriteReadOnlyFiles)'==''">false</OverwriteReadOnlyFiles>
    <ForceGeneration Condition="'$(ForceGeneration)'==''">false</ForceGeneration>
    <VerboseOutput Condition="'$(VerboseOutput)'==''">false</VerboseOutput>
</PropertyGroup>
  • ShowTrace: Set this to true to output trace information.
  • SpecFlowTasksPath: Path to specflow.exe.
  • OverwriteReadOnlyFiles: Set this to true to overwrite any read-only files in the target directory. This can be useful if your feature files are read-only and part of your repository.
  • ForceGeneration: Set this to true to forces the code-behind files to be regenerated, even if the content of the feature has not changed.
  • VerboseOutput: Set to true to enable verbose output for troubleshooting.

To change these options, add the corresponding element to your project file before the <Import> element you added earlier.

Example:

<PropertyGroup>
  <ShowTrace>true</ShowTrace>
  <SpecFlowTasksPath>..\packages\SpecFlow.2.2.0\tools\specflow.exe</SpecFlowTasksPath>
  <VerboseOutput>true</VerboseOutput>
</PropertyGroup>
...
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.tasks"  Condition="Exists('..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.tasks')" />
<Import Project="..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.2.0\tools\TechTalk.SpecFlow.targets')" />
...
</Project>

You can find an example here (project Bowling.SpecFlow)

Process the Generated Files (optional)

You can further process the generated files. The TechTalk.SpecFlow.targets file defines two targets (BeforeUpdateFeatureFilesInProject and AfterUpdateFeatureFilesInProject) that can be overridden. Furthermore it outputs the list of generated files for the MsBuild item @(SpecFlowGeneratedFiles).

The following example shows an overridden AfterUpdateFeatureFilesInProject target that moves the generated files to a separate folder:

<Target Name="AfterUpdateFeatureFilesInProject">
  <Move 
    SourceFiles="@(SpecFlowGeneratedFiles)" 
    DestinationFolder="MyGeneratedFiles" 
    OverwriteReadOnlyFiles="true" />
</Target>