【问题标题】:Get the path from a SpecFlow feature file in a Step Definition从步骤定义中的 SpecFlow 功能文件中获取路径
【发布时间】:2017-03-30 16:47:55
【问题描述】:

是否可以在运行时在步骤定义中检索 SpecFlow 功能文件的路径?

片段:

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

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

上下文:
我们对数据库和查询进行测试。源数据在 Excel 文件和 .SQL 文件中创建(用于检查查询)。这些源数据是大型数据集,无法放入特征文件本身或使用 SpecFlow.Plus.Excel 扩展名。
为了使数据靠近特征文件,我们希望将这些数据与特征文件本身放在同一个文件夹中。为此,我们需要此功能文件的路径,因此我们还有测试数据的路径。

【问题讨论】:

  • 似乎是XY problem 的情况。任何情况下的机会 - 你真正想要实现的目标是什么?
  • 对我来说似乎是一种测试气味。为什么你需要路径,也许你需要解决的实际问题有更好的解决方案?
  • @decPL 添加了上下文,我希望清楚我们想要实现的目标。
  • 你是使用 NUnit 还是其他一些框架作为测试框架?
  • @SamHolder 不幸的是没有 NUnit。我们使用 MsTest,我使用 Resharper 从 VS 运行和调试我的测试。

标签: c# specflow


【解决方案1】:

这里有一个建议。这只是我快速组合起来的东西,所以还有很大的改进空间。它依赖于功能文件名与您在描述中提供的功能的标题相同。它还假设您的 SpecFlow VS 项目有一个传统的文件夹结构,因为有很多字符串操作。

首先,调用代码应该使用 SpecFlow BeforeScenario 属性。像这样的:

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);
}

GetFeatureFilePath 方法将如下所示:

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;
}

它会抓取您当前的目录并将其拆分到 Features 文件夹应位于的位置。然后它遍历每个功能文件,直到找到一个在其路径名中包含您的功能标题的文件,并将其作为完整路径返回。

我目前不知道有任何其他方法可以得到这个。

【讨论】:

    【解决方案2】:

    我认为知道功能文件的路径是不可能的,因为功能文件用于生成包含单元测试的文件,并且该文件被编译并复制到测试运行目录。

    最简单的方法是将文件设置为解决方案的一部分,然后在项目构建时将它们复制到输出目录。

    如果您使用 NUnit 作为测试框架,那么文件应该与正在执行的测试位于同一目录中,因此您应该能够在不指定任何路径的情况下加载它们,或者使用 Assembly.GetExecutingAssembly().Location 找出代码实际上正在执行。

    如果您使用的是 MSTest,那么您需要将 [DeploymentItem(FileToDeploy)] 属性添加到测试中,以确保文件在运行时与测试一起实际部署。不幸的是,当 Specflow 生成测试时,它不会为您添加它。为了解决这个问题,您需要创建一个与包含测试的类同名的部分类。此类称为与末尾标记“Feature”的特征相同。因此,如果您的功能中有此功能:

    Feature: Do A Thing
    

    你的测试类将被称为DoAThingFeature

    所以你需要像这样创建一个部分类:

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

    确保 MsTest 将您需要的文件复制到正确的目录。

    编辑

    根据您的评论,您可能会做类似的事情

    为您的功能添加标签@hasFiles @source:myFile.xlsx

    然后你可以添加这个类:

    [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
         }
    }
    

    那么任何带有@hasFiles 标记的场景都会将@source 标记指定的任何文件部署到运行测试的根目录。

    不漂亮,我不确定它是否会起作用,但它可能会。

    【讨论】:

    • 将数据放入我的输出目录不是问题。默认情况下,我们在包含部署文件夹的解决方案下有一个 runsettings.testsettings 文件。想法是向功能文件所在的文件夹添加部署映射。
    • 那么你可以从当前目录加载文件,不是吗?还是我错过了什么?你有什么不想这样做的理由吗?
    • 通过 testsettings 部署,文件夹结构也被复制。所以当一个人在特征文件中创建一个新步骤时,他/她必须知道文件夹树。我想将其解耦并使其依赖于上下文。就像Specflow.Plus.Excel 包中的@source:myExcelFile.xlsx 标记一样。
    【解决方案3】:

    也许这可以帮助你,在 .net 4.5 中你可以获得调用者的路径,看看这个线程source path in .net 4.5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      • 2018-08-15
      • 1970-01-01
      • 2017-03-27
      • 1970-01-01
      • 1970-01-01
      • 2011-07-16
      相关资源
      最近更新 更多