Наследование определения шага specflow

У меня есть класс 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);          
        }

Возможно, в этом конструкторе невозможно иметь аргументы, я пробовал без них, и все прошло.

Вы знаете, как это решить?


person Vajda    schedule 16.03.2011    source источник


Ответы (3)


- Это копия из моего ответа о группе SpecFlow Googe - -

Я думаю, здесь есть недоразумение.

Я думаю, что нет смысла использовать наследование в том виде, в каком вы его предлагаете. SpecFlow работает совершенно иначе, чем традиционные фреймворки xUnit Test. В 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

Подробнее читайте в вики по Cucumber.
О глобальных шагах:
https://github.com/cucumber/cucumber/wiki/Feature-Coupled-Steps-(Antipattern)
Организация шагов:
https://github.com/cucumber/cucumber/wiki/Step-Organization

person jbandi    schedule 18.03.2011

Я обнаружил, что это ошибка. Я внес патч для этой ошибки в specflow, и он будет в следующем выпуске. Отныне возможно наследование с абстрактными классами.

person Vajda    schedule 04.04.2011
comment
Пришло ли это, если да, то в какой версии выпуска - person Ian Ringrose; 10.05.2011

Думаю, в каком-то смысле вы правы.

SpecFlow поддерживает так называемое внедрение контекста, что означает, что вы можете внедрить контекст в класс привязки (см. Это https://github.com/techtalk/SpecFlow/blob/master/Tests/FeatureTests/ContextInjection/FeatureWithADependentContextSteps.cs). У вас даже может быть несколько аргументов контекста (https://github.com/techtalk/SpecFlow/blob/master/Tests/FeatureTests/ContextInjection/FeatureWithMultipleContextsSteps.cs).

Думаю, это может быть связано с твоей проблемой. Дело в том, что все внедряемые контексты должны быть без параметров, то есть создаваться с помощью простого new, например:

var obj = new MyType();

Насколько я понимаю, ваш класс StepDefintion тоже содержит шаги? Когда они вызываются, SpecFlow попытается разрешить внедренные зависимости в конструктор и потерпит неудачу, если ни на чем другом в строке, которую SpecFlow не может знать, что установить.

Возможно, вы могли бы выделить свой репозиторий Office в отдельный класс, который классы StepDefinition могли бы принять в качестве аргумента.

Или вы можете использовать базовый класс, у которого нет шагов (и, следовательно, нет атрибута [Binding]).

Я не слишком много это проверял, но, как мне кажется, происходит именно это - я хотел бы услышать ваши мысли по этому поводу.

person Marcus Hammarberg    schedule 17.03.2011
comment
@ marcusoft.net У меня не может быть базового класса без шагов, потому что шаги - это то, что я хочу сделать одинаковым для обоих моих репозиториев (excel и word), чтобы не писать одно и то же дважды. - person Vajda; 17.03.2011
comment
@ marcusoft.net Если я разделю репозиторий Office на отдельный класс, мне все равно нужно будет выполнить те же шаги в двух классах с вызовом методов из офисного репозитория. В этом случае у меня тоже ничего нет. Я мог бы просто написать новый проект за слово, скопировать и вставить все мои шаги, в основном это то же самое. - person Vajda; 17.03.2011
comment
@ marcusoft.net Я посмотрю эту контекстную инъекцию и посмотрю, есть ли какое-то возможное решение - person Vajda; 17.03.2011
comment
@vadja - точно, я думаю, вы можете вызвать внедренный контекст или, в вашем случае, IReportFactoryAddInGuiElements. Это была моя мысль из моего скромного понимания вашей проблемы ... - person Marcus Hammarberg; 17.03.2011
comment
Как вы думаете, вызовите? Чтобы установить это поле позже в конструкторе? - person Vajda; 17.03.2011
comment
точно - отделите шаги от офисной интеграции, чтобы у вас были чистые шаги-классы с некоторой внедренной офисной интеграцией ... Надеюсь, я правильно понял вашу проблему ... - person Marcus Hammarberg; 18.03.2011