Geb的一般问题(StaleElementReferenceException和等待超时) [英] General Problems With Geb (StaleElementReferenceException & Wait Timeouts)

查看:255
本文介绍了Geb的一般问题(StaleElementReferenceException和等待超时)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Geb书,我开始映射我们门户的网页。我更喜欢使用静态内容关闭块中定义的变量,然后在页面方法中访问它们:

According to the "Book of Geb" I started to map our portal's web pages. I prefer to use variables defined within static content closure block and accessing them afterwards in page methods:

static content = {
    buttonSend { $("input", type: "submit", nicetitle: "Senden") }
}
def sendLetter() {
    waitFor { buttonSend.isDisplayed() }
    buttonSend.click()
}

不幸的是,有时候我得到一个Geb等待超时例外(60秒以后),甚至更糟糕的是我收到了众所周知的StaleElementReferenceException。

Unfortunately, sometimes I get an Geb waiting timeout exception (after 60 secs) or even worse I receive the well known "StaleElementReferenceException".

我可以避免使用isEnabled而不是isDisplayed的等待超时对于StaleElementReferenceException,我只能应用以下解决方案:

I could avoid the wait timeout when using "isEnabled" instead of "isDisplayed" but for the "StaleElementReferenceException" I could only apply the below solution:

def sendLetter() {
    waitFor { buttonSend.isEnabled() }
    try {
        buttonSend.click()
    } catch (StaleElementReferenceException e) {
        log.info(e.getMessage())
        buttonSend.click()
    }
}

我猜,这个解决方案不是很好,但是我无法按照另一篇文章的描述应用一个明确的等待。因此,我有一些一般的问题:

I guess, this solution is not really nice but I could not apply an explicitly wait as described in another article. Thus, I have some general questions:


  • 我们应该避免在网页动态时使用静态内容定义吗?

  • Geb在什么时间或事件刷新其DOM?如何触发DOM刷新?

  • 为什么在使用CSS选择器时仍然会收到StaleElementReferenceException?

我希望有助于理解或解决这个问题的每一个提示。最好的是有一个简单的代码示例,因为我还是一个初学者。谢谢!

I would appreciate every hint which helps to understand or to solve this issue. The best would be to have a simple code example since I'm still a beginner. Thank you!

推荐答案

除了twinj的答案,我想指出一些其他解决方法,以防遇到一个StaleElementReferenceException。

In addition to twinj's answer, I would like to point out a couple of other workarounds in case you encounter a StaleElementReferenceException.


  1. 我经常会发现手动写出选择器更好,而不是依赖于页面中定义的内容。即使您的网页内容不应通过默认进行缓存有时会逃离我。当处理动态内容或迭代时,这是特别普遍的。

  1. Often times I find it is better to write out your selector manually rather than rely on the contents as defined in the page. Even though your page contents should not be cached by default, they still manage to slip away from me at times. This is particularly prevalent when dealing with dynamic content or iterations.

例如:我们想要从动态创建的下拉列表中单击一个元素。

Ex: Let's say we want to click an element from a dynamically created dropdown.

通常你可能想要做一些类似...

Typically you might want to do something like...

static content = {
     dropdown { $("#parentDiv").find("ul") }
}

void clickDesiredElement(String elementName) {
     dropdown.click()
     def desiredElement = dropdown.find("li", text:elementName)
     waitFor { desiredElement.displayed }
     desiredElement.click()
}

如果这不起作用,请尝试完全删除内容,并手动写出选择器。

If this doesn't work, try getting rid of the contents altogether, and writing out the selector manually...

void clickDesiredElement(String elementName) {
     $("#parentDiv").find("ul").click()
     def desiredElement = $("#parentDiv").find("ul").find("li", text:elementName)
     waitFor { desiredElement.displayed }
     desiredElement.click()
}

真的很讨厌c ases,您可能必须使用手动计时器,如此答案所述,您的代码可能如下所示。 ..

In really nasty cases, you may have to use a manual timer, as pointed out in this answer, and your code may look like this...

void clickDesiredElement(String elementName) {
     $("#parentDiv").find("ul").click()
     sleepForNSeconds(2)
     def desiredElement = $("#parentDiv").find("ul").find("li", text:elementName)
     waitFor { desiredElement.displayed }
     desiredElement.click()
}

保持想想这是一个解决方法:)

Keep in mind this is a workaround :)

对于大型迭代和方便的关闭方法,例如每个{}或collect {},您可能需要添加一个waitFor

For large iterations and convenient closure methods, such as each{} or collect{}, you may want to add a waitFor{} in each iteration.

例如:假设我们要获取一个大表的所有行

Ex: Let's say we want to get all rows of a large table

通常你可能想要做一些类似...

Typically you might want to do something like...

def rows = $("#table1").find("tr").collect {
   [
      name: it.find("td",0),
      email: it.find("td",1)
   ]
}

有时我发现自己有为了避免StaleElementReferentException,迭代地执行此操作以及每个迭代之间的waitFor {}。它可能看起来像这样...

Sometimes I find myself having to do this iteratively, along with a waitFor{} between each iteration in order to avoid a StaleElementReferentException. It might look something like this...

def rows = []
int numRows = $("#table1").find("tr").size()
int i
for(i=0; i < numRows; i++) {
    waitFor {
      def row = $("#table1").find("tr",i)
      rows << [
          name: row.find("td",0),
          email: row.find("td",1)
      ]
    }
}


这篇关于Geb的一般问题(StaleElementReferenceException和等待超时)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆