Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the path from a SpecFlow feature file in a Step Definition

Tags:

c#

specflow

Is it possible to retrieve the path of a SpecFlow feature file during runtime in a Step Definition?

Snippet:

[Given(@"Some given statement")]
public void GivenSomeGivenStatement() {

    var featureFilePath = // retrieve the path of the feature file 
                          // that executes this step.
}

Context:
We do testing on databases and queries. The source data is created in Excel files and .SQL files (for check queries). These source data are large datasets, not feasible to put into the feature files itself or use the SpecFlow.Plus.Excel extension.
To keep the data close to the feature file, we want to have this data in the same folder as the feature file itself. To achieve this, we need the path to this feature file, so we also have the path to the testdata.

like image 844
AutomatedChaos Avatar asked Sep 29 '22 19:09

AutomatedChaos


2 Answers

Here's a suggestion. This is just something I put together quickly so lots of room to improve. It relies on the Feature file name being identical to the title of the feature you provide in the description. It also assumes you have a conventional folder structure for your SpecFlow VS project as there is a lot of string manipulation.

Firstly, the calling code should use the SpecFlow BeforeScenario attribute. Something like this:

public void BeforeScenario()
{      
   //grabs Feature Title from SpecFlow context
   var featureName = FeatureContext.Current.FeatureInfo.Title;
   //Calls method to obtain path of file
   var featureFilePath = GetFeatureFilePath(featureName);
}

The method GetFeatureFilePath will then look like this:

private static string GetFeatureFilePath(string featureName)
{
    string startupPath = Environment.CurrentDirectory; 
    var splitStartupPath = startupPath.Split(new[] {"\\"}, StringSplitOptions.None);

    var featureFolder = splitStartupPath[0] + @"\\" + 
                        splitStartupPath[1] + @"\\" + 
                        splitStartupPath[2] + @"\\" +
                        splitStartupPath[3] + @"\\" +
                        splitStartupPath[4] + @"\\" + 
                        splitStartupPath[5] + @"\\Features\";

    var dir = new DirectoryInfo(featureFolder);

    foreach (var fi in dir.GetFiles())
    {
        if (fi.FullName.Contains(featureName))
            return fi.FullName;
    }

    return "No Feature File Found With Title: " + featureName;
}

It grabs your current directory and splits it to the point where the Features folder should be. It then iterates through each feature file until it finds one that contains your feature title in its path name and returns that as a full path.

I'm not aware of any other way to get this currently.

like image 162
Phonesis Avatar answered Oct 07 '22 19:10

Phonesis


I don't think knowing the path to the feature file will be possible, as the feature file is used to generate a file containing the unit tests and this is compiled and copied to the test run directory.

The simplest thing will be to set the files as part of the solution and then have them copied to the output directory when the project builds.

If you are using NUnit as the test framework then the files should be in the same directory as the tests are executing so you should just be able to load them without specifying any path, or using the Assembly.GetExecutingAssembly().Location to findout where the code is actually executing.

If you are using MSTest then you need to add a [DeploymentItem(FileToDeploy)] attribute to the test to ensure that the file actually gets deployed with the tests when they are run. Unfortunately as Specflow generates the tests it won't add this for you. To solve this you need to create a partial class which has the same name as the class which contains the tests. This class is called the same as the feature with 'Feature' tagged on the end. So if you have this in your feature:

Feature: Do A Thing

The your test class will be called DoAThingFeature

so you need to create a partial class like this:

[DeploymentItem("FileToDeploy.ext")]
public partial class DoAThingFeature
{}

to ensure that MsTest copies the file you need to the correct directory.

Edit

based on your comment you could maybe do something similar to this

add tags to your feature @hasFiles @source:myFile.xlsx

Then you could add this class:

[Binding]
public class DeployFiles
{
     [BeforeScenario("hasFiles")]
     public void CopyFiles()
     {
         ..in here find the current executing directory and search 
         ..the subtree for any files defined in the 
         ..ScenarioInfo.Tags array that start with `source:` and copy 
         ..them to the current executing directory
     }
}

then any scenario tagged with the @hasFiles will deploy any files specified by @source tags to the root directory where the tests are running.

Not pretty and I'm not certain it'll work, but it might.

like image 38
Sam Holder Avatar answered Oct 07 '22 20:10

Sam Holder