Piszę testy Selenium z Selenium DSL ScalaTest i mam problemy z przekroczeniem limitu czasu, których nie potrafię wyjaśnić. Aby sprawy były bardziej skomplikowane, wydają się zdarzać tylko przez pewien czas.Dziwny limit czasu z ScalaTest's Selenium DSL
Problem pojawia się za każdym razem, gdy uzyskuję dostęp do elementu po wczytaniu strony lub renderowaniu JavaScript. Wygląda to tak:
click on "editEmployee"
eventually {
textField(name("firstName")).value = "Steve"
}
My PatienceConfig jest skonfigurowany tak:
override implicit val patienceConfig: PatienceConfig =
PatienceConfig(timeout = Span(5, Seconds), interval = Span(50, Millis))
test nie powiedzie się z powodu następującego błędu:
- should not display the old data after an employee was edited *** FAILED ***
The code passed to eventually never returned normally. Attempted 1 times over 10.023253653000001 seconds.
Last failure message: WebElement 'firstName' not found.. (EditOwnerTest.scala:24)
to ma sens, że nie uda natychmiast, ponieważ click
powoduje pewne renderowanie, a pole tekstowe może nie być dostępne od razu. Jednak nie powinno zająć 10 sekund, aby spróbować go znaleźć, prawda?
Uważam też, że bardzo interesujące jest to, że blok ostatecznie spróbował go tylko raz i że zajęło to prawie dokładnie 10 sekund. To pachnie jak timeout gdzieś, a to nie jest moja PatienceConfig, ponieważ ustawiono czas oczekiwania po 5 sekundach.
Z tego obejścia, to działa:
click on "editEmployee"
eventually {
find(name("firstName")).value // from ScalaTest's `OptionValues`
}
textField(name("firstName")).value = "Steve"
zrobiłem kilka kopanie w źródle ScalaTest, i zauważyłem, że wszystkie połączenia, które mają ten problem (nie tylko textField
), ewentualnie zadzwonić webElement
w pewnym momencie. Powodem, dla którego obejście tego problemu działa, jest to, że nie nazywa się webElement
. webElement
jest zdefiniowany następująco:
def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = {
try {
driver.findElement(by)
}
catch {
case e: org.openqa.selenium.NoSuchElementException =>
// the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem.
val queryStringValue = queryString
throw new TestFailedException(
(_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."),
Some(e),
pos
)
}
}
mam kopiowane tego kodu do mojego projektu i bawił się z nim, i wygląda na to, budowy i/lub rzuca wyjątek, gdzie większość z 10 sekund są wydawane.
(EDIT Wyjaśnienie: Rzeczywiście widziałem, że kod rzeczywiście spędził 10 sekund wewnątrz bloku catch. Domyślne oczekiwanie jest ustawione na 0, a poza tym, jeśli usunę blok catch, wszystko po prostu działa zgodnie z oczekiwaniami.)
Moje pytanie brzmi, co mogę zrobić, aby uniknąć tego dziwnego zachowania? Nie chcę ciągle wstawiać zbędnych wywołań do find
, ponieważ łatwo o tym zapomnieć, tym bardziej, że, jak powiedziałem, błąd występuje tylko przez pewien czas. (Nie byłem w stanie określić, kiedy zachowanie występuje, a kiedy nie.)
Czy strona nadal ładuje się po przekroczeniu limitu czasu? Czy sprawdziłeś konsolę przeglądarki, aby sprawdzić, czy są jakieś błędy? Domyślam się, że strona ma zasób, którego nie można załadować, uniemożliwiając w ten sposób osiągnięcie stanu "pełnego" oczekiwanego przez sterownik. –
Ale nawet jeśli tak jest, wywołanie 'driver.findElement' powinno po prostu zawieść (ponieważ domyślne oczekiwanie ma wartość 0), powinno przejść do bloku catch, a następnie' finally' sprawi, że spróbuje ponownie, prawda? – jqno
domyślne ustawienie oczekiwania nie ma wpływu i nie jest związane z oczekiwaniem na ukończenie strony. Sterownik czeka na stronę [pełny stan] (https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState) na każdym poleceniu, chyba że opcja 'pageLoadingStrategy' jest ustawiona na' none' . –