blog.testowka.pl

Kurs Selenium część 7 – Asynchronicznie doładowywane elementy na stronach

opublikowany przez 26, Sie, 2013, w kategoriach Kurs Selenium

Całość kursu dostępna tutaj.

Kilka razy zgłaszaliście się już do mnie z pytaniami odnośnie problemu z asynchronicznym doładowywaniem poszczególnych elementów na stronach internetowych, które testujecie.

Problem ten objawia się często niedeterministycznym zachowaniem testów, które raz na jakiś czas nie przechodzą. Oczywiście może to być objaw także wielu innych problemów, niemniej jednak najczęściej spowodowane jest to właśnie tym, że niektóre elementy na stronie są doładowywane asynchronicznie już po załadowaniu całej strony.

Jak wcześniej pisałem WebDriver opiera się na działaniu silnika przeglądarki. Przeglądarki internetowe po załadowaniu i wyświetleniu kodu strony (kodu html) otrzymują od serwera status „200 OK”. To właśnie na podstawie tej informacji Selenium uznaje, że strona się już załadowała więc pora na rozpoczęcie kolejnych akcji.

Coraz częściej jednak załadowanie samego kodu html z serwera to dopiero początek renderowania strony internetowej. Po potwierdzeniu statusu od serwera następuje jeszcze szereg asynchronicznych wywołań, które doładowują do strony poszczególne elementy. Często też różne efekty graficzne jak płynne wyłanianie się poszczególnych elementów, dzieje się już po załadowaniu strony, a elementy te nie są jeszcze przez chwile widoczne.

Podsumowując czasem Selenium zobaczy taki element (jeśli wyświetli się on dostateczni szybko) a czasem nie. Brak deterministycznego zachowania testów zasadniczo obniża ich jakość i wartość.

Oczywiście można próbować wstawiać różnego rodzaju pauzy w naszych testach – niestety takie podejście po pierwsze brzydko wygląda a po drugie zasadniczo spowalnia nasze testy.

Jest na to lepszy sposób. Selenium (od niedawna0 dostarcza wbudowanej funkcji, która oczekuje na pojawienie się elementu:

WebElement myDynamicElement = (new WebDriverWait(driver, 10))
  .until(ExpectedConditions.presenceOfElementLocated(By.id("login")));

Powyższe sprawdza, czy element jest widoczny w strukturze html oraz widoczny na stronie (to nie zawsze to samo).

Możemy też sprawdzić, czy element jest na przykład klikalny:

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));

Dzięki takiemu podejściu unikamy brzydkich opóźnień w naszych testach. Powyższe kawałki kodu oznaczają, że test będzie czekał maksymalnie 10 sekund na to aż element się pojawi, sprawdzając co kilka milisekund czy być może się już pojawił. Gdy tylko element stanie się widoczny skrypt oczekujący przerwie czekanie i nasze testy ruszą dalej.

Pozostaje pytanie czy zawsze stosować tego typu podejście? Możemy nawet ten kawałek kodu dodać bezpośrednio do metod typu „insertText” czy „click”, które sobie stworzymy. Należy jednak pamiętać, że tego typu podejście będzie o 10 sekund opóźniało wykonanie każdego testu zanim test nie przejdzie, jeśli jakiś element faktycznie się nie wyświetla.


15 Comments for this entry

  • nv

    Kiedy następne lekcje 😉 ?

  • kupix

    do całej serii brakuje mi jeszcze połączenie takich testów z np. jenkinsem. czy jakieś szanse na kontynuację/aktualizację serii?

  • streser

    Tak będzie kontynuacja! Coraz więcej osób tutaj zagląda więc jest to potrzebne (+aktualizacja tego co już jest).
    Kolejne plany to:
    – Page Object Pattern
    – Integracja z Jenkinsem
    – BDD/Specyfication By Example – z Cucumber lub JBehave (ale to dalsza przyszłość).

  • wahuu

    Elegancko wytłumaczone, czekam na kolejne lekcję.
    Przydała by się ta integracja z jenkinsem

  • stute

    Tak, chcemy więcej 🙂

  • selenium

    Hej będa kolejne część??

  • rafik

    Wciągnąłeś, zaczęliśmy się uczyć i co? 😀
    Proszę o dalsze artykuły dot. Selenium. Niestety, internet jest ubogi, mało osób dzieli się swym doświadczeniem.

  • gagatek

    Witka,
    co z kontynuacją?? Fajnie się zaczyna ale mało mało i jeszcze raz mało!!!:)

  • gherkin

    bump. ciągle czekamy na kontynuację 🙁

  • Misiek

    Więcej Więcej!

  • krakus

    Do tego „WebDriverWait” oraz „ExpectedConditions” należy wczytać jakieś biblioteki? jakie? Próbuję jak poniżej:

    package testowka;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.By;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.Test;
    import org.testng.annotations.AfterClass;
    import static org.testng.Assert.*;

    public class Test07_Asynchronous {
    WebDriver driver;

    @BeforeClass
    public void setUp(){
    System.setProperty(„webdriver.chrome.driver”, „X:\\!Software\\Selenium\\chromedriver_win32\\chromedriver.exe”);
    driver = new ChromeDriver();
    }

    @Test
    public void shouldBePossibleToLoginWithCorrectData(){
    //GIVEN
    openLoginPage();
    //WHEN
    logIn();
    //THEN
    checkIfLoggedIn();
    }

    private void openLoginPage() {
    driver.get(„https://github.com/login”);
    }

    private void logIn(){
    WebElement myDynamicElement = (new WebDriverWait(driver, 30)).until(ExpectedConditions.presenceOfElementLocated(By.name(„login”)));
    WebElement password = driver.findElement(By.id(„password”));
    WebDriverWait wait = new WebDriverWait(driver, 10);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.name(„commit”)));

    myDynamicElement.sendKeys(„Userkrk”);
    password.sendKeys(„Userkrk1”);
    element.click();
    }

    private void checkIfLoggedIn(){
    assert(driver.findElement(By.partialLinkText(„UserkrkA”)).isDisplayed());
    }

    @AfterClass
    public void tearDown() {
    driver.quit();
    }

    }

  • krakus

    Błędy: WebDriverWait cannot be resolved to a type.
    Pewnie trzeba zaimportować bibliotekę. Ale jaką?

  • krakus

    „I had the following errors:
    „The import org.openqa.selenium.support cannot be resolved”
    „WebDriverWait cannot be resolved to a type”
    area of problem:
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;

    Because I was using Selenium 2.44, I had to download jar from:
    https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-support/2.44.0

    As I was using elcipse Luna, I had to open menu Project\Properties,
    Java Build Path\Add External JARs, pick the file

    I had also to add dependency to pom.xml file acc. to description from page https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-support/2.44.0

    org.seleniumhq.selenium
    selenium-support
    2.44.0

    Musiałem też dodać:
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;

    Tak że wielkie dzięki wszystkim za pomoc!

  • MarcoI

    Kto chce zarobic nie wychodzac z domu kilkanascie $$$ dziennie?? Sposob jest prosty i dziala, poszukajcie sobie w google: jak kosic kase na adfly

Skomentuj