6

最近、同僚と私は、Protractor と Chai as Promised を使用して Cucumber のステップ定義を実装する「正しい」方法について意見の相違がありました。私たちの主張は、Cucumber のコンテキストでのプロミス解決で正確に何が起こっているのかを相互に理解していないことに起因しています。

AngularJS アプリケーションに対してテストしているため、promise と非同期動作の解決は必要悪です。私たちが経験した最大の問題は、同期テスト動作を強制し、Cucumber にステップ定義間の promise を待機させることです。場合によっては、Cucumber が Webdriver がステップ定義を実行する前にステップ定義を真っ直ぐ進んでいるように見える状況を観察しました。この問題に対する私たちの解決策はさまざまです...

架空のシナリオを考えてみましょう:

Scenario: When a user logs in, they should see search form
  Given a user exists in the system
  When the user logs into the application
  Then the search form should be displayed

混乱のほとんどは、Then ステップで発生します。この例では、定義は、検索フォームのすべてのフィールドがページに存在することをアサートする必要があります。つまり、複数の isPresent() チェックを意味します。

見つけたドキュメントと例から、アサーションは次のようになるはずだと感じました。

this.Then(/the search form should be displayed/, function(next) {
    expect(element(by.model('searchTerms')).isPresent()).to.eventually.be.true;
    expect(element(by.model('optionsBox')).isPresent()).to.eventually.be.true;
    expect(element(by.button('Run Search')).isPresent()).to.eventually.be.true.and.notify(next);
});

ただし、私の同僚は、約束の解決を満たすためには、次のように then() で期待値を連鎖させる必要があると主張しています。

this.Then(/the search form should be displayed/, function(next) {
    element(by.model('searchTerms')).isPresent().then(function(result) {
        expect(result).to.be.true;

    }).then(function() {
        element(by.model('optionsBox')).isPresent().then(function(result) {
            expect(result).to.be.true;

        }).then(function() {
            element(by.button('Run Search')).isPresent().then(function(result) {
                expect(result).to.be.true;
                next;
            });
        });
    });
});

後者は私には本当に間違っているように感じますが、前者も正しいかどうかはよくわかりません。私が最終的に理解する方法は、先に進む前に約束が解決するのを待つという点で、then() と同様に機能するということです。前の例では、各 expect() 呼び出しを順番に待機し、最後の expect() で notify() を介して next() を呼び出して、cucumber に次のステップに進むように通知することを期待します。

さらに混乱を招くことに、他の同僚が次のように予想を書いているのを観察しました。

expect(some_element).to.eventually.be.true.then(function() {
    expect(some_other_element).to.eventually.be.true.then(function() {
        expect(third_element).to.eventually.be.true.then(function() {
            next();
        });
    });
});

したがって、私がほのめかしていると思う質問は次のとおりです。

  • 上記のいずれかはちょっと正しいですか?
  • 最終的に()は実際に何をしますか?then() のような同期動作を強制しますか?
  • and.notify(next) は実際に何をしますか? then() 内で next() を呼び出すのとは違いますか?
  • これについてより明確にする、まだ見つかっていないベスト プラクティス ガイドはありますか?

よろしくお願いします。

4

2 に答える 2

4
  • あなたの感覚は正しかったのですが、あなたの同僚は間違っていました (もっともな間違いでしたが!)。分度器は、1 つの WebDriver コマンドが解決されるのを自動的に待ってから、2 番目のコマンドを実行します。したがって、2 番目のコード ブロックでelement(by.button('Run Search')).isPresent()は、両方が完了するまで解決されませelement(by.model('optionsBox')).isPresent()element(by.model('searchTerms')).isPresent()
  • eventually約束を解決します。説明はこちら: https://stackoverflow.com/a/30790425/1432449
  • next()中に入れるのと変わらないと思いますthen()
  • ベスト プラクティス ガイドがあるとは思えません。キュウリは分度器チームの中心的な焦点ではなく、そのサポートは主に github のコミュニティによって提供されています。あなたまたはあなたが知っている誰かがベスト プラクティス ガイドを書きたい場合は、私たち (分度器チーム) は PR を歓迎します!
于 2015-07-13T21:25:49.367 に答える
0

私にとってうまくいくのはこれです.htmlタグが存在する場合、以下の関数は常にtrueになるものを検索します。各テストの最後にこの関数を呼び出し、コールバックを渡します

function callbackWhenDone(callback) {
    browser.wait(EC.presenceOf(element(by.css('html'))))
        .then(function () {callback();})
}

これは、簡単なテストでの使用法です。

this.Given(/^I go on "([^"]*)"$/, function (arg1, callback) {
    browser.get('/' + arg1);
    callbackWhenDone(callback);
});

私が知っているちょっとしたハックですが、それは仕事を成し遂げ、どこでも使用するとかなりきれいに見えます

于 2016-08-16T03:45:51.420 に答える