机器人框架+ Selenium:如何避免"陈旧元素"错误(片状测试)?

时间:2018-01-25 18:03:13

标签: selenium robotframework

我使用Robot Framework和Selenium来测试具有语言选择器的网站。我需要能够选择一种语言,然后验证页面实际上是否已更改为该语言。

由于在选择新语言后,lang标记的<html>属性中的值发生了变化,我决定使用它来验证语言是否已成功更改。但是我得到了不稳定的结果,因为我的测试有时会过去,有时候也没有。

这是关键字I&m; m的定义:

CHANGE LANGUAGE  
  [Arguments]                        ${lang}
  Select From List By Value          ${LANGUAGE SWITCH}  ?hl=${lang}
  Wait Until Page Contains Element   css=html
  ${doc lang}                        Get Element Attribute  css=html@lang
  Should Be True                     '${doc lang}'=='${lang}'   timeout=15s

由于我必须执行此关键字很多次(每种可用语言一个),因此我经常会遇到可怕的过时元素&#34;错误:| FAIL | stale element reference: element is not attached to the page document

我在这里阅读了this article和其他一些问题,并了解如果在获取元素引用后更新它,可能会发生这种情况。但是,我不确定我应该如何修改我的关键字以避免出现此错误。

4 个答案:

答案 0 :(得分:4)

为了在用户操作(例如点击链接或按钮)之后等待页面准备好进行测试,我发现似乎几乎是防弹的算法是:

  1. 获取对html元素的引用
  2. 执行将导致页面更改的操作(例如:单击链接或按钮)
  3. 等待html元素过时 - 这表示刷新已经开始
  4. 等待document.readyState成为"complete"
  5. 步骤4可能没有必要,但它并没有受到伤害。

    这对我的团队非常有效。这可能仍会失败,因为您可能有一些在设置document.readyState后运行的异步javascript,但是根本没有通用的解决方案。

    如果您的网页上有一堆异步javascript,那么您必须提出自己的方案,以了解该网页何时最终可以进行测试。例如,要完成的最后一个作业可以设置一个标志,或者您可以等到没有待处理的异步作业等。

    我不确定您是否可以使用机器人关键字执行上述操作,因为它依赖于selenium staleness_of条件。不过,在python中实现起来相当容易。

    此解决方案的灵感来自此博文:How to get Selenium to wait for page load after a click

    如果您将page object library用于机器人,则会将其作为上下文管理器内置。

答案 1 :(得分:2)

如突出显示的那样,Stale Element错误通常意味着在元素检索和元素更改的相应操作之间。通常这是由于页面刷新。

因此,投资强大的等待方法非常重要。不要猜测你的页面/应用程序已经完成加载,而是知道它已经完成了。这不仅可以防止Stale Element错误,还可以加速您的测试,因为您没有不必要的等待。

由于Get Element Attribute ${DOCUMENT}@lang导致陈旧元素错误而Select From List By Value ${LANGUAGE SWITCH} ?hl=${lang}导致页面刷新,因此Wait Until Page Contains Element html将等待您的等待。

由于<html>标记始终存在且第一个要加载到DOM中,因此这不是等待的最佳标记。我会为加载的页面或该页面的最后一个元素建议一些独特的东西。虽然我必须强调这仍然构成猜测页面已加载。

最好投资强大的等待方法。特别是如果你的应用程序使用像Angular,React或jQuery这样的框架,那么你有几个Javascript标记可以帮助你解决这个问题。对于某些框架,甚至还有支持其特定标记的自定义Robot Framework库。

如果您的应用程序不使用框架,请与您的开发人员交谈并让他们为您开发。最简单的是一个可见的微调器,但返回True的Javascript函数也可以正常工作。

答案 2 :(得分:2)

使用每个人都非常友好提供的信息,我可能已经找到了一个潜在的修复方法(不确定它是否足够强大,不再抛出异常,但经过几次测试后它们全部通过了):我添加了一个“等到关键字成功“并将语言验证移到新关键字:

VALIDATE PAGE LANGUAGE
  [Arguments]                        ${lang}
  ${doc lang}                        Get Element Attribute  css=html@lang
  Should Be True                     '${doc lang}'=='${lang}'

CHANGE LANGUAGE  
  [Arguments]                        ${lang}
  Select From List By Value          ${LANGUAGE SWITCH}  ?hl=${lang}
  Wait For Condition                 return document.readyState=="complete"
  Wait Until Keyword Succeeds        5  5s  VALIDATE PAGE LANGUAGE  ${lang}

然后我将这个“CHANGE LANGUAGE”关键字称为我需要测试的语言的次数。

我将此作为答案而不是评论添加,因此我可以以更易读的方式显示代码。

答案 3 :(得分:0)

当我想单击某个元素或执行某个动作时,我会创建一个自定义关键字,我将其称为该自定义关键字。此自定义关键字使用内置关键字“等待关键字成功”,该关键字将运行指定的关键字,并在失败时重试。通过此内置关键字,可以配置上次运行失败后重试的次数和尝试再次运行该关键字之前的等待时间。

此自定义关键字将调用另一个自定义关键字,其中将调用三个SeleniumLibrary关键字。第一个将等待直到元素定位器启用关键字,然后将等待直到元素未禁用或只读。启用该元素后,将把焦点放在要执行操作的元素上。最后执行操作。所有这些预防措施使我避免了Stale Element错误。

HighLevelKeyword_Identify And Click Element
        [Arguments]    ${locator}
        Wait Until Keyword Succeeds    ${RETRY_ATTEMPTS}    ${RETRY_AFTER}    Identify And Click Element    ${locator}

Identify And Click Element
    [Arguments]    ${locator}
    Wait Until Element Is Enabled    ${locator}
    Set Focus To Element    ${locator}
    Click Element    ${locator}