【问题标题】:Protractor proper way to use browser.wait to control flow of tests量角器使用 browser.wait 控制测试流程的正确方法
【发布时间】:2018-12-31 03:54:38
【问题描述】:

我已经为 browser.wait 编写了一些函数。我的问题是当我运行测试时,由于量角器运行太快,它们不一致地通过。为了解决这个问题,我使用了 browser.sleep。这有效,但效率不高。例如,如果我的连接速度很慢,这些 browser.sleep 语句可能会变得不可靠。所以我开始使用browser.wait。这是我使用的等待函数的示例。

EC = Expected Conditions;
myForm = element(by.id('myForm');
button1 = element(by.id('btn1');
waitForBtn = this.EC.elementToBeClickable(button1)
formIsVisible = this.EC.visibilityOf(myForm)

//Test
it(should click the button and bring up the form), () => {
    browser.wait(page.waitForBtn, 3000);
    page.button1.click()
    browser.wait(page.formIsVisible, 3000);
    expect(page.getMyForm().isDisplayed).toBeTruthy(); 

此测试可以单独运行,但与其他测试结合使用时,有时测试会失败并返回错误"element" is not clickable at point...。即使使用这些等待功能,我也会收到此错误。它似乎总是用于单击元素时。

我的问题是:在运行多个测试时,量角器等待的最佳方式是什么,以免量角器执行测试过快而错过元素?谢谢。 编辑: 这是解决方案。

点击元素的辅助函数。

 async function sendClick(el: ElementFinder): Promise<void> {
    try {

      let result = await forCondition(function() { return el.isDisplayed() });
      if(!result || !await el.isEnabled()) {
        throw new Error('element disabled');
      }

      await browser.executeScript('arguments[0].click();', el.getWebElement());
    } catch(error) {
      console.warn('element:', el.locator().toString(), 'is not clickable', error.message);
    }
  }

export async function forCondition(condition: () => any | PromiseLike<boolean>, timeout = 20000): Promise<boolean> {
try {
  return await browser.wait(condition, timeout);
} catch (err) {
  console.log('Condition: false');
  return false;
}

}

【问题讨论】:

    标签: protractor


    【解决方案1】:

    我不能告诉你最好的方法,但这是一种方法:)

    通常,element" is not clickable at point... 之类的错误是在元素与另一个元素重叠或尚未完成渲染时引起的。

    1) 为防止element is not clickable 错误,您应该使用javascript 进行点击。一个缺点是元素总是被点击。意味着您必须手动检查元素是否可点击,并且只有在可点击的情况下才应点击。 一个“正确的”点击函数可能如下所示:

    async function sendClick(el: ElementFinder): Promise<void> {
      try {
    
        // forCondition() is a custom function and listed below..
        let result = await forCondition(function() { return el.isDisplayed() });
        if(!result || !await el.isEnabled()) {
          throw new Error('element disabled');
        }
    
        // click via javascript
        await browser.executeScript('arguments[0].click();', el.getWebElement());
      } catch(error) {
        console.warn('element:', el.locator().toString(), 'is not clickable', error.message);
      }
    }
    

    上面的函数等待元素被显示,如果它被启用就点击它。

    这里是辅助函数::

    forCondition() 等待条件完成。您不能向forCondition() 添加更多逻辑以确保页面已加载(假设直到微调器消失或类似的东西。)

    export async function forCondition(condition: () => boolean | PromiseLike<boolean>, timeout = 20000): Promise<boolean> {
      try {
        // add function which waits until page is loaded here..
        return await browser.wait(condition, timeout);
      } catch (err) {
        logger.silly('Condition: false');
        return false;
      }
    }
    

    在测试中它看起来如下:

    it('should click element', async function() {
      let button = element(by.id('myButton');
    
      // it's waited until button appears and clicks it if possible.
      await sendClick(button);
    });
    

    如果您总是使用这些辅助函数,您可以轻松添加等待页面加载或其他自定义逻辑的检查。

    如果有什么不清楚的地方请告诉我。

    【讨论】:

    • 啊,我明白了,谢谢。我目前正在使用 Angular 6。在为 sendClick 编写函数时,我在let result = await forCOndition(function(){el.isDisplayed()} 行收到打字稿错误;该错误指出类型“void”不可分配给类型“boolean |”。 PromiseLike'
    • 啊,是的。我们通常使用箭头函数。有了他们,你不需要写回报。所以这就是你想要的函数let result = await forCOndition(function(){return el.isDisplayed()}); 使用箭头函数,它看起来如下:let result = await forCondition(() =&gt; el.isDisplayed()); 我调整了 asnwer,
    • 再次感谢您。我仍然无法兑现承诺。我现在收到一个类似的错误,说 Type 'Promise&lt;boolean&gt;' is not assignable to type PromiseLike&lt;boolean&gt;. 我更新了我的问题将是完整的错误。
    • 好的,请尝试更改forCondition()的类型如下::export async function forCondition(condition: () =&gt; boolean | PromiseLike&lt;boolean&gt; | Promise&lt;boolean&gt;, timeout = 20000): Promise&lt;boolean&gt; { // ... }我添加了类型Promise&lt;boolean&gt;。如果这不起作用,请尝试在不输入的情况下使用该功能。如果没有它们也能工作,你必须找出正确的类型:)对我来说,它就是这样工作的......
    • 根据您的建议,我从 forCondinition 函数的 Promise 中删除了 boolean 类型。它看起来像这样:export async function forCondition(condition: () =&gt; any | PromiseLike&lt;boolean&gt;... 谢谢!现在我的测试效率提高了一百万倍。
    猜你喜欢
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2018-05-05
    • 1970-01-01
    • 2014-07-20
    相关资源
    最近更新 更多