In my latest project we needed to keep SpecFlow scenarios in the project and included in the reports but excluded from the execution. This could be due to the fact that the feature file is still in draft stage or it has been superseded. Accomplishing this requires a bit of msbuild magic.

I have prepared example for the xUnit runner that can be found here. In the listing below one of the scenarios has been tagged @Superseded and will be ignored during execution.

Feature: Calculations
	In order to perform basic calculations
    As a user of this program
    I want to be told results of calculations


Scenario Outline: Perform basic operations
	Given I have provided <First Number> and a <Second Number>
	When I perform operation '<Operation>'
	Then the result should be <Result Number>

Examples: 
    | Operation | First Number | Second Number | Result Number |
    | Add       | 5            | 7             | 12            |
    | Add       | 3            | 4             | 7             |
    | Sub       | 4            | 1             | 3             |
    | Sub       | 987          | 342           | 645           |
    | Multiply  | 7            | 3             | 21            |
    | Multiply  | 14           | 12            | 168           |
    | Divide    | 121          | 11            | 11            |
    | Divide    | 63           | 7             | 9             |
    
@Superseded
Scenario: Perform calculations
    Given An outdated test
    When I perform outdated operation
    Then Some Result will be produced    

Another example would be a draft of the feature

Feature: NewFunctions
	
@Draft
Scenario: Draft scenario
	Given I have a number 90	
	When I take sinus of the number
	Then I will receive 1

To get this working you need to add FeatureGeneration.targets file to your project

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTarget="GeneratePatchedFeatureFiles" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\packages\SpecFlow.2.3.0\tools\TechTalk.SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.3.0\tools\TechTalk.SpecFlow.targets')" />
     
  <Target Name="GeneratePatchedFeatureFiles" DependsOnTargets="UpdateFeatureFilesInProject">
    <UpdateFeatureFile FeatureFiles="@(SpecFlowFeatureFiles->'%(RelativeDir)\%(Filename).feature.cs')" SkippedTags ="Superseded|Manual|Draft"/>
  </Target>
  
  <UsingTask TaskName="UpdateFeatureFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <FeatureFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
      <SkippedTags ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <!--
      Go through generated feature.cs files and patch if not already patched
      Patching will skip all scenarios marked with predefined tags
      -->
      <Reference Include="System.Core" />
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Text.RegularExpressions" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[      
        foreach(var featureFile in FeatureFiles) {
            
            var automaticallyPatchedFlag = "//Automatically patched";
            var input = File.ReadAllText(featureFile.ToString());
            if(input.EndsWith(automaticallyPatchedFlag)) continue;
            
            Log.LogMessage("Patching feature file " + featureFile.ToString());
            input = Regex.Replace(input, @"\[Xunit.(FactAttribute|TheoryAttribute)\(([^)]*)""\)\](.[^\{]+\[Xunit.TraitAttribute\(""Category"", ""("
            + SkippedTags + 
            @")""\)\])",
              "[Xunit.$1(Skip=\"Test not run as it was tagged: $4\", $2\")]$3", RegexOptions.Multiline | RegexOptions.IgnoreCase);
            input += automaticallyPatchedFlag;
            File.WriteAllText(featureFile.ToString(), input);
        }
          ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

Then add following lines to your .csproj file

  <Import Project="FeatureGeneration.targets" />
  <Target Name="BeforeBuild" DependsOnTargets="GeneratePatchedFeatureFiles" />

Doing this will automatically patch *.feature.cs on build and scenarios marked with tags specified in FeatureGeneration.targets will not be executed. In one of my future posts I will provide example of the same functionality for the NUnit runner.