web-dev-qa-db-ja.com

AngularJSアプリの分度器テストの一貫性のない合格/不合格

私の分度器e2eテストは一貫して合格し、失敗しています。

これは、ここで説明するように、非同期のJavaScriptが原因である可能性があります。 分度器:ボタンをクリックした後、ページが完了するのを待つ方法は?

ただし、ここでは、分度器のテストが自動的に順次/同期的に実行されることが言及されています。 https://github.com/angular/protractor/issues/909

私のテストスクリプト:

describe('Login', function() {

  var ptor;

  beforeEach(function() {
    browser.get('https://127.0.0.1:8443');
    ptor = protractor.getInstance();
    element(by.id('splash')).click();
    browser.ignoreSynchronization = true;  // <-- to proceed beyond splash screen
  });

  describe('with correct email and password', function() {

    beforeEach(function() {
        element(by.id('email')).sendKeys('[email protected]');
        element(by.id('password')).sendKeys('adminpassword');
        element(by.id('loginButton')).click();
    });

    afterEach(function() {
        ptor.findElement(by.id('logout')).then(function(elem) {
            elem.click();
        });
    });

    it('does not show alert', function() {  // <-- sometimes passes, sometimes fails
        expect(browser.isElementPresent(by.css('.alert-danger'))).toBe(false);
    });

    it('changes route to /admin', function() {  // <-- sometimes passes, sometimes fails
        expect(browser.getCurrentUrl()).toMatch(/\/admin/);
    });
  });
});

上記の2つのテストでは、 両方のテストに合格します、または 1つまたは両方のテストが失敗する これらのメッセージで:

Failures:

1) Login with correct email and password does not show alert
Message:
  NoSuchElementError: no such element
...
==== async task ====
WebDriver.findElement(By.id("logout"))
...

または

Failures:

1) Login with correct email and password changes route to /admin
Message:
  NoSuchElementError: no such element
...
==== async task ====
WebDriver.findElement(By.id("logout"))
...

考え/助けていただければ幸いです。

18
ozandlb

私は以下に基づいて問題を解決することができました:

元の質問への Nguyen Vu Hoang のコメントで述べたように、私は純粋なAngularアプリを純粋な分度器と考えているものでテストしています(webdriver呼び出しはありません)。この場合、ptor.ignoreSynchronization = trueは必要ないはずですが、何らかの理由で、この設定がないとボタンクリックでテストが続行されません。

私の新しいスペック:

describe('Login', function() {

  var ptor;

  beforeEach(function() {
    ptor = protractor.getInstance();
    ptor.ignoreSynchronization = true;
    ptor.waitForAngular();
    ptor.get('https://127.0.0.1:8443');
    ptor.findElement(by.id('splash')).then(function(elem) {
        elem.click();
    });
  });

  describe('with correct email and password', function() {

    beforeEach(function() {
        ptor.findElement(by.id('email')).then(function(elem) {
            elem.sendKeys('[email protected]');
        });

        ptor.findElement(by.id('password')).then(function(elem) {
            elem.sendKeys('adminpassword');
        });

        ptor.findElement(by.id('loginButton')).then(function(elem) {
            elem.click();
        });
    });

    afterEach(function() {
        ptor.findElement(by.id('logout')).then(function(elem) {
            elem.click();
        });
    });

    it('does not show alert', function() {
        expect(ptor.isElementPresent(by.css('.alert-danger'))).toBe(false);
    });

    it('changes route to /admin', function() {
        expect(ptor.getCurrentUrl()).toMatch(/\/admin/);
    });
  });
});
18
ozandlb

テストをより安定させる別の手法もあります:明示的な待機と予期される条件docs )。

角張っていないページや、アニメーションが多数含まれているangularアプリケーションに対してテストするときに、期待される条件を使用すると特に便利であることがわかりました。

たとえば、クリックする前に要素がクリック可能になるまで待つことができます

_var EC = protractor.ExpectedConditions;
var link = element(by.id("mylink"));

browser.wait(EC.elementToBeClickable(link), "10000", "The link is still not clickable");
link.click();
_

以下のような他の組み込みの期待される条件もあります。

  • presenseOf()
  • visibilityOf()
  • alertIsPresent()
  • textToBePresentInElementValue()

また、カスタムの期待される条件、サンプルユースケースを簡単に記述できます。

combine Expected Conditions を使用してandorおよびnotを使用することもできます。例:

_var urlChanged = function() {
  return browser.getCurrentUrl().then(function(url) {
    return url != 'http://www.angularjs.org';
  });
};

// condition to wait for url to change, title to contain 'foo', and $('abc') element to contain text 'bar'
var condition = EC.and(urlChanged, EC.titleContains('foo'), EC.textToBePresentInElement($('abc'), 'bar'));
$('navButton').click();
browser.wait(condition, 5000); //wait for condition to be true.
_
8
alecxe

browser.ignoreSynchronization = true;すべてのテストにグローバルな効果があります。 falseに戻す必要がある場合があるため、分度器はangularがページのレンダリングを完了するのを待ちます。たとえば、2番目のbeforeEach関数の中または前に

4
nilsK