javascript 量角器测试不一致地通过/失败 AngularJS 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24946840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 03:38:09  来源:igfitidea点击:

Protractor tests inconsistently passing / failing for AngularJS app

javascriptangularjsasynchronousprotractor

提问by ozandlb

My Protractor e2e tests are inconsistently passing and failing.

我的量角器 e2e 测试不一致地通过和失败。

It seems this could be due to asynchronous javascript, as discussed here: Protractor : How to wait for page complete after click a button?.

似乎这可能是由于异步 javascript 所致,如下所述: 量角器:单击按钮后如何等待页面完成?.

However, here it's mentioned that Protractor tests automatically execute sequentially / synchronously: https://github.com/angular/protractor/issues/909

但是,这里提到量角器测试自动按顺序/同步执行:https: //github.com/angular/protractor/issues/909

My test script:

我的测试脚本:

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

In the two tests above, either both tests will pass, or one/both of the tests will failwith these messages:

在上面的两个测试中,要么两个测试都通过,要么一个/两个测试都失败并显示以下消息:

Failures:

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

or

或者

Failures:

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

Thoughts / help much appreciated.

非常感谢您的想法/帮助。

采纳答案by ozandlb

I was able to resolve the issue based on the following:

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

As mentioned by Nguyen Vu Hoang's comment to the original question, I am testing a pure Angular app with what I think is pure Protractor (no webdriver calls). I know ptor.ignoreSynchronization=true should not be required in this case, but for some reason, the tests are not proceeding at button click without this setting.

正如Nguyen Vu Hoang对原始问题的评论所提到的,我正在测试一个纯 Angular 应用程序,我认为它是纯量角器(没有 webdriver 调用)。我知道在这种情况下不应该需要 ptor.ignoreSynchronization=true,但是由于某种原因,如果没有此设置,则不会在单击按钮时进行测试。

My new spec:

我的新规格:

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

回答by alecxe

There is also an another technique to make your tests more stable: Explicit Waits and Expected Conditions(docs).

还有另一种技术可以使您的测试更加稳定:显式等待和预期条件( docs)。

I've found using Expected Conditions especially useful when testing against non-angular pages or angular applications that have a lot of animations involved.

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

For example, you can wait for an element to be clickablebefore making a click:

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

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

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

There are also other built-in Expected Conditions, such as:

还有其他内置的预期条件,例如:

  • presenseOf()
  • visibilityOf()
  • alertIsPresent()
  • textToBePresentInElementValue()
  • etc
  • presenseOf()
  • visibilityOf()
  • alertIsPresent()
  • textToBePresentInElementValue()
  • 等等

And, it is easy to write a custom Expected Condition, example use case:

而且,编写自定义预期条件很容易,示例用例:

You can also combine Expected Conditionsusing and, orand not, e.g.:

您还可以使用,和组合预期条件,例如: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.

回答by nilsK

browser.ignoreSynchronization = true; has a global effect for all your tests. you may have to set it back to false, so protractor waits for angular to be finished rendering the page. e.g. in or before your second beforeEach function

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