Akcja - automatyzacja! Część 4: Asercje, dobre praktyki

Akcja - automatyzacja! Część 4: Asercje, dobre praktyki
Witamy wszystkich w kolejnej części naszej serii: Akcja - automatyzacja! Na wstępie zapraszamy do zapoznania się z naszym materiałem filmowym, w którym omawiamy temat asercji, oraz przedstawiamy dobre praktyki związane z ich wykorzystaniem.
 

Poniższy tekst jest tylko krótkim wstępem, którego rozbudowaną formą wraz z przykładami podpartymi kodem oraz szerszym opisem dobrych praktyk jest materiał filmowy.

Zarówno, gdy rozpoczynamy swoją przygodę z automatyzacją, jak i utrzymujemy wieloletni projekt, naszym celem jest zapewnienie jakości oprogramowania, a co za tym idzie, nie możemy zapomnieć o jakości tworzonego przez nas kodu.

Jedną z nieodłącznych części bibliotek testowych, są specjalnie przygotowane metody odpowiedzialne za weryfikację naszego wyniku -  asercje. Mimo że asercje są z nami już od Javy w wersji 4, to musimy pamiętać, że przy bardziej rozbudowanych projektach, dobrą praktyką jest korzystanie z osobnej biblioteki testowej.

A co za tym idzie, stosownym wydaje się wykorzystanie bardziej intuicyjnych asercji udostępnionych dla wybranej biblioteki.
 
Jednak by rozpocząć musimy w pierwszej kolejności skupić się na podstawach.
 
A więc zaczynajmy!
 

 
 
 

Trudne początki

Tworząc nasze testy pamiętajmy, że wiele zasad, wiele dobrych praktyk zostało już opisanych. Nie twórzmy “koła” na nowo, a wyciągajmy wnioski z wiedzy przekazanej przez bardziej doświadczonych i uczmy się by jakość naszych projektów była na najwyższym poziomie.

Zacznijmy sztampowo, od “regułki”:

Asercja (ang. assertion) – predykat (forma zdaniowa w danym języku, która zwraca prawdę lub fałsz), umieszczony w pewnym miejscu w kodzie. Asercja wskazuje, że programista zakłada, że predykat ów jest w danym miejscu prawdziwy. W przypadku gdy predykat jest fałszywy (czyli niespełnione są warunki postawione przez programistę) asercja powoduje przerwanie wykonania programu. Asercja ma szczególne zastosowanie w trakcie testowania tworzonego oprogramowania, np. dla sprawdzenia luk lub jego odporności na błędy. Zaletą stosowania asercji jest możliwość sprawdzenia, w którym fragmencie kodu źródłowego programu nastąpił błąd.
 

Przykład asercji w języku java:

int total = countNumberOfUsers();
 if (total % 2 == 0) {
  // wartość zmiennej total jest parzysta
 } else {
  // wartość zmiennej total jest nieparzysta
  assert(total % 2 == 1);
 }
 

Po wstępie, który raczej nie nasycił naszych szarych komórek, przedstawmy asercje bardziej praktycznie.

Pamiętajmy, że asercja to wyrażenie w języku programowania Java, która umożliwia weryfikację założeń dotyczących oprogramowania. Asercje pozwalają nam na sprawdzenie czy podany zestaw danych jest prawidłowy, np. czy nie próbujemy obliczyć ujemnego wyrazu ciągu Fibonacciego.

Każda asercja zawiera wyrażenie boolowskie, które według założenia będzie prawdziwe, gdy asercja zostanie wykonana. Jeżeli wyrażenie nie jest prawdą, system zwróci AssertionError. Poprzez sprawdzenie, czy wyrażenie logiczne jest prawdziwe, asercja potwierdza zakładane założenia dotyczące zachowania oprogramowania, zwiększając zaufanie do naszego oprogramowania.

 

Asercja ma dwie formy. Pierwsza, prostsza forma to:


	
assert Expression; gdzie operujemy na wyrażeniu boolowskim. Gdy system wykonuje asercję, ocenia tym samym wyrażenie, a jeśli jest ono fałszem, zwróci AssertionError bez szczegółowego komunikatu.
 

Druga forma to:


	
assert Expression : Expression; operujemy na wyrażeniu boolowskim a jako parametr podajemy wyrażenie do zweryfikowania.
 
Pamiętajmy o dobrych praktykach związanych z użyciem asercji w naszym kodzie.
 

Przykład poprawnego wykorzystania asercji:

  • Asercje można wykorzystać do wykrycia sytuacji, w której program dociera do miejsca, w którym nie powinien się znaleźć lub jego wynik jest inny niż się spodziewaliśmy.
 
Dobrą praktyką jest również znajomość instrukcji w kodzie dla których asercje nie powinny być używane.
 
Przykład niepoprawnego wykorzystania asercji:
 
  • Asercji nie należy stosować przykładowo do sprawdzania poprawności argumentów metod publicznych. Poprawność tych danych powinna być weryfikowalna w każdej sytuacji. Pamiętajmy, że asercje mogą być wyłączone przy uruchomieniu programu (i co więcej, jest to zachowanie domyślne). Gdyby asercja była wyłączona wówczas walidacja danych nie zostanie wykonana! Z tego też powodu nie wolno w warunku asercji umieszczać metod będących częścią logiki aplikacji. 
 
Więcej pozytywnych oraz negatywnych przykładów stosowania asercji prezentujemy w udostępnionym materiale filmowym.
 

Biblioteka testowa

Tworząc nasz projekt, wraz z jego rozwojem dobrą praktyką  jest korzystanie ze wsparcia bibliotek zewnętrznych, a co za tym idzie, wspomaganie rozwoju i utrzymanie naszego procesu.

Kontynuując temat asercji, posłużmy się przykładem biblioteki TestNG, która jest jedną z części bazowych prezentowanego przez nas przykładowego projektu w poprzednich materiałach.

Jak już wspomnieliśmy wcześniej podczas omawiania biblioteki TestNG, opiera się ona na specjalnie przygotowanych asercjach.

Jedną z prostych, przykładowych asercji TestNG, używanych podczas tworzenia testów jest: assertTrue(condition);

 
Jak widzimy, służy ona do sprawdzenia czy podany warunek jest prawdziwy, jeżeli nie, generowany jest AssertionError.
 

Przykład:

assertTrue(driver.findElement(By.id("login")).isDisplayed());

 

Inną przykładową asercją wykorzystywaną w testach jest:

assertEquals(actual, expected);
 
Służy ona do sprawdzenia czy dwie wskazane wartości są sobie równe.
 

Przykład:

assertEquals(driver.getTitle(), "Logowanie - TestArena Demo");

 
Gdy oczekujemy, by asercja zwróciła nam jakąś dodatkową informację, możemy ją rozwinąć, dodając do niej “String” wraz z wybranymi danymi (odpowiadającymi typowi danych dla klasy “String”), określającymi naszą wiadomość.
 

Przykład:

assertEquals(driver.getTitle(), "Logowanie - TestArena Demo", "przykładowa informacja");

 
Szerszy opis dostępnych asercji dla biblioteki TestNG znajdziecie tutaj:
 
 
Powyższe przykłady pokazują, że asercje są zbudowane w intuicyjny sposób, co wspomaga nas w doborze odpowiedniego do nich warunku.
 
Odpowiedzialność
 

Tworząc nasze testy musimy pamiętać o ważnej zasadzie, a jest nią:

“The Single Responsibility Principle” - (Zasada jednej odpowiedzialności).
 
Zgodnie z tą zasadą odwołującą się również do tworzonych testów, musimy pamiętać by:
każdy nasz test sprawdzał tylko jeden warunek, a co za tym idzie, by każdy nasz test zawierał tylko jedną asercję.
 

Zastosowanie się do tej zasady pomaga nam np. w:

  • utrzymaniu czytelnego kodu,
  • zmniejsza szansę na niepowodzenie testu w przypadku źle zdefiniowanych asercji,
  • możliwość szybkiej refaktoryzacji kodu.
Opis zasady jednej odpowiedzialności znajdziecie tutaj: https://pl.wikipedia.org/wiki/Zasada_jednej_odpowiedzialno%C5%9Bci 
 

Zatem, stosując się do poznanych zasad, nasz przykładowy test mógłby wyglądać tak:

@Test(priority = 1)
public void failLoginWithWrongPassword()
{
     driver.findElement(By.id("email")).sendKeys("administrator@testarena.pl");
     driver.findElement(By.id("password")).sendKeys("sum666");
     driver.findElement(By.id("login")).click();

     assertTrue(driver.findElement(By.className("login_form_error"))
             .getText().equals("Adres e-mail i/lub hasło są niepoprawne."));
}
 
 

Nawiązując do poznanych przykładów i korzystając z omówionych praktyk oraz zasad jesteśmy w stanie stworzyć prosty i łatwy w utrzymaniu test.

Pamiętajcie, że wykorzystane asercje są nieodłączną częścią dobrze napisanych testów automatycznych.

Pomagają nam zarówno w utrzymaniu czytelnej struktury naszych testów, jak i w szybkiej refaktoryzacji naszego kodu.

W tym miejscu kończymy nasz dzisiejszy materiał. Jeszcze raz zapraszamy do zapoznania się z materiałem filmowym. Znajdziecie tam m.in.: rozwinięcie tematu asercji, dodatkowe asercje wykorzystywane w testach wraz z przykładami podpartymi  kodem, oraz omówienie dobrych praktyk.

 

A już w następnych materiałach, omówimy m.in. takie zagadnienia jak:

Klasa WebElement:

  • lokalizacja elementów na podstawie selektorów,
  • operacje na elementach.
 

Klasa WebDriverWait:

  • oczekiwanie na element,
  • oczekiwanie na zdarzenie,
  • najczęstsze błędy dotyczące oczekiwania.
 

Wzorce projektowe - wprowadzenie

  • Page Object Pattern
 
 
Trzymajcie się, HEJ!
 
 
Autor: Krzysztof Kołodziejczyk
 
 
 
SPRAWDŹ TAKŻE
Akcja - automatyzacja! Część 1: Konfiguracja 
Akcja - automatyzacja! Część 2: JUnit / TestNG - porównanie 
Akcja - automatyzacja! Część 3: Pierwsza klasa testowa 

 

To powinno Cię zainteresować