SpecFlow で複数依存の要件に対応する機能を作成する方法
質問
私は SpecFlow を学習しており、単純な Com-Sci 標準 FizzBuzz プロジェクトを実行しています。さまざまな数値を考えると、分割可能な数字を3でゼロと交換します。分割可能である5で分裂します。
これは非常に単純なアプリケーションですが、私にとって疑問が生じました。API の 1 つのメソッド呼び出しからすべてが起動される複数の要件をテストする機能を作成するにはどうすればよいでしょうか?例えば。API呼び出しは次のようになります。 FizzBuzz.Replace(1, 100);
Replace メソッド コードを使用して
public static string Replace (int min, int max)
{
if (IsDiv3 && IsDiv5) {...}
if (IsDiv3) {...}
if (IsDiv5) {...}
...
}
SpecFlow の機能は次のとおりです。
Feature: FizzBuzz
In order to display Fizz Buzz in range of numbers
As a user I want to be able to see Fizz Buzz replace certain numbers
Scenario: Replace muliples of three and five with Fizz, Buzz or FizzBuzz
Given I have a range of numbers from 1 to 15
When I press Submit
Then the result should be
| Numbers |
| 1 |
| 2 |
| Fizz |
| 4 |
| Buzz |
| Fizz |
| 7 |
| 8 |
| Fizz |
| Buzz |
| 11 |
| Fizz |
| 13 |
| 14 |
| FizzBuzz|
さらに問題となるのは、すべての要件を 1 つの機能にまとめる必要がある場合に、その機能をより有意義なものにする方法です。
編集2 番目のシナリオを作成するとすぐに最初のシナリオが失敗するため、複数のシナリオを作成するのに苦労しています。
scenario 1: replace divisable by 3 with Fizz
Expected = 1 2 Fizz 4 5 Fizz 7 8 Fizz 10 11 Fizz 13 14 Fizz
Actual = 1 2 Fizz 4 5 Fizz 7 8 Fizz 10 11 Fizz 13 14 Fizz (First test)
Actual = 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 Fizz (Second test)
それから次のシナリオを実行します
Scenario 2: replace divisable by 5 with Buzz
Expected = 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 Fizz
Actual = 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 Fizz (Second test)
2 番目のシナリオは成功しますが、最初のシナリオは失敗します。シナリオ 1、2、3 を実行するために API を開くことがアプリにとって良い設計であるとは思いません。
ありがとう、
解決
メーリングリストであなたのメッセージを見ました。Fizz、Buzz、FizzBuzz のテストを分割したい場合は、仕様を変更して実装の各ブランチのシナリオを作成できます (つまり、それぞれの「場合」):
Scenario: Replace multiples of three with Fizz
Given I have a range of numbers from 1 to 4
When I press Submit
Then the result should be
| Numbers |
| 1 |
| 2 |
| Fizz |
| 4 |
Scenario: Replace multiples of five with Buzz
Given I have a range of numbers from 4 to 5
When I press Submit
Then the result should be
| Numbers |
| 4 |
| Buzz |
Scenario: Replace multiples of three and five with FizzBuzz
Given I have a range of numbers from 14 to 16
When I press Submit
Then the result should be
| Numbers |
| 14 |
| FizzBuzz |
| 16 |
あなたの例のもう 1 つの観察は、期待はテーブル (基本的に配列) で表現されますが、結果は文字列で表現されることです。この例では SpecFlow を使用して API テストを行っているため、仕様または API を変更して、これら 2 つをより厳密に調整しようとします。
たとえば、次の API 変更「public static string[] Replace(int min, int max)」について考えてみましょう。そうすれば、次のような手順を書くのが簡単になります。
[Binding]
public class FizzBuzzSteps
{
private int _min;
private int _max;
private string[] _results;
[Given(@"I have a range of numbers from (\d+) to (\d+)")]
public void GivenIHaveARangeOfNumbers(int min, int max)
{
_min = min;
_max = max;
}
[When(@"I press Submit")]
public void WhenIPressSubmit()
{
_results = FizzBuzz.Replace(_min, _max);
}
[Then(@"the result should be")]
public void ThenTheResultShouldBe(Table table)
{
for (var i = 0; i < table.RowCount; i++)
{
var expected = table.Rows[i]["Numbers"];
var actual = _results[i];
Assert.AreEqual(expected, actual);
}
}
}
HTH、ダン・モーク
他のヒント
表示した仕様を実行すると、specflow は次のようなメソッドを作成することを提案します。
[Then(@"the result should be")]
public void ThenTheResultShouldBe(Table table)
次のようにテーブルから値を反復して取得できます。
[Then(@"the result should be")]
public void ThenTheResultShouldBe(Table table)
{
foreach (var row in table.Rows)
{
var numberValue = row["Numbers"]; // the name of the column specified
}
}
テストをより意味のあるものにする方法として、私が言えることは、私個人としては、このテストをさまざまなシナリオに分割することです。3 で割った数字以外の数字として表示される数字について 1 つのシナリオを実行し、もう 1 つのシナリオを 5 で割ったものを実行します。