9

首先,我是 SpecFlow 的新手。

我有一个功能文件,我有/想要使用 MSTest 自动运行它作为涉及完全设置的服务器、数据访问的功能测试......为此,我必须使用 SpecFlow 的“给定”中的数据配置服务器块并在之后启动它。我还必须将一些文件复制到测试的输出目录。

在非 SpecFlow 功能测试中,我使用 ClassInitialize 属性从 TestContext 获取 TestDeploymentDir;像这样的东西:

[ClassInitialize]
public static void ClassSetup(TestContext context)
{
  TargetDataDeploymentRoot = context.TestDeploymentDir;
}

现在有了 SpecFlow,我不能再使用这个属性了,因为它是由 SpecFlow 本身使用的。确实存在一些新属性,例如BeforeFeature,它的作用类似,但它没有将 TestContext 作为参数传递。

在真正启动我的功能测试服务器之前,我只需要访问 TestContext 的 TestDeploymentDir 以便在那里复制一些文件 - 没有 SpecFlow 很容易做到,但使用 SpecFlow 几乎不可能。

如何处理这个问题?

有可能吗?

非常感谢您的建议!

罗伯特


环境:

  • 视觉工作室 2012
  • 规范流 1.9.0.77
4

4 回答 4

5

从 SpecFlow 2.2.1 开始,TestContext 可通过上下文注入获得。(https://github.com/techtalk/SpecFlow/pull/882

您可以直接从容器中获取它:

ScenarioContext.Current.ScenarioContainer.Resolve<Microsoft.VisualStudio.TestTools.UnitTesting.TestContext>()

或通过上下文注入:

public class MyStepDefs
{
    private readonly TestContext _testContext;
    public MyStepDefs(TestContext testContext) // use it as ctor parameter
    { 
        _testContext = testContext;
    }

    [BeforeScenario()]
    public void BeforeScenario()
    {
        //now you can access the TestContext
    } 
}
于 2017-09-14T10:55:29.443 回答
3

为了能够访问 TestContext 中的值,您必须为您在其中添加 .

using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechTalk.SpecFlow;

/// <summary>
/// Partial class for TestContext support.
/// </summary>
public partial class DistributionFeature
{
    /// <summary>
    /// Test execution context.
    /// </summary>
    private TestContext testContext;

    /// <summary>
    /// Gets or sets test execution context.
    /// </summary>
    public TestContext TestContext
    {
        get
        {
            return this.testContext;
        }

        set
        {
            this.testContext = value;

            //see https://github.com/techtalk/SpecFlow/issues/96
            this.TestInitialize();
            FeatureContext.Current["TestContext"] = value;
        }
    }
}

然后,您可以使用以下步骤访问部署目录

var testContext = (TestContext)FeatureContext.Current["TestContext"];
var deploymentDir = testContext.TestDeploymentDir;

如果您有太多场景,那么您可能必须使用 T4 自动创建此类文件。

于 2013-06-03T06:24:14.563 回答
3

您可以创建插件并自定义 IUnitTestGeneratorProvider 实现。下面应该将这一行添加到 MSTest 的类初始化中。

// It's very important this is named Generator.SpecflowPlugin.
namespace MyGenerator.Generator.SpecflowPlugin
{
    public class MyGeneratorProvider : MsTest2010GeneratorProvider
    {
        public MyGeneratorProvider(CodeDomHelper codeDomHelper)
            : base(codeDomHelper)
        {
        }

         public override void SetTestClassInitializeMethod(TestClassGenerationContext generationContext)
        {

            base.SetTestClassInitializeMethod(generationContext);

generationContext.TestClassInitializeMethod.Statements.Add(new CodeSnippetStatement(
                                                                      @"TargetDataDeploymentRoot = context.TestDeploymentDir;"));

        }

     }


[assembly: GeneratorPlugin(typeof(MyGeneratorPlugin))]

    public class MyGeneratorPlugin : IGeneratorPlugin
    {
        public void RegisterDependencies(ObjectContainer container)
        {
        }

        public void RegisterCustomizations(ObjectContainer container, SpecFlowProjectConfiguration generatorConfiguration)
        {
            container.RegisterTypeAs<MyGeneratorProvider, IUnitTestGeneratorProvider>();
        }

        public void RegisterConfigurationDefaults(SpecFlowProjectConfiguration specFlowConfiguration)
        {
        }
    }

}

并在 App.config 文件中引用它:

<specFlow>
    <plugins>
      <add name="MyGenerator" type="Generator"/>
    </plugins>
 </specFlow>

下次您重新保存 .feature 文件时,ClassInitialize 中生成的代码应该设置 TargetDataDeploymentDirectory。

我不得不做类似的事情。这是我的工作代码https://github.com/marksl/Specflow-MsTest和博客文章 http://codealoc.wordpress.com/2013/09/30/bdding-with-specflow/

于 2014-02-10T16:46:55.383 回答
-1

有一个 FeatureContext 以及更常用的 ScenarioContext。当然区别在于 FeatureContext 存在于完整功能的执行期间,而 ScenarioContext 仅存在于场景期间。

例如:

添加到上下文:

ScenarioContext.Current.Add("ObjectName", myObject);

得到:

var myObject = ScenarioContext.Current.Get<object>("ObjectName");

你可以在这里阅读更多关于它的信息。

于 2012-09-02T21:43:28.563 回答