42

私は 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]ますか?

4

7 に答える 7

41

素晴らしい質問です。私は 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

例外は引き続きバックグラウンドでスローされますが、最終結果は単純なエラー メッセージです。

Scott Bellware は、この Herding Code ポッドキャストでこの概念に触れています: http://herdingcode.com/?p=176

于 2010-05-21T23:59:07.180 に答える
39

SpecFlow の初心者として、これがその方法であるとは言いませんが、その 1 つの方法は、 WhenScenarioContextでスローされた例外を格納するために を使用することです。

try
{
    calculator.Add(1,1);
}
catch (Exception e)
{
    ScenarioContext.Current.Add("Exception_CalculatorAdd", e);
}

Thenでは、スローされた例外を確認し、それに対してアサートを行うことができます。

var exception = ScenarioContext.Current["Exception_CalculatorAdd"];
Assert.That(exception, Is.Not.Null);

とは言うものの; もう少し「ビジネスに適した」表現でシナリオを策定する必要があるというscoarescoare の意見に同意します。ただし、SpecFlow を使用してドメイン モデルの実装を推進し、例外をキャッチしてそれらに対してアサートを実行すると便利です。

ところで、TekPub で Rob Conery のスクリーンキャストをチェックして、SpecFlow の使用に関する非常に役立つヒントを確認してください: http://tekpub.com/view/concepts/5

于 2010-05-23T13:05:01.467 に答える
14

BDD は、機能レベルの動作またはユニット レベルの動作で実践できます。

SpecFlow は、機能レベルの動作に焦点を当てた BDD ツールです。例外は、機能レベルの動作で指定/観察する必要があるものではありません。例外は、ユニット レベルの動作で指定/観察する必要があります。

SpecFlow シナリオは、非技術関係者向けのライブ仕様と考えてください。また、例外がスローされることを仕様に記述するのではなく、そのような場合にシステムがどのように動作するかを記述します。

技術者以外の利害関係者がいない場合、SpecFlow は適切なツールではありません。誰も読みたいと思っていないのに、ビジネスで読める仕様を作成することにエネルギーを浪費しないでください!

ユニット レベルの動作に焦点を当てた BDD ツールがあります。.NET で最も一般的なのは MSpec ( http://github.com/machine/machine.specifications ) です。ユニット レベルの BDD は、標準のユニット テスト フレームワークでも簡単に実行できます。

とはいえ、 SpecFlow で例外をチェックすることはできます。

ユニット レベルの bdd と機能レベルの bdd の詳細については、次を参照して ください

このブログ投稿も参照してください: BDD ツールの分類 (単体テスト駆動型 vs. 受け入れテスト駆動型) と BDD の歴史の一部

于 2010-05-31T12:36:08.650 に答える
7

例外がないようにシナリオを変更することは、シナリオをよりユーザー指向にするためのおそらく良い方法です。ただし、それでも機能させる必要がある場合は、次の点を考慮してください。

  1. 操作を呼び出してシナリオ コンテキストに渡すステップで、例外をキャッチします (本当にすべてをキャッチする必要がない限り、特定の例外をキャッチすることを強くお勧めします)。

    [When("I press add")]
    public void WhenIPressAdd()
    {
       try
       {
         _calc.Add();
       }
       catch (Exception err)
       {
          ScenarioContext.Current[("Error")] = err;
       }
    }
    
  2. 例外がシナリオ コンテキストに格納されていることを検証する

    [Then(@"it should throw an exception")]
    public void ThenItShouldThrowAnException()
    {
          Assert.IsTrue(ScenarioContext.Current.ContainsKey("Error"));
    }
    

PS既存の回答の1つに非常に近いです。ただし、次のような構文を使用して ScenarioContext から値を取得しようとすると:

var err = ScenarioContext.Current["Error"]

「エラー」キーが存在しない場合は、別の例外がスローされます (正しいパラメーターで計算を実行するすべてのシナリオが失敗します)。だからScenarioContext.Current.ContainsKey、もっと適切かもしれません

于 2010-07-07T00:02:52.553 に答える
5

ユーザー インタラクションをテストしている場合は、ユーザー エクスペリエンスに焦点を当てることについて既に述べられていることのみをアドバイスします。「その後、ユーザーにエラー メッセージが表示されます」。ただし、UI の下のレベルをテストしている場合は、私の経験を共有したいと思います。

SpecFlow を使用してビジネス層を開発しています。私の場合、UI インタラクションは気にしませんが、BDD アプローチと SpecFlow は非常に便利です。

ビジネスレイヤーでは、「その後、ユーザーにエラーメッセージが表示される」という仕様は望んでいませんが、実際にはサービスが間違った入力に正しく応答することを検証しています。"When" で例外をキャッチし、"Then" でそれを検証するという既に言われていることをしばらく実行しましたが、このオプションは最適ではないことがわかりました。予期していなかった例外。

現在、明示的な「Then」句を使用していますが、「When」を使用しない場合もあります。次のようにします。

Scenario: Adding with an empty stack causes an error
     Given I have entered nothing into the calculator
     Then adding causes an error X

これにより、アクションと例外検出を 1 つのステップで明確にコーディングできます。これを再利用して、必要な数のエラー ケースをテストできます。また、失敗しない「When」ステップに関係のないコードを追加する必要もありません。

于 2011-06-14T00:20:52.520 に答える