W jaki sposób Selenium oczekuje na zakończenie ładowania strony?

W poprzednim artykule wytłumaczyłem, co oznacza z technicznego punktu widzenia zakończenie ładowania strony.
Powtórzę pokrótce podstawową definicję: Selenium (i najprawdopodobniej większość narzędzi) wykorzystuje właściwość document.readyState do określenia chwili zakończenia ładowania strony.

Teraz szczegółowo wytłumaczę jak ono to robi. Dokładniej mówiąc, nie jak, a kiedy.
Na pierwszy rzut oka wszystko wydaje się proste.
Właściwość document.readyState może przyjmować łącznie trzy różne wartości:

  • loading – oznacza, że strona jeszcze się ładuje,
  • interactive – oznacza, że podstawowa zawartość strony została załadowanai użytkownik może już z nią pracować, ale trwa jeszcze ładowanie dodatkowych zasobów (na przykład, obrazków),
  • complete – oznacza, że strona jest w całości załadowana.

Wykonujemy polecenie get, aby otworzyć w przeglądarce stronę ze wskazanym adresem, po czym czekamy, aż właściwość document.readyState nabędzie wartość complete.
Niestety, to nie wystarczy.

Jakby trochę pomyśleć – przypomina to polecenie click, wykonujące przejście po linku. Po nim także trzeba czekać na zakończenie ładowania strony.

Jednak to także nie wszystko.
Po każdym działaniu użytkownika może mieć miejsce ładowanie nowej strony.
Każde działanie użytkownika (nie tylko klik, ale również, na przykład, naciśnięcie klawisza albo najechanie kursorem na jakiś element) może mieć przypisaną wtyczka JavaScript, która aktywuje ładowanie nowej strony. Dlatego, po dowolnym poleceniu należy postarać się poczekać, aby zobaczyć czy nie ładuje się nowa strona.
Nadal to jeszcze nie wszystko.

Czasem po time out strona sama się odświeża, nawet jeśli nie zostały wykonane żadne działania. Jak Selenium może to wyśledzić? Nie jest to możliwe.

Co więc można robić?

Programiści Selenium znaleźli pomysłowe rozwiązanie.
By wykonać jakiekolwiek działanie na stronie musi być ona załadowana, czyli właściwość document.readyState musi nabyć odpowiednią wartość. Nie jest jednak konieczne, aby czekać na to po wykonaniu polecenia. Znacznie lepiej robić to przed jego wykonaniem.

Przed wykonywaniem każdego polecenia Selenium czeka, aż właściwość document.readyState otrzyma odpowiednią wartość.

Przykładowo, wykonuje się polecenie get, strona zaczyna się ładować, ale Selenium nie czeka, aż ona zakończy tę czynność. Zamiast tego dość szybko zawiadamia, że polecenie get zostało pomyślnie wykonane.

Potem próbujemy znaleźć na stronie dany element, aby zrealizować z nim jakieś działania, czyli wykonujemy polecenie findElement. W tej chwili Selenium zauważa, że właściwość document.readyState jeszcze nie osiągnęła wartości complete, czyli strona mimo wszystko nadal się ładuje. Wtedy wstrzymuje wykonanie polecenia poszukiwania elementu i czeka aż strona zakończy ładowanie.

Takim oto sposobem, wykonując jakieś polecenie, Selenium w ogóle nie interesuje, czy będzie po tym ładować się nowa strona czy nie. Jeżeli tak – poradzi sobie z tym przed wykonywaniem kolejnego polecenia.
Wspaniale, nieprawdaż?

P.S. Dlaczego na obrazku, który przekierowuje do tego artykułu jest kotek? To takie moje skojarzenie 🙂

Selenium jest jak kot w pułapce – czeka, aż przeglądarka “rozluźni się” i w tej chwili rzuca się na nią i wykonuje polecenie!

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn