Как я заставляю SpecFlow ожидать исключение?

Я использую 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]?

40
задан Raedwald 1 March 2019 в 14:09
поделиться

4 ответа

Отличный вопрос. Я не являюсь экспертом по 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

40
ответ дан 27 November 2019 в 01:13
поделиться

Как новичок в 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

37
ответ дан 27 November 2019 в 01:13
поделиться

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

14
ответ дан 27 November 2019 в 01:13
поделиться

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

  1. Перехватить исключение (я действительно рекомендую перехватить определенные исключения, если вам действительно не нужно перехватывать все) на шаге, который вызывает операцию, и передать его сценарию контекст.

      [Когда ("Я нажимаю добавить")]
    public void WhenIPressAdd ()
    {
    пытаться
     {
     _calc.Add ();
     }
    catch (ошибка исключения)
     {
    ScenarioContext.Current [("Ошибка")] = err;
     }
    }
    
  2. Убедитесь, что исключение сохранено в контексте сценария

      [Затем (@ "должно быть сгенерировано исключение")]
    public void ThenItShouldThrowAnException ()
    {
    Assert.IsTrue (ScenarioContext.Current.ContainsKey («Ошибка»));
    }
    

P.S. Это очень близко к одному из существующих ответов. Однако, если вы попытаетесь получить значение из ScenarioContext, используя синтаксис, подобный приведенному ниже:

var err = ScenarioContext.Current["Error"]

, он вызовет другое исключение в случае, если ключ «Ошибка» не существует (и это приведет к сбою всех сценариев, которые выполняют вычисления с правильными параметрами). Так что ScenarioContext.Current.ContainsKey может быть более подходящим

7
ответ дан 27 November 2019 в 01:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: