【问题标题】:Explicit waits for isPresent and isDisplayed result in no element found fail显式等待 isPresent 和 isDisplayed 导致找不到元素失败
【发布时间】:2015-12-11 15:47:39
【问题描述】:

这将是一个很长的问题:p
我有这个测试失败了大约 50% 的时间,“未找到元素”失败,即使我明确等待 element.isPresent 和 element.isDisplayed 并等待每个承诺得到解决,基本上消除了任何异步性。

基本上,场景如下:用户将鼠标悬停在表格单元格上,出现一个标注(我的意思是创建而不仅仅是使其可见),如下所示:

用户然后单击编辑按钮,调用变为:

用户输入一些文本,单击保存按钮并看到调用框中的值已更新。用户重复该操作,但这次单击取消按钮并看到更改的值已被丢弃。
除此之外,我所做的是保存初始值并重复“悬停并编辑”操作以使单元格的内容恢复到运行测试之前的状态。

代码如下:
规格:

var editMemoBoxAction = function(box){
 var data = page.editMemoBox(box,'',false);
 return data.then(function(backup){
  if(backup == 'No data.') backup = '';
  expect(page.editMemoBox(box,'abc',true)).toEqual('abc');
  expect(page.editMemoBox(box,'xyz',false)).toEqual('abc');
  return page.editMemoBox(box,backup,true);
 });
};

it('does stuff', function(){
 page.mouseOver('Future Contract Action').then(function(){
  editMemoBoxAction('Future Contract Action').then(function(){
   page.mouseOver('Future Contract Action');
  });
 });
});

页面对象:

this.mouseOver = function(box){
var headers = element.all(by.xpath('//table/thead/tr/th')).map(function(elm){
  return elm.getText();
});
return headers.then(function(list){
  if(list.length == 0) return undefined;
  var elm = element(by.xpath('//table/tbody/tr[1]/td[' + (list.indexOf(box) + 1) + ']'));
  return browser.actions().mouseMove(elm).perform().then(function(){
    return true;
  });
});


};

this.editMemoBox = function(box, value, save){

var headers = element.all(by.xpath('//table/thead/tr/th')).map(function(elm){
  return elm.getText();
});
return headers.then(function(list){
  if(list.length == 0) return undefined;
  var timeout = 10000;
  var text = element(by.xpath('//div[@class=\'popover-content\']/div/div/div[1]')); // CONTAINS THE INITIAL TEXT VALUE OF THE CALL OUT
  return browser.wait(function(){return text.isPresent;}, timeout).then(function(){
    return browser.wait(function(){return text.isDisplayed;}, timeout).then(function(){
      return text.getText().then(function(backup){
        if (backup == 'No data.') backup = '';
        var button = element(by.xpath('//div[@class=\'popover-content\']/div/div/div[2]')); // THE EDIT BUTTON
        return browser.wait(function(){return button.isPresent;}, timeout).then(function(){
          return browser.wait(function(){return button.isDisplayed;}, timeout).then(function(){
            return button.click().then(function(){
              var edit = element(by.model('data.editValue')); // THE EDITABLE TEXT AREA
              return browser.wait(function(){return edit.isPresent;}, timeout).then(function(){
                return browser.wait(function(){return edit.isDisplayed;}, timeout).then(function(){
                  return edit.clear().then(function(){
                    return edit.sendKeys(value).then(function(){
                      var confirm; // EITHER THE SAVE OR CANCEL BUTTON
                      if(save == true){
                        confirm = element(by.xpath('//span[@class=\'glyphicon glyphicon-ok glyphicon-lg\']'));
                      }
                      else {
                        confirm = element(by.xpath('//span[@class=\'glyphicon glyphicon-remove glyphicon-lg\']'));
                      }
                      return browser.wait(function(){return confirm.isPresent;}, timeout).then(function(){
                        return browser.wait(function(){return confirm.isDisplayed;}, timeout).then(function(){
                          return confirm.click().then(function(){
                            var result = element(by.xpath('//div[@class=\'popover-content\']/div/div/div[1]')); // THE NEW VALUE OF THE CALL OUT
                            return browser.wait(function(){return result.isPresent;}, timeout).then(function(){
                              return browser.wait(function(){return result.isDisplayed;}, timeout).then(function(){
                                return result.getText();
                              });
                            });
                          });
                        });
                      });
                    });
                  });
                });
              });
            });
          });
        });
      });
    });
  });
});

};

这非常难看,因为我尝试了一切以消除代码中任何地方存在的任何异步性,因为我的问题绝对是时间问题,而我正处于这个烦人事情的第二天。
可能值得将代码复制到为其着色的文本编辑器中。

现在,它不应该有任何时间问题,因为在每次与元素交互之前,我都会明确等待 element.isPresent 和 element.isDisplayed 并且在每一个承诺出现的时候,我都会等待它得到解决,然后再做任何其他事情.

它现在所做的是在我正在与之交互的元素之一(每次都不是同一个)处失败并显示“未找到元素”。大约有 50% 的时间通过。

如果我可以更清楚地说明这一点,请告诉我。

我知道阅读量很大,但这不是一个有趣的问题,就是我很笨,两者都应该很有趣:p

谢谢!

【问题讨论】:

  • 哦,我的眼睛,很想知道所呈现代码的“圈复杂度”和“可维护性指数”是什么? :)

标签: javascript asynchronous jasmine promise protractor


【解决方案1】:

我会尝试的事情:

【讨论】:

  • Angular 和 CSS 动画都已禁用。隐式等待超时已经是 10 秒。一旦我确定了问题的根源,肯定会进行重构:p
  • @Vlad 好的,您可以增加隐式超时值。用更多选项更新了答案。顺便说一句,这是特定于浏览器的,还是您可以在不同的浏览器上重现它?
  • @Vlad 添加了一个选项。
  • @alexcxe 它在 Firefox 上也失败了。 isElementPresent 确实做了一些事情,它实际上等待并在超时后失败。似乎鼠标随机变为“未结束”,但现在我实际上可以看到它正在发生。因此,我会接受您的回答,至少我知道问题出在哪里。 mouseOver 动作实际上就像一个切换,所以我不确定如何在调用 mouseOver 之前检查鼠标是否结束。感谢您迄今为止的帮助!
猜你喜欢
  • 2020-12-26
  • 2021-04-05
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
相关资源
最近更新 更多