如何将Specflow步骤标记为“已过时”以支持渐进式,向后兼容的重构

时间:2017-07-10 19:42:15

标签: c# refactoring bdd specflow

由于业务术语中的某些术语更改,我目前正在重构中型应用程序。我们有大约121个需要更改的SpecFlow功能文件。

我喜欢你如何在C#中“弃用”API,首先是警告:

[Obsolete("Use MyClass.NewMethod instead")]
public void OldMethod() { }

然后编译错误:

[Obsolete("Use MyClass.NewMethod instead", true)]
public void OldMethod() { }

为SpecFlow步骤提供此类功能会很好:

[When("I old foo", Obsolete = true)]
[When("I new foo")]
public void WhenIFoo() { }

有没有办法将SpecFlow中的步骤标记为过时,以便其他开发人员知道需要在其Feature文件中更改的步骤,但不能阻止他们编写和运行测试?并且作为补充奖金,有没有办法可选地导致编译器或测试运行失败?

3 个答案:

答案 0 :(得分:3)

version v2.4开始,SpecFlow在步骤绑定中遵循[Obsolete]属性。

对于您的示例,您可能会这样使用它:

[When("I old foo")]
[Obsolete("you should use WhenIFoo instead")]
public void WhenIOldFoo() { }

[When("I new foo")]
public void WhenIFoo() { }

使用这些步骤的默认行为是发出警告。利用SpecFlow的obsoleteBehavior配置中的<runtime>属性,可以更改它,尤其是。测试执行失败:

<specFlow>
    ...
    <runtime obsoleteBehavior="Error" />
</specFlow>

与此同时,Wiki-page for the Configuration已更新为记录该功能。

答案 1 :(得分:0)

我还没有直接在SpecFlow中找到解决方案,但我使用ScenarioContext的扩展方法做了Get It To Work™:

注意:这使用了MsTest,但我确信其他单元测试框架有一种方法可以将测试标记为&#34; pending&#34;或者没有结果的消息。

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

namespace MyTestProject
{
    public static class ScenarioContextExtensions
    {
        public static void MarkStepObsolete(this ScenarioContext scenario, string newStep, params object[] newStepFormatArgs)
        {
            var message = string.Format(@"This step is obsolete. Use '" + scenario.CurrentScenarioBlock + " " + newStep + "' instead.", newStepFormatArgs);

            Assert.Inconclusive(message);
        }
    }
}

现在,在您的步骤定义中,您将完成旧步骤&#34;过时&#34;它们显示为不确定的测试,为您提供更换步骤的提示:

[When(@"I click the ""(.*)"" anchor")]
public void WhenIClickTheAnchor(string anchorText)
{
    ScenarioContext.Current.MarkStepObsolete(@"I click the ""{0}"" link", anchorText);
}

[When(@"I click the ""(.*)"" link")]
public void WhenIClickTheLink(string linkText)
{
    // ...
}

它出现在Test Explorer面板中:

  

Assert.Inconclusive失败 - 此步骤已过时。使用&#39;当我点击&#34; Home&#34;链接&#39;代替。

这至少告诉其他开发人员在我改变现有场景中的术语时如何修复他们正在编写的新测试。

答案 2 :(得分:0)

有一种方法可以使用步骤Scopes执行此操作:

[When("I old foo", Scope(Tag = "Obsolete"))]
[When("I new foo")]
public void WhenIFoo() { }

确保标记(它的正则表达式)是唯一的,因为它的想法是不匹配标记的任何方案。

将会发生的情况是,您的测试将被标记为Not Run,更重要的是,使用此步骤的方案将获得粉红色的步骤,因此它将是可见的编译时间。

如果你想将整个班级标记为过时,那么只需按如下方式标记该类:

[Binding, Scope(Tag = "Obsolete")]
public class Steps

参考: https://github.com/techtalk/SpecFlow/wiki/Scoped-bindings#scoping-tips--tricks