2

我有 ExcelStepDefinition 类,其中是我进行 excel 测试的步骤。我也有 WordStepDefinition 类。由于这两个类都有大量相同的步骤,因此我制作了一些 StepDefinition 类,它将成为这两个类的基类。

在这个基类中,我需要在构造函数中有一些参数,这取决于实例化的类(excel 或 word)。我已经完成了所有这些,但是当我在 Nunit 中开始测试时,它会失败并显示以下堆栈跟踪:

System.IndexOutOfRangeException : Index was outside the bounds of the array.
TearDown : System.IndexOutOfRangeException : Index was outside the bounds of the array.
at TechTalk.SpecFlow.ScenarioContext.GetBindingInstance(Type bindingType)
at TechTalk.SpecFlow.ScenarioContext.GetBindingInstance(Type bindingType)
at lambda_method(ExecutionScope )
at TechTalk.SpecFlow.Bindings.MethodBinding.InvokeAction(Object[] arguments, ITestTracer testTracer, TimeSpan& duration)
at TechTalk.SpecFlow.TestRunner.FireEvents(BindingEvent bindingEvent, IEnumerable`1 tags)
at TechTalk.SpecFlow.TestRunner.FireScenarioEvents(BindingEvent bindingEvent)
at TechTalk.SpecFlow.TestRunner.OnScenarioStart(ScenarioInfo scenarioInfo)
at ABZ.ExcelTest.DisplayValueOfLinkedItemUsingFormattingRulesDefinedForAGivenLanguageFeature.ScenarioSetup(ScenarioInfo scenarioInfo) in D:\Projects\VS2008\ABZ\ABZ Report Office\ABZ.ExcelTest\ExcelSwitchLanguage.feature.cs:line 0
at ABZ.ExcelTest.DisplayValueOfLinkedItemUsingFormattingRulesDefinedForAGivenLanguageFeature.DisplayFactValueWithFormattingDefinedInSelectedLanguage(String cell, String column, String label, String lang, String cellValue) in d:\Projects\VS2008\ABZ\ABZ Report Office\ABZ.ExcelTest\ExcelSwitchLanguage.feature:line 23
--TearDown
at TechTalk.SpecFlow.ScenarioContext.GetBindingInstance(Type bindingType)
at TechTalk.SpecFlow.ScenarioContext.GetBindingInstance(Type bindingType)
at lambda_method(ExecutionScope )
at TechTalk.SpecFlow.Bindings.MethodBinding.InvokeAction(Object[] arguments, ITestTracer testTracer, TimeSpan& duration)
at TechTalk.SpecFlow.TestRunner.FireEvents(BindingEvent bindingEvent, IEnumerable`1 tags)
at TechTalk.SpecFlow.TestRunner.FireScenarioEvents(BindingEvent bindingEvent)
at TechTalk.SpecFlow.TestRunner.OnScenarioEnd()
at ABZ.ExcelTest.DisplayValueOfLinkedItemUsingFormattingRulesDefinedForAGivenLanguageFeature.ScenarioTearDown() in D:\Projects\VS2008\ABZ\ABZ Report Office\ABZ.ExcelTest\ExcelSwitchLanguage.feature.cs:line 0

以下是基类和派生类(只是定义和构造函数):

// base class
[Binding]
    public class StepDefinition : Steps
    {
        IOfficeAppDriver officeAppDriver ;
        public StepDefinition(IReportFactoryAddInGuiElements repo, string application)
        {
            officeAppDriver = new OfficeAppDriver(new ReportFactoryOfficeAddInDriver(repo), application);
        }

// derivded one
[Binding]   
    public class ExcelStepDefinition : StepDefinition
    {          
        IExcelDriver excelDriver;
        public ExcelStepDefinition() : base(new Excel2007Repository(), "excel")
        {
            excelDriver = new ExcelDriver(officeAppDriver.ReportFactoryOfficeAddInDriver, factReader);          
        }

也许在这个构造函数中不可能有 args,我试过没有它们,它通过了。

你知道如何解决这个问题吗?

4

3 回答 3

6

-- 这是我在 SpecFlow Googe Group 上的回答的副本--

我认为这里有一个误解。

我认为按照您建议的方式使用继承是没有意义的。与传统的 xUnit 测试框架相比,SpecFlow 的工作方式大不相同。在 SpecFlow 中,步骤定义是全局的。步骤定义不必驻留在基类中即可从子类中使用。步骤定义与 xUnit 框架中的测试装置中的方法不同。

通常,使用 [Binding] 属性修饰的所有类都由 SpecFlow 扫描以发现步骤定义。当 SpecFlow 解析和执行功能时,找到的所有步骤定义都在运行时可用。为了让 SpecFlow 找到匹配的步骤定义,定义的步骤定义在哪个类中无关紧要。

但是,当 SpecFlow 找到匹配的步骤定义时,它需要能够实例化定义它的类。因此,包含步骤定义的类不能是抽象的。该实例主要用于在相关步骤定义之间传递状态(但是还有其他可能传递状态)。

钩子也是如此(之前.../之后...):它们是全局的,在运行时定义它们的类无关紧要。

以上是一般概念。当我们开始考虑作用域的步骤时,事情变得有点复杂:步骤定义可以作用于标签和场景,钩子可以作用于标签。

示例:
https ://github.com/techtalk/SpecFlow/blob/master/Tests/FeatureTests/ScopedStep/ScopedStepsBindings.cs
https://github.com/techtalk/SpecFlow-Examples/blob/master/ASP.NET-MVC /BookShop/BookShop.AcceptanceTests.Selenium/Support/SeleniumSupport.cs

在此处阅读更多信息: http://groups.google.com/group/specflow/browse_frm/thread/080c531cb17c86e0/5350665da2544871?
#5350665da2544871

阅读更多关于黄瓜维基。
关于全局步骤:
https ://github.com/cucumber/cucumber/wiki/Feature-Coupled-Steps-(Antipattern )
步骤组织:
https ://github.com/cucumber/cucumber/wiki/Step-Organisation

于 2011-03-18T21:39:14.390 回答
2

我发现这是错误。我为 specflow 贡献了这个 bug 的补丁,它将在下一个版本中发布。从现在开始,可以使用抽象类进行继承。

于 2011-04-04T16:18:52.383 回答
0

I think you are right - in a way.

SpecFlow supports something called Context injection which means that you can inject context into a Binding-class (see this https://github.com/techtalk/SpecFlow/blob/master/Tests/FeatureTests/ContextInjection/FeatureWithADependentContextSteps.cs). You can even have multiple context arguments (https://github.com/techtalk/SpecFlow/blob/master/Tests/FeatureTests/ContextInjection/FeatureWithMultipleContextsSteps.cs).

I think this can have to do with your problem. The thing is that all the contextes that are injected need to be parameterless, i.e. instantiated with a simple new, like this:

var obj = new MyType();

As I understand your class StepDefintion also contains steps? When these are called SpecFlow will try to resolve the injected dependencies to the constructor and fail, if on nothing else on the string which SpecFlow cannot know what to set to.

Maybe you could break out your Office-repository stuff to a separate class that the StepDefinition-classes could take as an argument.

Or you could go with an base-class that doesn't have steps (and hence no [Binding]-attribute).

I haven't checked this to much but this is what I think happens - love to hear you thoughts on this.

于 2011-03-17T07:48:14.187 回答