うまくいけば、他の人が理解できるように自分の問題を十分に明確に説明できます。ここでは、次の2つの仮想シナリオがあると想像してください。
Scenario: Filter sweets by king size and nut content
Given I am on the "Sweet/List" Page
When I filter sweets by
| Field | Value |
| Filter.KingSize | True |
| Filter.ContainsNuts | False |
Then I should see :
| Value |
| Yorkie King Size |
| Mars King Size |
Scenario: Filter sweets by make
Given I am on the "Sweet/List" Page
When I filter sweets by
| Field | Value |
| Filter.Make | Haribo |
Then I should see :
| Value |
| Starmix |
これらのシナリオは、関連するコンパイル済みテストステップを変更せずに、Field/ValueエントリとThenValueエントリのWhen行を好きなだけ追加できるので便利です。ただし、さまざまなフィルターテストのコピー/貼り付けのシナリオは繰り返しになり、多くのコードを使用します。これは避けたいことです。理想的には、シナリオのアウトラインを作成し、上記のテストでの動的な性質を維持したいと思いますが、それを実行しようとすると、サンプルテーブルの定義で問題が発生し、適切と思われる新しい行を追加できません。新しいテストインスタンス、現在私はこれを持っています:
Scenario Outline: Filter Sweets
Given I am on the <page> Page
When I filter chocolates by
| Field | Value |
| <filter> | <value> |
Then I should see :
| Output |
| <output> |
Examples:
| page | filter | value | output |
| Sweet/List | Filter.Make | Haribo | Starmix |
したがって、シナリオのアウトラインを使用すると、フィルターと期待されるデータに行を動的に追加できるという問題があります。これを回避する方法を知っている人はいますか?これに別の角度からアプローチする必要がありますか?
回避策は次のようになります。
Then I should see :
| Output |
| <x> |
| <y> |
| <z> |
Examples:
| x | y | z |
しかし、それはあまり動的ではありません....より良い解決策を望んでいますか? :)
技術的には、ステップ定義内からステップを呼び出すことができると思います。
たとえば、私はあなたが書き直すことができると思います
Then I should see :
| Output |
| <output> |
のようなカスタムステップになる
I should have output that contains <output>
ここで、出力は期待値のコンマ区切りのリストです。カスタムステップでは、コンマ区切りのリストを配列に分割し、それを繰り返して呼び出すことができます。
Then "I should see #{iterated_value}"
同様の手法を使用して、フィルターとフィルター値のリストを渡すことができます。キングサイズテストの行の例は次のようになります。
| page | filter | value | output |
| Sweet/List | Filter.KingSize, Filter.ContainsNuts | True, False | Yorkie King Size, Mars King Size |
または多分
| page | filter-value-pairs | output |
| Sweet/List | Filter.KingSize:True, Filter.ContainsNuts:False | Yorkie King Size, Mars King Size |
そうは言っても、あなたはおそらくダレンの言葉を心に留めるべきです。この方法が、開発者以外でも読めるシナリオを作成するという最終的な目標に役立つかどうかはわかりません。
SpecFlow、Gherkin、およびすぐに使用できるCucumberでは、あなたが求めていることは不可能だと思います。著者のために話すことはできませんが、これらの仕様を作成して実装する全体的な「流れ」に反するため、意図的にこのように使用することを意図したものではないと思います。とりわけ、仕様は、プログラマー以外の人にも読めるように、仕様に一致するコードを実装するためのガイドをプログラマーに提供し、統合テストを行い、リファクタリング時に認証者にある程度の柔軟性を与えることを目的としています。
これはあなたが感じている痛みが問題の兆候である状況の1つだと思いますが、それはあなたが思っているものではないかもしれません。あなたが言った:
「しかし、さまざまなフィルターテストのコピー/貼り付けのシナリオは繰り返しになり、多くのコードを消費します。これは避けたいことです。」
First、書面で自分自身を説明することが「反復的」であることに同意しません。少なくとも、「the、Apple、carなど」などの特定の単語を使用することは反復的です。何度も何度も。問題は:これらの言葉はあなたがしていることを適切に説明していますか?もしそうなら、そしてあなたの状況を説明するためにあなたが複数のシナリオを書き出す必要があるなら、それはそれが必要とするものです。コミュニケーションには言葉が必要であり、時には同じ言葉が必要です。
実際、「反復的」と呼ぶものは、GherkinとCucumberやSpecFlowなどのツールを使用する利点の1つです。その文を何度も何度も使用できる場合は、テストコードを何度も何度も書く必要がないことを意味します。
Second、あなたは正しいことの仕様を書いていると確信していますか?シナリオの数が手に負えなくなって、人間があなたの書いたものに従えなくなるほど多くなると、あなたのスペックが正しいものに向けられていない可能性があるからです。
この可能性のある例は、このシナリオでフィルタリングおよびページネーションをテストする方法です。はい、あなたはあなたのスペックが完全な機能をカバーすることを望みます、そしてあなたのサイトはあなたのフィルタリングと同じページにページネーションを持ちます、しかしどのくらいの費用がかかりますか?想定される「理想的な」モックなしの完全統合テストをあきらめると、より良い結果が得られることを知るには、経験と実践が必要です。
番目、仕様がすべての可能なシナリオを完全にカバーすることを意図しているとは思わないでください。シナリオは基本的に状態のスナップショットです。つまり、無限に大きなシナリオのセットをカバーできる機能がいくつかありますが、これは不可能です。それで、あなたは何をしますか?できる限りストーリーを伝える機能を作成します。ストーリーでさえ開発を推進します。ただし、仕様やその他のケースに変換されない詳細は、仕様に加えて行われるTDDに任せるのが最善です。
あなたの例では、基本的に、ユーザーがお菓子やキャンディーに対して動的な検索を作成できるサイトについての話をしているようです。可能な検索条件の大規模なセットの1つを入力し、ボタンをクリックして、結果を取得します。それに固執し、ストーリーを実現するのに十分なスペックだけを書いてください。カバレッジに満足できない場合は、より多くの仕様または単体テストでクリーンアップしてください。
とにかく、それは私の考えです、それが役立つことを願っています。