Я использую SpecFlow, и я хотел бы записать сценарий, такой как следующее:
Scenario: Pressing add with an empty stack throws an exception
Given I have entered nothing into the calculator
When I press add
Then it should throw an exception
Это calculator.Add()
это собирается выдать исключение, поэтому как я обрабатываю это в отмеченном методе [Then]
?
Отличный вопрос. Я не являюсь экспертом по bdd или specflow, однако мой первый совет - сделать шаг назад и оценить свой сценарий.
Вы действительно хотите использовать в этой спецификации термины «выброс» и «исключение»? Имейте в виду, что идея bdd состоит в том, чтобы использовать универсальный язык для бизнеса. В идеале они должны уметь читать эти сценарии и интерпретировать их.
Попробуйте изменить фразу «then», чтобы включить что-то вроде этого:
Scenario: Pressing add with an empty stack displays an error
Given I have entered nothing into the calculator
When I press add
Then the user is presented with an error message
Исключение все еще генерируется в фоновом режиме, но конечным результатом является простое сообщение об ошибке.
Скотт Беллвар затрагивает эту концепцию в этом подкасте Herding Code: http://herdingcode.com/?p=176
Как новичок в SpecFlow, я не скажу вам, что это способ сделать это, но один из способов сделать это - использовать ScenarioContext
для хранения исключения, сгенерированного в When ;
try
{
calculator.Add(1,1);
}
catch (Exception e)
{
ScenarioContext.Current.Add("Exception_CalculatorAdd", e);
}
В вашем Затем вы можете проверить выбранное исключение и выполнить для него утверждения;
var exception = ScenarioContext.Current["Exception_CalculatorAdd"];
Assert.That(exception, Is.Not.Null);
С учетом сказанного; Я согласен с scoarescoare , когда он говорит, что вам следует сформулировать сценарий в более «дружественных для бизнеса» формулировках. Однако использование SpecFlow для управления реализацией вашей модели предметной области, перехват исключений и выполнение на них утверждений может пригодиться.
Кстати: посмотрите скринкаст Роба Конери на TekPub, чтобы получить несколько действительно полезных советов по использованию SpecFlow: http://tekpub.com/view/concepts/5
BDD можно практиковать на уровне функций и / или на уровне единиц.
SpecFlow - это инструмент BDD, который фокусируется на поведении на уровне функций. Исключения - это не то, что вы должны указывать / соблюдать при поведении на уровне функций. Исключения должны быть указаны / соблюдены в поведении на уровне единиц.
Думайте о сценариях SpecFlow как о живой спецификации для нетехнических заинтересованных сторон. Вы бы также не писали в спецификации, что генерируется исключение, а как система ведет себя в таком случае.
Если у вас нет заинтересованных сторон, не имеющих технического характера, тогда SpecFlow - неподходящий инструмент! Не тратьте силы на создание бизнес-удобочитаемых спецификаций, если их никто не хочет читать!
Существуют инструменты BDD, которые фокусируются на поведении на уровне юнита. В .NET наиболее популярным является MSpec ( http://github.com/machine/machine.specifications ). BDD на уровне модулей также может быть легко применен к стандартным средам модульного тестирования.
Тем не менее, вы все еще можете проверить исключение в SpecFlow .
Вот еще несколько обсуждений bdd на уровне модулей и bdd на уровне функций: SpecFlow / BDD против модульного тестирования BDD для приемочных тестов против BDD для модульных тестов (или: ATDD против TDD)
Также ознакомьтесь с этим сообщением в блоге: Классификация инструментов BDD (управляемые модульным тестированием vs.Acceptance Test Driven) и немного истории BDD
Изменение сценария, чтобы исключение не было, вероятно, является хорошим способом сделать сценарий более ориентированным на пользователя. Однако, если вам все еще нужно, чтобы это работало, учтите следующее:
Перехватить исключение (я действительно рекомендую перехватить определенные исключения, если вам действительно не нужно перехватывать все) на шаге, который вызывает операцию, и передать его сценарию контекст.
[Когда ("Я нажимаю добавить")]
public void WhenIPressAdd ()
{
пытаться
{
_calc.Add ();
}
catch (ошибка исключения)
{
ScenarioContext.Current [("Ошибка")] = err;
}
}
Убедитесь, что исключение сохранено в контексте сценария
[Затем (@ "должно быть сгенерировано исключение")]
public void ThenItShouldThrowAnException ()
{
Assert.IsTrue (ScenarioContext.Current.ContainsKey («Ошибка»));
}
P.S. Это очень близко к одному из существующих ответов. Однако, если вы попытаетесь получить значение из ScenarioContext, используя синтаксис, подобный приведенному ниже:
var err = ScenarioContext.Current["Error"]
, он вызовет другое исключение в случае, если ключ «Ошибка» не существует (и это приведет к сбою всех сценариев, которые выполняют вычисления с правильными параметрами). Так что ScenarioContext.Current.ContainsKey
может быть более подходящим