Całość kursu dostępna tutaj
Stwórzmy troszeczkę bardziej skomplikowany test. Spróbujmy się zalogować do http://demo.bananascrum.com
@Test public void test1() { driver.get("http://demo.bananascrum.com/login"); WebElement a = driver.findElement(By.id("login")); //pole z loginem a.sendKeys("admin"); //wpisuje login WebElement b = driver.findElement(By.id("password")); //pole z haslem b.sendKeys("password");//wpisuje haslo WebElement c = driver.findElement(By.name("commit")); //klikam zatwierdz c.click(); driver.findElement(By.id("admin")).isDisplayed(); //Sprawdź czy zalogowany }
Czy coś z tym testem jest nie tak?
Przecież działa…
Przede wszystkim problemem są w nim komentarze. Jeśli nasz kod potrzebuje komentarzy to znaczy, że nie jest wystarczająco przejrzysty. I tak własnie jest w przypadku tego kodu.
Zanim zabiorę się do komentarzy wypadało by się zastanowić co chcemy przetestować – z tego testu nie wynika to wprost.
Przede wszystkim należało by zmienić nazwę.
@Test public void shouldBePossibleToLogInWithCorrectData() { ...
Używam konwencji z “should” na początku – dzięki temu nazwa testu zawsze wskazuje na to co chcemy przetestować.
Nazwa ma dodatkowo bardzo istotne znaczenie – raczej staramy się by nasze testy były jak najbardziej atomowe i testowały zawsze jedną rzecz. Dzięki takiemu podejściu informacja jaką nam dają jest zawsze przejrzysta – dokładnie wiemy co się zepsuło i gdzie szukać błędów.
Jeśli w nazwie swojego testu wpisujesz “and” albo “or” to wiedz, że coś się dzieje…
Komentarze…
Z komentarzami główny problem jest taki, że przeważnie są nieaktualne i mylące – o ile w momencie gdy piszemy kod bywają pomocne to z czasem tylko przeszkadzają. Pamiętajmy o tym, że nasz kod żyje swoim życiem i cały czas się rozwija.
Jak się ich pozbyć? Można na przykład stosować odpowiednie nazwy metod.
Krok pierwszy – Extract Method.
@Test public void shouldBePossibleToLogInWithCorrectCredentials() { openLoginPage(); logIn(); checkIfLogedIn(); } private void checkIfLogedIn() { driver.findElement(By.id("admin")).isDisplayed(); } private void logIn() { WebElement a = driver.findElement(By.id("login")); //pole z loginem a.sendKeys("admin"); //wpisuje login WebElement b = driver.findElement(By.id("password")); //pole z haslem b.sendKeys("password");//wpisuje haslo WebElement c = driver.findElement(By.name("commit")); //klikam zatwierdz c.click(); }
Polecam używać skrótu klawiszowego ALT+SHIFT+M. Zaznaczamy kawałek kodu i wciskamy skrót – pozostaje podanie nazwy metody.
Wytworzone w ten sposób metody pozostawiają wiele do życzenia.
Zwłaszcza metoda logIn() nadal wymaga komentarzy…
private void logIn() { WebElement login = driver.findElement(By.id("login")); WebElement password = driver.findElement(By.id("password")); WebElement commit = driver.findElement(By.name("commit")); login.sendKeys("admin"); password.sendKeys("password"); commit.click(); }
Teraz wygląda to trochę lepiej. Nie jest jeszcze perfekcyjnie ale do tego przejdziemy później.
Krok 2 – struktura testów.
@Test public void shouldBePossibleToLogInWithCorrectCredentials() { openLoginPage(); logIn(); checkIfLogedIn(); }
Powyższy test wygląda już całkiem nieźle.
Widać w nim pewną strukturę:
- najpierw przygotowujemy sobie środowisko testowe (otwieramy testowaną stronę)
- następnie wykonujemy testowaną akcję
- i weryfikujemy czy akacja przyniosła oczekiwany efekt.
Powyższą strukturę można opisać jako Given, When, Then (konwencja znana praktykom BDD). Given – kontekst testu, When – akcja do wykonania (zawsze jedna), Then – sprawdzenie poprawności wykonywanej akcji, asercje.
@Test public void shouldBePossibleToLogInWithCorrectCredentials() { // GIVEN openLoginPage(); // WHEN logIn(); // THEN checkIfLogedIn(); }
To by było na tyle jak na początek. Więcej w praniu…
Polecam książkę Clean Code – Robert C. Martin.
Czystość i przejrzystość testów to podstawa jeśli zależy nam na ich utrzymywalności i rozwijalności w przyszłości. A zależy nam na tym zawsze – inaczej nie było by sensu pisać testów.
W następnych częściach kursu będzie o tym jak parametryzować testy oraz rozpoczniemy przygodę z wzorcami projektowymi. Nasze testy nadal nie są obiektowe – a warto by było wykorzystać w pełni możliwości języków obiektowych takich jak Java.