10

C#Specflowテストプロジェクトに少なくとも3つの.featureファイルがあり、そのステップがあります。たとえば、次のようになります。

Given I am at the Home Page

最初にファイルにステップを記述Feateure1.featureしてstepメソッドを作成したとき、それをステップファイルに配置しました。たとえば、Steps1.csを初期化する基本クラスから継承しますFirefoxDriver。私のクラスはすべて、StepsXXXX.csこの基本クラスを継承しています。

Feature2.feature次に、ステップを持っている、を書きましたGiven I am at the Home Page。そして、そのステップは自動的に次のステップにバインドされましたSteps1.cs

「今まで、問題ありません。それは私が望んでいたこととほぼ同じです。テストプロジェクト全体で再利用可能な手順を実行する必要があります。ただし、問題は、異なるファイルにステップがあるシナリオを実行しているときはいつでも、StepsXXXXさまざまなブラウザーインスタンスが実行されることです。

======

これは、My StepsXXXX(バインディングクラス)がすべて、独自のIWebDriverを持つこの基本クラスから継承し、ステップが呼び出されると、他のすべて(シナリオの前後のメソッドを含む)がと呼ばれる。しかし、これを回避する方法がわかりません。

私はまだ再利用可能なステップが欲しいです。これらのステップを基本クラスに入れようとしましたが、うまくいきませんでした。バインディングも変更することを考えましたが、specflowは意味のある文字列を使用して変更するため、誤解を招く文字列に変更したくありません。

誰かがこれに遭遇しましたか?どんな助けでも本当にありがたいです。

4

4 に答える 4

6

問題は、SpecFlowバインディングが継承を尊重しないことです。すべてのカスタム属性はグローバルと見なされるため、SpecFlowは、[Binding]を使用してクラスのリストを検索し、すべての[Given] / [When] / [Then]のディクショナリを作成して、それらを評価できるようにします。ベストマッチのために。次に、クラスのインスタンスを作成し(まだ作成していない場合)、そのインスタンスでメソッドを呼び出します。

結果として、最初の完全一致であるため、単純なケースはすべてSteps1クラスにとどまります。より複雑なケースでは、より多くのクラス、つまり複数のブラウザーのインスタンス化が開始されます。また、抽象基本クラスに[Binding]がないため、リファクタリングの試みは機能しません。

私はおそらく、すべてのステップクラス階層を1つの大きなAllSteps.csクラスにフラット化することから始めます。これは逆効果に見えるかもしれませんが、実際に行っているのは、現在のバインディングがSpecFlow機能にどのように表示されるかをコードに配置することだけです。このようにして、異なるGWTバインディング間のオーバーラップをリファクタリングし始めることができます。

現時点では、バインディングはシナリオの周りに配置されています。あなたがする必要があるのはあなたの機能の周りでそれらをリファクタリングすることです。とにかく誰のドメインを読んだことがありますか?あなたが始める前に、これはおそらくあなたにいくつかの良いアイデアを与えるでしょう。次に、SpecFlowドキュメントのSharing-Data-between-Bindingsを参照して、新しいステップクラス間のリンク方法を確認してください。

于 2013-03-19T18:50:34.927 に答える
6

スコープ付きバインディングを使用[Scope(Tag = "mytag", Feature = "feature title", Scenario = "scenario title")]して、次のような特定のシナリオまたは機能を参照できます。

Feature: Feateure1

Scenario: demo
Given I am at the Home Page
When ....

[Binding, Scope(Feature = "Feateure1")]
public class Steps1{

 [Given(@"Given I am at the Home Page")]
 public void GivenIAmAtTheHomePage(){
  {  }
}

Feature: Feateure2

Scenario: demo
Given I am at the Home Page
When ....
...

[Binding,Scope(Feature = "Feateure2")]
public class Steps2{

 [Given(@"Given I am at the Home Page")]
 public void GivenIAmAtTheHomePage(){
 {  }

}
于 2016-06-28T08:46:12.913 に答える
4

これは、ここでの質問と回答よりもはるかに単純だと思います。ここでは、実際に2つの質問があります。

AISkiは、specflowコンテキストに関するドキュメントへのリンクで正しい答えを示しましたが、実際には答えとして提示されておらず、実際の答えとして劣った答えを提示することに気を取られていました。

あなたが見る行動に関する答えは、あなたが物事を設定する方法で何が起こっているかを正確に期待するべきであるということです。ブラウザインスタンスを作成する複数のバインディングクラスがあり(そして、それらすべてにブラウザインスタンスを作成する共通ベースがある場合)、機能に一致するものがある場合は、複数のブラウザインスタンスを期待する必要があります。

意図すること(ステップ間で共有される単一のブラウザー)に対する答えは、ブラウザーインスタンスへの依存関係を制御するためにspecflowのコンテキスト機能を使用する必要があるということです。これは依存性注入に相当します。ステップ定義クラスは、ブラウザーインスタンスを作成するものに対するコンストラクターの依存関係を取得する必要があります。specflowが依存関係を管理し、作成された最初のクラスの新しいインスタンスを取得し、その後同じインスタンスを取得します。

https://github.com/techtalk/SpecFlow/wiki/Sharing-Data-between-Bindings

于 2014-03-18T10:57:25.063 に答える
3

私は同じ問題に直面しています。

さまざまなcsクラスのステップを呼び出す1つの機能ファイルが必要でした。この問題は、シナリオごとにセットアップして破棄したいときに発生しました。

ステップクラスコンストラクターをDispose()使用しますが、シナリオで複数回「セットアップ」したくない複数のステップクラスをシナリオが使用しているため、不可能です。

[BeforeScenario]両方のステップクラスにandを使用[AfterScenario]すると、ランナーは両方のクラスのbeforeメソッドとafterメソッドを実行し、セットアップを2回実行します。

だから私がやったことはBrowserScenarioSetup、シナリオの前と後のクラスを入れてシナリオのブラウザをセットアップし、ScenarioContext.Current辞書に割り当てるようなものと呼ばれる別の3番目のクラスを作成することです。テストを実行すると、シナリオ用に作成されたブラウザーは1つだけで、任意のクラスで定義されたシナリオステップを使用できますScenario.Context.Currentが、ブラウザーインスタンスを取得するために使用します。

両方のステップクラスに基本ステップクラスを持たせ、ブラウザインスタンス(またはセットアップで作成された共有インスタンス)を非表示にするための短いメソッドを作成できますScenario.Context.Current

最後に[BeforeScenario("Browser", "IE")]、機能またはシナリオで@Browserと@IEをマークして使用し、適切なコンテキストでのみこのセットアップメソッドを呼び出すことができます。

于 2013-08-01T16:27:01.077 に答える