13

次のようなコードがあります。

ExamPage.prototype.enterDetailsInputData = function (modifier) {
    page.sendKeys(this.modalExamName, 'Test Exam ' + modifier);
    page.sendKeys(this.modalExamVersionId, 'Test exam version ' + modifier);
    page.sendKeys(this.modalExamProductVersionId, 'Test exam product version ' + modifier);
    page.sendKeys(this.modalExamAudienceId, 'Test exam audience ' + modifier);
    page.sendKeys(this.modalExamPublishedId, '2014-06-1' + modifier);
    page.sendKeys(this.modalExamPriceId, '100' + modifier);
    page.sendKeys(this.modalExamDurationId, '6' + modifier);
};

これが page.sendKeys 関数です。現在、これは約束の返却などを行っていないことに注意してください。関数がうまくコーディングされていない場合は、コメントを歓迎します。

// page.sendkeys function
sendKeys(id: string, text: string) {
    element(by.id(id)).sendKeys(text);
} 

画面の各フィールドにゆっくりと入力し、その後のテストで何度も繰り返します。

これを最適化する方法はありますか、それともフィールドが次々と入力されるのを待って、実行に時間がかかるテストを実行する必要がありますか?

sendKeys は約束ベースだと思います。たとえば、AngularJS $qを使用してすべての sendKey を同時に発行し、$q を使用してそれらが完了するのを待つことはできますか?

4

5 に答える 5

11

考えられる解決策どのように最適化しても、少なくとも少しハッカーが必要だと思います。分度器は、すぐに使用できるわけではありません。しかし、このような小さなヘルパー関数はあなたのニーズに合っていますか? text inputサイドs をs でスピードアップするには、他に何が必要ng-modelですか?

function setNgModelToString(element, value) {
    return element.getAttribute('ng-model').then(function (ngModel) {
        element.evaluate('$eval("' + ngModel + ' = \'' + value + '\'") && $digest()');
    });
}

ソリューション例:

describe('angularjs homepage', function() {
  it('should have a title', function() {
    browser.get('http://juliemr.github.io/protractor-demo/');

    var inputString1 = '';
    var inputString2 = '';
    for (var i = 0; i < 1000; i++) {
        inputString1 += '1';
        inputString2 += '2';
    }

    /* Uncomment this to see it runs much much slower when you enter each key. */
    //element(by.model('second')).sendKeys(inputString1);   

    setNgModelToString(element(by.model('second')), inputString2);

    expect(element(by.model('second')).getAttribute('value')).toEqual(inputString2);
  });
});

ソリューションが機能する理由

副作用を評価しないため$eval、割り当てだけでなく、割り当てをラップするために使用する必要があります(ネストされた評価ですが...へえ)。evaluate角度式でそれが真実であると仮定すると、 ;$digest()から呼び出されます。&&これによりダイジェストが発生します。ダイジェスト サイクルの外から値を設定するため、すべてを更新する必要があります。

解決策についての考え:

E2E テストの背後にある全体的な考え方は、アプリを使用するエンドユーザーを「エミュレート」することです。これは間違いなく、キーを 1 つずつ送信したり、コピーして貼り付けたりするのと同じようには行われません (要素への貼り付けは、入力を入力する有効な方法であるためです。フラッシュなどのために設定が難しいだけです。 、 下記参照)。

その他の潜在的な解決策:

  • コピーと貼り付け:要素を作成し、テキストを入力してコピーし、Ctrl + V をターゲット要素に送信してテキストを貼り付けます。これには、Flash を使用したり (システム クリップボードを公開することはセキュリティ上のリスクがあります)、目に見えない Flash Player をクリックして「コピー」するなど、多くの高度なフットワークが必要になる場合があります。必要に応じてexecuteScript変数にアクセスできるように、ターゲットで関数を評価する方法を参照してください。window

  • テストの並列化。こちら の公式ドキュメントを読み、「シャード」を検索してから「複数」を検索してください。個々のテストではなく、テスト コレクション全体の所要時間を主に気にしている場合は、ブラウザー数をスケールアウトするのがおそらく最善の方法です。ただし、TDD を行っている可能性が高いため、各テストをより高速に実行する必要があります。

于 2014-09-09T08:40:13.137 に答える
2

何らかの方法で DOM を操作するプロセス (データ フォームの入力を含む) を本当にスピードアップしたい場合、考慮すべきオプションの 1 つは、browser.executeScriptまたはを使用することですbrowser.executeAsyncScript。そのような場合、webdriverブラウザにスクリプトを単独で実行させます。唯一のオーバーヘッドは、スクリプト本体をブラウザに送信することです。したがって、これより高速なものはないと思います。

私が見たところ、DOM 要素をids で識別しているので、私が提案するアプローチでスムーズに動作するはずです。

これがその足場です - テストしたところ、正常に動作します:

browser.get('someUrlToBeTested');
browser.waitForAngular();
browser.executeScript(function(param1, param2, param3){

        // form doc: arguments may be a boolean, number, string, or webdriver.WebElement
        // here all are strings: param1 = "someClass", param2 = "someId", param3 = "someModifier"
        var el1 = document.getElementsByClassName(param1)[0];
        var el2 = document.getElementById(param2);

        el1.setAttribute('value', 'yoohoo ' + param3);
        el2.setAttribute('value', 'hooyoo ' + param3);

        // depending on your context it will probably
        // be needed to manually digest the changes
        window.angular.element(el1).scope().$apply();


},'someClass', 'someId', 'someModifier')

ちょっとした注意: 引数の 1 つとして渡すwebdriver.WebElementと、対応する にキャストダウンされDOM elementます。

于 2014-09-09T10:53:39.297 に答える