【问题标题】:How can you avoid redundant call while waiting for element visibility在等待元素可见性时如何避免冗余调用
【发布时间】:2017-11-17 23:01:20
【问题描述】:

我目前有一个使用 WebdriverIO 的测试脚本,它点击一个按钮并等待弹出窗口显示。测试的目的是确保元素在单击后显示,但由于它是异步的,我必须等到它显示出来。

但是,如果我等到元素显示,如果 waitForVisible 成功,我的断言将始终通过。如果不成功,它总是会在 waitForVisible 命令上抛出异常,并且断言永远不会执行。

下面是代码示例:

browser.click(btnElement)
browser.waitForVisible(popupElement)
expect(browser.isVisible(popupElement)).to.be.true

是否有不同的方法来告诉期望语句重试/等待直到元素可见,这样断言就没有用了?

【问题讨论】:

  • 只需删除断言...正如您所说,它是多余的。
  • 但是没有断言的测试有什么用?

标签: selenium selenium-webdriver webdriver-io


【解决方案1】:

您似乎混淆了 assertions 的用途,或者滥用了它们,特别是在您的示例中。仅当您有事物WebElementtextattribute 元素等)要验证的确定性时,您才应该使用断言包含预期的值类型(您将其返回到您的assertexpect 语句以进行最终验证=> 输出是所需的值)。

断言验证 static 值,它们不会轮询 DOM。这就是为什么您拥有.waitForVisible()waitForText() 或更重要的.waitUntil()(提供更大的灵活性)之类的工具的原因。

诚然,ChaiJS 提供的 expect 断言样式可能有一个令人困惑的词汇(expect 可能会断章取义:它期望 WebElement 是可见的)。只需使用它们来验证不同命令的输出,而不是 WebElements 的状态或其他动态/变化的元素。


话虽如此,作为最佳实践,您应该始终将您的命令(例如:.click())包装到.waitUntil() 块中并确保@ 987654339@ 已准备好执行您即将执行的操作:

  • 是不是被前端逻辑渲染到了DOM中? (使用.isExisting()
  • 在 DOM 中是否可见? (您*不能点击viewport中不可见的元素)
  • 它是否可点击? (或您想要对其执行的其他操作...)

最后,一个惯用的动作(在我们的例子中是.click())应该是这样的:

browser.waitUntil(() => {
    browser.isExisting(locator);
}, timeout, "Oups! An error occured.\nReason: element ('" + locator + "') does not exist");
browser.waitUntil(() => {
    browser.isVisible(locator);
}, timeout, "Oups! An error occured.\nReason: element ('" + locator + "') is not visible");
browser.waitUntil(() => {
    browser.click(locator);
}, timeout, "Oups! An error occured.\nReason: element ('" + locator + "') could not be clicked");

您可以将整个内容封装到 custom-command 中,然后根据需要使用它。告别片状测试! :)

* Selenium 是一个以用户为中心的网络自动化工具,因此所有操作都像用户一样执行(用户不能点击不可见的元素,用户不能同时点击多个元素,或者通过输入整个单词或整个段落等来填写input字段)

【讨论】:

  • 如果我理解正确你是说你应该只使用断言/期望来验证值?但是我见过很多人使用断言来检查元素是否可见/可点击的例子。如果单击此按钮会创建一个包含未知内容的弹出窗口(通过 CMS?),那么我无法知道该值,但我仍然可以验证它是否已显示。是的,即使它是空的,它也会通过,但是我没有其他方法可以知道弹出窗口中将提供哪些内容。如果我只能断言已知值,我该如何为此编写测试?
  • 你的回答没有多大意义。为什么你需要断言你确定会通过的东西?这就是断言的全部意义,以确保它确实通过或没有通过时出错。我不知道您所说的 static 值是什么意思......如果值永远不会改变,那么断言它是没有意义的。这就像断言pi 仍然等于3.14.... 你永远不会那样做。总是在等待中包装命令并不是最佳实践。请张贴这样的链接。
  • 那票否决@JeffC :) 那是一个 d!$% 的举动!非常非常令人失望的态度男人。
  • @iamdanchiv 我明白你在说什么,但不能说我同意,特别是:“只需使用它们来验证不同命令的输出,而不是 WebElements 的状态。”如果页面上按钮的唯一目的是显示一些用户不知道的内容,为什么断言该元素的可见性是错误的?如果用户因为不可见而无法访问某个元素,那么这就是缺少将破坏我的用户体验的功能。我什至在文档中看到过这个例子:protractortest.org/#/…
  • @iamdanchiv 我确实喜欢将命令包装在等待语句中的想法,但我认为 WebdriverIO 应该能够通过框架内置的承诺链来解决异步命令?向每个命令添加等待语句不会增加套件的执行时间吗?
【解决方案2】:

我不知道 WebdriverIO,但我认为它类似于 try-catch。将您的等待包裹在try-catch 中。如果成功,Assert.pass() 或等效项。如果超时,将引发异常,因此在您的 catch 中为超时设置 Assert.fail() 或等效项。


我从未使用过 ChaiJS,但我确实查看了 the documentation 并发现了一些你应该可以使用的东西。

assert.isOk(false, 'this will fail');

这是来自文档,应该与我熟悉的 Assert.Fail() 相同。有人会假设以下稍作调整将等同于Assert.Pass()

assert.isOk(true, 'this will pass?');

如果由于某种原因这不起作用,您可以使用文档中的以下内容。

assert.isNotOk(false, 'this will pass');

【讨论】:

  • 这几乎概括了我对您的回答的感受:here。作为专业提示和高级提示,当您推销想法、解决方案、概念与某人辩论时,永远不要开头说你对你将要做出客观陈述的事情一无所知。看到这里的悖论,杰夫?!
  • @iamdanchiv 我使用 C# 和 Java Selenium。 WebdriverIO 是 Selenium 的语言组合,我没有在其中编程。这个概念仍然适用,不是吗?这是一个扩展到其他语言的编程概念。
  • @JeffC 我们已经实现了 try-catch 但不幸的是我们没有看到 ChaiJS 使用通过/失败函数。也许我在文档中错过了它。
  • @wco-lalka 我不知道 ChaiJS,但我确实查看了文档并发现了一些我认为您可以用作等价物的东西。我已经用文档中的一些示例更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
  • 2013-05-24
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
相关资源
最近更新 更多