6

次のようなテストを記述できるようにしたいと考えています。

Background:
  Given a user signs up for a 30 day account

Scenario: access before expiry
  When they login in 29 days
  Then they will be let in

Scenario: access after expiry
  When they login in 31 days
  Then they will be asked to renew

Scenario: access after acounnt deleted
  When they login in 2 years time
  Then they will be asked to register for a new account

テストの specflow 側を行うにはどうすればよいですか?

編集:同じステップ定義で「31日」と「2年」の両方にどのように対処できますか

4

6 に答える 6

3

この .feature ファイルをビルドすると、テスト用の分離コードが作成されます。次に、各ステップをメソッドに接続する必要があります。これを行う最も簡単な方法は、

1: テストをデバッグします。テストは不確定として失敗します。Test run results specflow を見ると、このテストのテンプレートを追加するのに役立ちます。エラーメッセージは次のようになります

Assert.Inconclusive が失敗しました。1 つ以上のステップに一致するステップ定義が見つかりません。

    [Binding]
public class StepDefinition1
{
    [Given(@"a user signs up for a 30 day account")]
    public void GivenAUserSignsUpForA30DayAccount()
    {
    }

    [When(@"they login in 29 days")]
    public void WhenTheyLoginIn29Days()
    {
        ScenarioContext.Current.Pending();
    }

    [Then(@"they will be let in")]
    public void ThenTheyWillBeLetIn()
    {
        ScenarioContext.Current.Pending();
    }
}

2: これを新しい specflow ステップ定義ファイルにコピーします。これは基本的に、specflow 属性が入力された単体テスト クラスです。今、あなたを助けるためにあなたができるいくつかのトリックがあります. GivenAUserSignsUpForA30DayAccount メソッドでは、30 日間の試用アカウントを持つテストで使用されるユーザーを作成します。プライベート メンバーはここでは正常に機能するため、メソッド間でアクセスできますが、これはすべてのメソッドが同じクラスにある場合にのみ機能します。複数の機能/クラス間でメソッドを再利用しようとする場合は、オブジェクトを ScenarioContext に保存することを検討する必要があります

3: specflow テストを実行すると、同じ文字列を持つ一致する属性を持つメソッドが検索されます。ここでの秘訣は、メソッド属性でワイルドカードを使用してパラメーターをメソッドに渡すことができることです。2種類のファイルカードがあります

(.*) は、そのメソッドに文字列を渡すことを意味します (\d+) は、そのメソッドに int を渡すことを意味します。

When メソッドは一般的であるため、このようなパラメーターを使用して再利用できます。

    [When(@"they login in (\d+) days")]
    public void WhenTheyLoginInDays(int daysRemaining)
    {
        Account.DaysRemaining = daysRemaining;
    }

4: 最後に Assert を Then メソッドに追加して、最終結果が次のようになるようにします。(個人的には、機能の文言を少し再構成し、テスト ロジックが私の例ほど厄介ではない方法で期待される結果を渡すことに注意してください。データ ドリブン テストのシナリオの概要を参照してください)

    [Binding]
public class StepDefinition1
{
    UserAccount user;

    [Given(@"a user signs up for a 30 day account")]
    public void GivenAUserSignsUpForA30DayAccount()
    {
        user = AccountController.CreateNewUser("bob", "password", AccountType.Trial);
    }

    [When(@"they login in (\d+) days")]
    public void WhenTheyLoginInDays(int daysRemaining)
    {
        Account.DaysRemaining = daysRemaining;
    }

    [Then(@"they will (.*)")]
    public void ThenTheyWillBeLetIn(string expected)
    {
        //check to see which test we are doing and then assert to see the expected result.
        if(string.Compare(expected, "be let in", true)
            Assert.AreEqual(LoginResult.Passed, LoginService.Login);
        if(string.Compare(expected, "be asked to renew", true)
            Assert.AreEqual(LoginResult.Passed, LoginService.Login);

    }
}
于 2011-03-04T02:10:47.450 に答える
3

私は、 SpecFlow で相対的な日付と時刻を処理する方法について同様の問題に直面し、仕様内であいまいな日付をサポートすることで対処しました。この回答のコードを使用しました: Fuzzy Date Time Picker Control in C# .NET? 、これにより、次のように必要なものを表現できます。

バックグラウンド:
    ユーザーが 30 日間のアカウントにサインアップしたとします。

シナリオ: 有効期限が切れる前にアクセスする
    次の 29 日以内にログインしたとき
    その後、彼らは入れられます

シナリオ: 期限切れ後のアクセス
    次の 31 日以内にログインしたとき
    その後、更新を求められます

シナリオ: アカウント削除後のアクセス
    今後 2 年間にログインするとき
    次に、新しいアカウントを登録するように求められます

次のようなステップ定義を使用します。

[When(@"they login in the (.*)")]
public void WhenTheyLoginIn(string loginDateTimeString)
{
    DateTime loginDateTime = FuzzyDateTime.Parse(loginDateTimeString);

    // TODO: Use loginDateTime
}

あいまいな日付の構文が気に入らない場合は、FuzzyDateTime コードの正規表現を適切に変更できます。

于 2011-03-14T09:01:04.263 に答える
2

StepArgumentTransformationを探していると思います。

「31日以内」に対処するために、ドキュメントにはそれがあります:

[Binding]
public class Transforms
{
    [StepArgumentTransformation(@"in (\d+) days?")]
    public DateTime InXDaysTransform(int days)
   {
      return DateTime.Today.AddDays(days);
   }
}

そして「2年後」については、パターンを見ることができます...

    [StepArgumentTransformation(@"in (\d+) years?")]
    public DateTime InXYearsTransform(int years)
   {
      return DateTime.Today.AddYears(years);
   }
于 2016-11-11T17:38:03.493 に答える
1
> how can the same step definitions cope with both "31 days" and "2 years time"

ルールが就業日、クリスマス、週末などに特別な処理を必要としない場合は、@Nitro52の回答を次のように変更できます。

[When(@"they login in (\d+) days")]
public void WhenTheyLoginInDays(int daysRemaining)
{
    Account.RegristrationDate = DateTime.ToDay().SubtractDays(daysRemaining);
    Account.VerificationDate = DateTime.ToDay();    
}

たぶん、このようなシナリオの再構築について考えることもできます

Scenario: access before expiry
  When they login on '2010-01-01'
    And TodayIs '2010-01-29'
  Then they will be let in
于 2011-03-14T09:23:04.937 に答える
-2

Molesを使用して、DateTime.Now をスタブして、毎回同じ日付を返すようにしてください。Moles の優れた機能の 1 つは、あらゆるものに近いダンを、分離できるランタイム デリゲートに変換できることです。唯一の欠点は、選択した実装 (スタブとモール) によっては実行速度が遅くなる可能性があることです。私はそれに飛び込み始めたばかりなので、私の提案を一粒の塩で受け取ってください.

于 2011-04-06T13:25:14.780 に答える