【问题标题】:Intermittently failing tests with Protractor - promise order execution?Protractor 的测试间歇性失败 - 承诺订单执行?
【发布时间】:2017-08-11 16:09:50
【问题描述】:

我在一系列测试套件中面临间歇性量角器测试失败,在失败案例中没有任何真实模式来指示可能发生的情况,例如失败的测试不同。有时我会遇到很多失败,而在其他情况下只有一个失败案例。

我应该指出,这往往只会在我们配置的 Jenkins CI 服务器上执行测试运行时发生(在 linux 下运行)。在本地的 Windows 开发机器上,我们可能会在运行 30-40 次后遇到一个失败案例,我可以忍受!

我们正在测试的应用程序目前是使用 angular 1.5 构建的,我们正在使用 angular material 1.1.3

由于角材料中使用的动画和这些可能产生的性能影响,我们已经尝试按照这种方法禁用动画 here 这肯定会使测试更快,但对我们看到的失败案例没有帮助/

我现在正在反复运行一个测试套件,在成功运行 5 次后,它在我们的 Jenkins CI 环境\linux 机器上的第 6 次尝试失败,在本地我已经多次运行此测试并且还没有失败。

下面详细介绍了有问题的测试套件以及页面对象文件 sn-p:

//test suite
describe('Operators View', function () {
  var operatorPage = require('./operators.po.js'),
    loginView = require('../login/login.po.js'),
    page = new operatorPage();

  describe('Large screen tests', function () {
    beforeAll(function () {
      loginView.login();
    });

    afterAll(function () {
      loginView.logout();
    });

    it('should create an operator', function () {
      page.settlementBtn.click();
      page.operatorsBtn.click();
      page.fabBtn.click();
      page.createOperator();
      expect(page.headline.getText()).toEqual('Operators');
    });
    });
});

// operators.po.js
var operatorsSection = function() {
    this.helper = new Helpers();
    this.headline = element(by.css('.md-headline'));
    this.settlementBtn = element(by.css('[ui-sref="settlement"]'));
    this.operatorsBtn = element(by.css('[ui-sref="operators"]'));
    this.fabBtn = element(by.css('.md-fab'));

    // Form Elements
    this.licenceNumber = element(by.model('vm.transportOperator.licenceNumber'));
    this.tradingName = element(by.model('vm.tradingName'));
    this.name = element(by.model('vm.name'));
    this.operatorAddressFirstLine = element(by.model('vm.transportOperator.address.line1'));
    this.operatorAddressCityTown = element(by.model('vm.transportOperator.address.line5'));
    this.operatorAddressPostCode = element(by.model('vm.transportOperator.address.postcode'));
    this.payeeAddressFirstLine = element(by.model('vm.transportOperator.payee.address.line1'));
    this.payeeAddressCityTown = element(by.model('vm.transportOperator.payee.address.line4'));
    this.payeeAddressPostCode = element(by.model('vm.transportOperator.payee.address.postcode'));
    this.opID = element(by.model('vm.transportOperator.fields.opID'));
    this.spID = element(by.model('vm.transportOperator.fields.spID'));
    this.schemeSelect = element(by.model('reference.scheme'));
    this.schemeOptions = element(by.exactRepeater('scheme in vm.schemes').row('0'));
    this.alias = element(by.model('reference.alias'));
    this.reference = element(by.model('reference.reference'));
    this.saveBtn = element(by.css('.md-raised'));


    this.createOperator = function() {
      this.licenceNumber.sendKeys(this.helper.getRandomId(10));
      this.tradingName.sendKeys('Protractor Trade Name LTD');
      this.name.sendKeys('Protractor Trade Name');
      this.operatorAddressFirstLine.sendKeys('Protractor Town');
      this.operatorAddressCityTown.sendKeys('Cardiff');
      this.operatorAddressPostCode.sendKeys('PT4 4TP');
      this.payeeAddressFirstLine.sendKeys('Protractor Town');
      this.payeeAddressCityTown.sendKeys('Cardiff');
      this.payeeAddressPostCode.sendKeys('PT4 4TP');
      this.opID.sendKeys('177');
      this.spID.sendKeys('Protractor Spid');
      this.schemeSelect.click();
      this.schemeOptions.click();
      this.alias.sendKeys('PTAlias');
      this.reference.sendKeys('Protractor');
      this.saveBtn.click();
    }

  };
module.exports = operatorsSection;

在此测试套件中,从 PO 文件调用 createOperator 并单击 savteBtn 后,应用程序将转换到显示已创建条目表的状态(当然是在成功创建之后)。我们也在使用 angular ui-router,目前版本为 0.2.18

期望失败:

预期 'Create An Operator' 等于 'Operators'。

然而,捕获的随附屏幕截图显示了带有“操作员”标题的表格视图,似乎在期望调用中对 page.headline.getText() 的调用被调用得太快了,因此在创建项目的数据库操作之前和页面更改有机会完成吗?

我开始怀疑这是否可以归结为量角器执行的承诺顺序。我遇到过有关量角器中的控制流的文章,以及为什么在某些情况下您应该使用.then() 挂钩到量角器调用的承诺的结果 - 我找到了this

这让我想知道是否应该将调用移动到我的saveBtn.click(),这是在我的页面对象的createOperator 函数的末尾调用的,进入测试套件,所以这样做:

it('should create an operator', function () {
      page.settlementBtn.click();
      page.operatorsBtn.click();
      page.fabBtn.click();
      page.createOperator();
      page.saveBtn.click().then(function(){
        expect(page.headline.getText()).toEqual('Operators');
      });
    });

老实说,我在这里开始抓紧救命稻草,因此非常感谢来自社区的任何想法\建议。

谢谢!

【问题讨论】:

  • 似乎是时间问题。有时 Protractor 过早地询问标题文本是什么并且它正在获取旧页面。在转换到新页面时,我倾向于使用一个名为 waitForUrlToBeLike(x) 之类的辅助函数,它等待当前 url 包含 x。我发现量角器测试的稳定性取决于确保你等待事情如你所愿。
  • @preeve 听起来很有用,我可以试试,你能分享一下你目前使用的辅助函数吗?
  • 作为最佳实践,您可能希望减少在单个 it 块中执行的操作数量。为什么不能在每个click 之后做出断言?那些可以捕获的点击事件一定会有所改变,并有助于操纵控制流。
  • @Gunderson - 我猜你指的是我发布的测试 sn-p 中的settlementBtnoperatorsBtnfabBtn 点击?那些处理单击导航菜单项和操作按钮以使我进入用于填写输入字段的创建表单,所以是的,我可能可以在这里添加一些额外的断言来考虑它。当您说操纵控制流时,断言如何影响这一点?
  • @Gunderson - 使用 preeve 的等待 url 来改变方法,并在每次交互后添加断言,正如你所描述的,这对我有很大帮助,我在进行更改后多次运行没有任何失败- 非常感谢!

标签: angularjs jenkins protractor e2e-testing


【解决方案1】:

根据要求,这是我用来等待 URL 正常的函数。

public waitForUrlToBeLike (urlPart: string, timeout: number = 10000) {
    return browser.wait(() => {
        return browser.driver.getCurrentUrl().then((url) => {
            let regex = new RegExp(urlPart);
            return regex.test(url);
        });
    }, timeout);
}

我还经常使用以下方法来等待元素出现,然后再对它们进行断言:

public waitTillPresent (element: ElementFinder, timeout: number = 10000) {
    return browser.wait(() => {
        return element.isPresent();
    }, timeout);
}

【讨论】:

  • 谢谢你,我会试一试,听起来应该有帮助!
  • 这对我的失败案例很有帮助,一旦 http 操作解决了我在 Jenkins 盒子上看到的间歇性失败案例,点击按钮更改状态后等待 url 更改。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2018-11-09
  • 2018-11-11
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
  • 2017-11-22
  • 2016-12-14
  • 2021-05-27
相关资源
最近更新 更多