量角器测试AngularJS app的传递/失败不一致

时间:2014-07-25 01:52:41

标签: javascript angularjs asynchronous protractor

我的量角器e2e测试不一致传递和失败。

这似乎可能是由于异步javascript,如下所述: Protractor : How to wait for page complete after click a button? 的。

但是,这里提到了Protractor测试自动顺序/同步执行: 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('admin@email.com');
        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/);
    });
  });
});

在上面的两个测试中,两个测试都将通过,或者一个/两个测试都将失败这些消息:

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"))
...

思考/帮助非常感谢。

3 个答案:

答案 0 :(得分:17)

我能够根据以下内容解决问题:

Nguyen Vu Hoang对原始问题的评论所述,我正在测试一个纯粹的Angular应用程序,我认为它是纯粹的Protractor(没有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('admin@email.com');
        });

        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/);
    });
  });
});

答案 1 :(得分:8)

还有另一种技术可以让您的测试更稳定: Explicit Waits and Expected Conditions docs)。

我发现使用预期条件在对非角度页面或涉及大量动画的角度应用程序进行测试时尤其有用。

例如,您可以在点击之前等待元素可点击

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使用andornot,例如:

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.

答案 2 :(得分:4)

browser.ignoreSynchronization = true;对所有测试都有全局影响。您可能必须将其设置为false,因此量角器等待角度完成渲染页面。例如在你的第二个beforeEach函数之前或之前