web-dev-qa-db-ja.com

SpecFlowでは、ステップ/機能間でデータをどのように共有できますか?

共通の「When」ステップを使用する2つの機能がありますが、クラスによって異なる「Then」ステップがあります。

たとえば、2つのThenステップのWhenステップでMVCコントローラコールのActionResultにアクセスするにはどうすればよいですか?

37
Simon Keep

SpecFlow 1.3には3つの方法があります。

  1. 静的メンバー
  2. ScenarioContext
  3. ContextInjection

コメント:

  1. 静的メンバーは非常に実用的であり、この場合、開発者が最初に考えるほど邪悪ではありません(スレッド化やステップ定義でのモック/置換の必要はありません)。

  2. このスレッドで@Si Keepからの回答を参照してください

  3. ステップ定義クラスのコンストラクターに引数が必要な場合、Specflowはこれらの引数を挿入しようとします。これは、同じコンテキストをいくつかのステップ定義に挿入するために使用できます。
    ここに例を示します: https://github.com/techtalk/SpecFlow/wiki/Context-Injection

36
jbandi

すべてのステップに共通の辞書であるScenarioContextクラスを使用します。

ScenarioContext.Current.Add("ActionResult", actionResult);
var actionResult = (ActionResult) ScenarioContext.Current["ActionResult"];
34
Simon Keep

私は書くことを可能にするヘルパークラスを持っています

Current<Page>.Value = pageObject;

これはScenarioContextのラッパーです。タイプ名で機能するため、同じタイプの2つの変数にアクセスする必要がある場合は、少し拡張する必要があります。

 public static class Current<T> where T : class
 {
     internal static T Value 
     {
         get { 
               return ScenarioContext.Current.ContainsKey(typeof(T).FullName)
               ? ScenarioContext.Current[typeof(T).FullName] as T : null;
             }
         set { ScenarioContext.Current[typeof(T).FullName] = value; }
     }
 }

2019編集:@JoeTの回答を最近使用します。拡張機能を定義しなくても、同じ利点が得られるようです

16
mcintyre321

各ディクショナリエントリをキャストアウトする必要があるため、Scenario.Contextの使用は好みませんでした。キャストせずにアイテムを保存および取得する別の方法を見つけました。ただし、ScenarioContextディクショナリからオブジェクトにアクセスするキーとしてタイプを効果的に使用しているため、ここにはトレードオフがあります。つまり、そのタイプのアイテムは1つしか保存できません。

TestPage testPageIn = new TestPage(_driver);
ScenarioContext.Current.Set<TestPage>(testPageIn);
var testPageOut = ScenarioContext.Current.Get<TestPage>();
11
JoeT

保存する値のキーとなるパラメーターをステップに定義できます。このように、キーを使用して後のステップでそれを参照できます。

...
Then I remember the ticket number '<MyKey>'
....
When I type my ticket number '<MyKey>' into the search box
Then I should see my ticket number '<MyKey>' in the results 

実際の値は、辞書やプロパティバッグなどに保存できます。

0
Daniel Kereama