Czas czytania: około 12 minut
Test automatyczny, który otwiera stronę, klika „Kup teraz”, wypełnia formularz i kończy się zielono, może nie sprawdzać niczego. Jeśli po drodze nie ma ani jednego porównania wyniku z oczekiwaniem, przechodzi także wtedy, gdy koszyk pokazuje zero złotych, a płatność zwraca błąd. Tym porównaniem jest asercja i to ona, nie kliknięcia, zamienia skrypt w test. W tym tekście wyjaśniamy, czym jest asercja, jakie ma rodzaje, jak używać jej w Selenium z JUnit, TestNG, pytest i AssertJ, dlaczego asercje padają, choć aplikacja działa, i jak pisać takie, które mówią, co się zepsuło.
Asercja to instrukcja w teście, która porównuje wynik rzeczywisty z oczekiwanym i przerywa test albo oznacza go jako nieudany, gdy się nie zgadzają. Bez asercji test tylko wykonuje kroki i przechodzi niezależnie od tego, co pokazuje aplikacja. W Selenium asercje dostarcza framework testowy (JUnit, TestNG, pytest, NUnit) albo biblioteka (AssertJ, Hamcrest), a sprawdza się nimi tytuł, adres, tekst, widoczność, atrybuty i liczbę elementów na stronie.
Spis treści
- Czym jest asercja?
- Dlaczego test bez asercji niczego nie sprawdza?
- Asercje twarde i miękkie: czym się różnią i kiedy której użyć?
- Jakie są rodzaje asercji?
- Co sprawdzać asercjami w testach Selenium?
- Asercje w JUnit 5, TestNG, pytest i AssertJ: czym się różnią?
- Dlaczego asercja pada, choć aplikacja działa?
- Jak pisać dobre asercje?
- Jakie są najczęstsze błędy w asercjach?
- Asercje poza Selenium: API i testy jednostkowe
- Najczęstsze pytania o asercje

Czym jest asercja?
Asercja to warunek zapisany w kodzie testu, który musi być prawdziwy, żeby test przeszedł: porównuje wartość rzeczywistą (to, co zwróciła aplikacja) z wartością oczekiwaną (to, co powinna zwrócić według wymagań) i przy niezgodności zgłasza błąd z komunikatem.
W terminologii ISTQB źródłem wartości oczekiwanej jest wyrocznia testowa: wymagania, specyfikacja, poprzednia wersja systemu albo wiedza eksperta, a wynik oczekiwany to zachowanie przewidziane przez tę wyrocznię. Asercja jest miejscem, w którym ta wiedza trafia do kodu. Wszystko, co test robi wcześniej (otwarcie strony, wpisanie danych, kliknięcie), przygotowuje tylko grunt pod to jedno porównanie.
Słowo pochodzi z programowania: instrukcja assert w wielu językach sprawdza założenie, które programista uważa za zawsze prawdziwe, i zatrzymuje program, gdy nie jest. W testach automatycznych asercja robi to samo, tylko założeniem jest wymaganie biznesowe. Kliknięcia i wpisy w teście są jak pytanie, a asercja jak odpowiedź. Test bez asercji zadaje pytanie i wychodzi, nie czekając, co usłyszy.
Dlaczego test bez asercji niczego nie sprawdza?
Test bez asercji przechodzi zawsze, dopóki nie wystąpi wyjątek techniczny, więc mówi tylko, że strona się otworzyła i elementy dały się kliknąć; nie mówi nic o tym, czy aplikacja zrobiła to, co powinna, a to jedyne pytanie, na które test ma odpowiedzieć.
Typowy przykład z projektów: zestaw dwustu testów regresyjnych, wszystkie zielone od miesięcy, a na produkcji rabat nalicza się od złej kwoty. Testy klikały przez koszyk i płatność, ale żaden nie porównywał kwoty na podsumowaniu z wartością oczekiwaną. Taki zestaw daje fałszywe poczucie bezpieczeństwa droższe niż brak testów, bo nikt nie sprawdza ręcznie tego, co „jest zautomatyzowane”.
Dlatego przegląd zestawu testów zaczyna się od pytania, ile testów kończy się asercją na wyniku biznesowym, a ile na tym, że element istnieje. Test, który sprawdza tylko obecność przycisku „Zapłać”, nie sprawdza płatności. Jak zaprojektować, co ma być sprawdzone, opisujemy w tekście o technikach projektowania testów, a jak zapisać wynik oczekiwany w zgłoszeniu w tekście Jak poprawnie zgłosić błąd.
Asercje twarde i miękkie: czym się różnią i kiedy której użyć?
Asercja twarda przerywa test przy pierwszej niezgodności i oznacza go jako nieudany, a asercja miękka zapisuje niezgodność, pozwala wykonać dalsze kroki i zgłasza wszystkie zebrane błędy na końcu; twardej używa się tam, gdzie dalszy test nie ma sensu, miękkiej tam, gdzie chcecie zobaczyć wszystkie błędy na jednym ekranie w jednym przebiegu.
| Kryterium | Asercja twarda | Asercja miękka |
|---|---|---|
| Zachowanie przy niezgodności | przerywa test natychmiast, wyjątek, status nieudany | zapisuje błąd, test biegnie dalej, zgłoszenie zbiorcze na końcu |
| Kiedy | warunek wstępny dalszych kroków: zalogowano, przeniesiono na stronę zakupu, zamówienie istnieje | sprawdzanie wielu pól jednego ekranu: etykiety, wartości, widoczność elementów formularza |
| Zaleta | szybka informacja, brak pracy na uszkodzonym stanie | pełna lista błędów z jednego przebiegu, mniej cykli napraw |
| Wada | jeden błąd na przebieg; kolejne widać dopiero po naprawie pierwszego | łatwo zapomnieć o wywołaniu podsumowania i wtedy błędy giną; test biegnie na złym stanie |
| JUnit 5 | Assertions.assertEquals i pozostałe | Assertions.assertAll z listą lambd |
| TestNG | Assert.assertEquals | SoftAssert z assertAll na końcu |
| pytest | assert | pytest-check albo własna lista błędów |
| AssertJ | assertThat(…).isEqualTo(…) | SoftAssertions z assertAll |
Praktyczna reguła: pierwsza asercja w teście jest twarda i sprawdza, czy test w ogóle doszedł tam, gdzie ma sprawdzać (właściwa strona, właściwy stan). Dalsze, na szczegółach jednego ekranu, mogą być miękkie. Miękka asercja bez wywołania podsumowania na końcu jest gorsza niż brak asercji, bo wygląda jak sprawdzenie, a nic nie zgłasza.
Jakie są rodzaje asercji?
Asercje dzielą się według tego, co porównują: równość i nierówność wartości, prawdę i fałsz warunku, obecność i brak wartości (null), zgłoszenie wyjątku, zawartość kolekcji i tekstu, a w narzędziach do testów interfejsu także asercje ponawiane, które czekają, aż warunek stanie się prawdziwy.
| Rodzaj | Wywołanie | Przykład | Uwaga |
|---|---|---|---|
| Równość | assertEquals(oczekiwane, rzeczywiste) | kwota na podsumowaniu równa 180,00 | kolejność argumentów: w JUnit i TestNG oczekiwane jest pierwsze, pomylenie myli komunikaty |
| Nierówność | assertNotEquals | nowy identyfikator zamówienia różny od poprzedniego | rzadko potrzebna, często zastępowana konkretną wartością |
| Prawda i fałsz | assertTrue, assertFalse | element widoczny, przycisk włączony | komunikat błędu bez treści: „expected true”, zawsze dodajcie opis |
| Obecność wartości | assertNull, assertNotNull | odpowiedź zawiera identyfikator | w testach interfejsu rzadziej, częściej w testach API i jednostkowych |
| Wyjątek | assertThrows | niepoprawny kod rabatu zgłasza wyjątek walidacji | sprawdza też typ i komunikat wyjątku |
| Kolekcje i tekst | assertThat z AssertJ lub Hamcrest: contains, hasSize, startsWith, matches | lista produktów ma 3 pozycje i zawiera „Szkolenie Selenium” | czytelniejsze komunikaty niż assertTrue(lista.contains(x)) |
| Ponawiane (web-first) | expect(locator).toHaveText w Playwright, cy.should w Cypress | tekst pojawi się w ciągu limitu czasu | w Selenium trzeba połączyć oczekiwanie z asercją ręcznie |
Dokumentacja: asercje w JUnit 5, asercje w TestNG, assert w pytest, AssertJ, Hamcrest, asercje w Playwright. Nazwy różnią się między frameworkami, mechanizm jest ten sam: porównanie i wyjątek przy niezgodności.

Co sprawdzać asercjami w testach Selenium?
W testach Selenium asercjami sprawdza się tytuł i adres strony, tekst elementu, widoczność i stan (włączony, zaznaczony), wartość atrybutu, liczbę elementów pasujących do lokatora oraz brak elementu, którego być nie powinno; najważniejsza asercja w teście dotyczy wyniku biznesowego, nie obecności przycisku.
Selenium 4 z JUnit 5, Java: asercje twarde i miękkie w jednym teście
@Test
void rabatNaliczaSieOdKwotyNetto() {
driver.get("https://sklep.przyklad.pl/koszyk");
new WebDriverWait(driver, Duration.ofSeconds(10))
.until(ExpectedConditions.visibilityOfElementLocated(By.id("kod-rabatowy")))
.sendKeys("WIOSNA10");
driver.findElement(By.id("zastosuj")).click();
// twarda: bez potwierdzenia rabatu dalsze sprawdzenia nie mają sensu
WebElement komunikat = new WebDriverWait(driver, Duration.ofSeconds(10))
.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".alert-success")));
assertEquals("Kod WIOSNA10 został zastosowany", komunikat.getText(), "komunikat po zastosowaniu kodu");
// miękkie: wszystkie pola podsumowania w jednym przebiegu
assertAll("podsumowanie koszyka",
() -> assertEquals("200,00 zł", driver.findElement(By.id("suma-netto")).getText(), "suma netto"),
() -> assertEquals("20,00 zł", driver.findElement(By.id("rabat")).getText(), "kwota rabatu"),
() -> assertEquals("180,00 zł", driver.findElement(By.id("do-zaplaty")).getText(), "do zapłaty"),
() -> assertTrue(driver.findElement(By.id("zaplac")).isEnabled(), "przycisk Zapłać włączony")
);
}
TestNG, ten sam pomysł z SoftAssert
SoftAssert miekka = new SoftAssert();
miekka.assertEquals(driver.findElement(By.id("suma-netto")).getText(), "200,00 zł", "suma netto");
miekka.assertEquals(driver.findElement(By.id("do-zaplaty")).getText(), "180,00 zł", "do zapłaty");
miekka.assertAll(); // bez tej linii błędy nigdy nie zostaną zgłoszone
Trzy rzeczy w tym przykładzie: każda asercja ma komunikat, który mówi, co sprawdzała; element jest najpierw oczekiwany, potem sprawdzany; asercja twarda otwiera, miękkie domykają. Lokatory po identyfikatorach zamiast po strukturze opisujemy w tekście o selektorach w Selenium, a to, jak w ogóle zacząć, w tekście Selenium: co to jest i od czego zacząć.
Asercje w JUnit 5, TestNG, pytest i AssertJ: czym się różnią?
JUnit 5 i TestNG mają wbudowane klasy asercji z asercjami miękkimi (assertAll, SoftAssert), pytest używa zwykłego słowa kluczowego assert z rozbudowanym komunikatem o różnicy, a AssertJ i Hamcrest dodają płynny zapis i czytelne komunikaty dla kolekcji i tekstu; różnią się składnią i kolejnością argumentów, nie zasadą działania.
| Framework | Język | Zapis | Miękkie | Uwaga |
|---|---|---|---|---|
| JUnit 5 | Java, Kotlin | Assertions.assertEquals(oczekiwane, rzeczywiste, komunikat) | assertAll | oczekiwane pierwsze; assertThrows i assertTimeout wbudowane |
| TestNG | Java | Assert.assertEquals(rzeczywiste, oczekiwane, komunikat) | SoftAssert plus assertAll | rzeczywiste pierwsze, odwrotnie niż JUnit; łatwo pomylić przy migracji |
| pytest | Python | assert rzeczywiste == oczekiwane, komunikat | pytest-check | pytest sam pokazuje różnicę wartości w komunikacie, bez osobnych metod |
| AssertJ | Java | assertThat(rzeczywiste).isEqualTo(oczekiwane) | SoftAssertions | płynny zapis z podpowiedziami w edytorze, bogate asercje na kolekcjach i tekście |
| Hamcrest | Java, Python | assertThat(rzeczywiste, equalTo(oczekiwane)) | brak, przez biblioteki | dopasowania składane w wyrażenia, czytelne komunikaty |
| NUnit | C# | Assert.That(rzeczywiste, Is.EqualTo(oczekiwane)) | Assert.Multiple | model ograniczeń jak w AssertJ |
| unittest | Python | self.assertEqual(rzeczywiste, oczekiwane) | subTest | wbudowany w Pythona, bardziej rozwlekły niż pytest |
Kolejność argumentów to najczęstsze źródło mylących komunikatów: JUnit oczekuje wartości oczekiwanej jako pierwszej, TestNG rzeczywistej. Pomyłka nie psuje wyniku testu, ale komunikat „oczekiwano 180,00, otrzymano 200,00″ będzie odwrócony i wyśle programistę w złą stronę. AssertJ omija problem, bo w zapisie płynnym zawsze zaczyna od wartości rzeczywistej. Podstawy Javy i Pythona potrzebne do tych frameworków uczymy na szkoleniach Java dla testerów i Python dla testerów.
Dlaczego asercja pada, choć aplikacja działa?
Asercja w teście interfejsu pada mimo działającej aplikacji najczęściej dlatego, że sprawdza element, zanim aplikacja skończyła go rysować lub ładować dane; rozwiązaniem jest jawne oczekiwanie na warunek przed asercją albo asercja ponawiana, nie stałe uśpienie i nie zwiększanie limitów.
- Oczekiwanie przed asercją. W Selenium asercja nie czeka. Jeśli tekst komunikatu pojawia się po odpowiedzi serwera, sprawdzenie milisekundę po kliknięciu zobaczy pustkę. Przed asercją stoi WebDriverWait z warunkiem na tekst, widoczność albo obecność, opisany w tekście o waitach w Selenium WebDriver.
- Asercje ponawiane. Playwright i Cypress łączą oczekiwanie z asercją: sprawdzenie „element ma tekst” ponawia się do limitu czasu. W Selenium ten sam efekt daje warunek ExpectedConditions.textToBePresentInElement użyty przed asercją.
- Stan przejściowy. Element widoczny, ale z poprzednią wartością: koszyk pokazuje 200,00 przez ułamek sekundy, zanim przeliczy się na 180,00. Oczekiwanie na konkretną wartość, nie na widoczność.
- Dane testowe. Asercja oczekuje „180,00 zł”, a cena produktu zmieniła się w bazie testowej. Wartość oczekiwana liczona z danych wejściowych albo przygotowana przez API przed testem, nie wpisana na sztywno z zeszłego miesiąca.
- Format. „180,00 zł” a „180.00 PLN”, spacja niełamliwa, białe znaki na końcu. Porównanie po normalizacji albo asercja na liczbie, nie na napisie.
Liczby z projektu dla Argos, potwierdzone przez klienta. Część sprawdzeń, które wcześniej były asercjami w testach interfejsu, przeszła tam na poziom API, gdzie ta sama asercja na kwocie rabatu wykonuje się w milisekundy i nie zależy od rysowania ekranu.
Jak pisać dobre asercje?
Dobra asercja sprawdza jedną rzecz, ma komunikat mówiący, co sprawdzała i w jakim kontekście, porównuje z wartością oczekiwaną wyliczoną albo pobraną z wyroczni, a nie wpisaną z pamięci, stoi po oczekiwaniu na stan, nie przed nim, i dotyczy wyniku biznesowego, nie obecności elementu.
Asercje to część architektury testów, obok Page Objectów i konfiguracji, o której piszemy w tekście Automatyzacja testów Selenium WebDriver: wzorce projektowe. Dobre miejsce na asercje to test, nie Page Object: klasa strony zwraca wartości, test je porównuje, dzięki czemu Page Object da się użyć w wielu testach z różnymi oczekiwaniami.
Jakie są najczęstsze błędy w asercjach?
Najczęstsze błędy to test bez asercji, asercja tylko na obecności elementu, asercja przed oczekiwaniem na stan, miękka asercja bez podsumowania, kilka warunków w jednej asercji bez komunikatu, wartości oczekiwane wpisane na sztywno i asercje w Page Objectach.
- Zero asercji. Test klika i przechodzi. Sprawdźcie zestaw: ile testów kończy się porównaniem wyniku biznesowego.
- Tylko obecność. assertTrue(element.isDisplayed()) na przycisku „Zapłać” zamiast asercji na potwierdzeniu i kwocie.
- Asercja przed oczekiwaniem. Sprawdzenie tekstu milisekundę po kliknięciu. Test niestabilny, choć aplikacja działa.
- Miękka bez assertAll. SoftAssert bez wywołania podsumowania nigdy nie zgłosi błędu. Wygląda jak test, nie jest testem.
- Wiele warunków bez komunikatu. assertTrue(x == 1 && y.equals(“a”)) pada z „expected true”. Nikt nie wie, który warunek.
- Wartości na sztywno. „180,00 zł” wpisane w test przestaje być prawdą po zmianie ceny w danych testowych.
- Odwrócone argumenty. Oczekiwane i rzeczywiste zamienione miejscami. Test działa, komunikat kłamie.
- Asercje w Page Objectach. Klasa strony, która sama sprawdza wynik, nie nadaje się do testów z innymi oczekiwaniami.
Asercje poza Selenium: API i testy jednostkowe
Asercje działają tak samo w testach API i jednostkowych, a tam wykonują się szybciej i stabilniej niż w interfejsie; w testach API sprawdza się kod odpowiedzi, strukturę i wartości pól oraz czas, w testach jednostkowych wynik funkcji i zgłaszane wyjątki, a większość asercji na logice biznesowej powinna żyć właśnie na tych poziomach.
W Postmanie asercje pisze się w skryptach po żądaniu: kod odpowiedzi 200, pole „rabat” równe 20, czas poniżej 500 milisekund. Opisujemy to w tekstach o Postmanie i o testach integracyjnych i API w Postmanie. W testach jednostkowych asercja porównuje wynik funkcji naliczającej rabat z wartością oczekiwaną dla każdej klasy równoważności, bez przeglądarki i bez serwera. To tam piramida testów każe umieszczać sprawdzenia logiki, o czym piszemy w tekście o piramidzie testów.
Asercje, oczekiwania i budowę frameworka ćwiczymy na szkoleniu Automatyzacja testów Selenium WebDriver, a asercje w testach API na szkoleniu Wprowadzenie do testowania API Postman. Wiedzę dla liderów jakości publikujemy na portalu Strefa QA.
Najczęstsze pytania o asercje
Co to jest asercja?
Asercja to instrukcja w teście, która porównuje wynik rzeczywisty z oczekiwanym i oznacza test jako nieudany, gdy się nie zgadzają. Bez asercji test tylko wykonuje kroki i przechodzi niezależnie od tego, co pokazuje aplikacja.
Czym różni się asercja twarda od miękkiej?
Asercja twarda przerywa test przy pierwszej niezgodności. Asercja miękka zapisuje błąd, pozwala wykonać dalsze kroki i zgłasza wszystkie zebrane błędy na końcu, pod warunkiem wywołania podsumowania (assertAll w JUnit i TestNG). Twardej używa się do warunków wstępnych, miękkiej do wielu pól jednego ekranu.
Jakie asercje są w Selenium?
Selenium samo nie ma asercji. Dostarcza je framework testowy: JUnit 5, TestNG, pytest, NUnit, albo biblioteka AssertJ lub Hamcrest. W testach Selenium sprawdza się nimi tytuł i adres strony, tekst, widoczność i stan elementów, atrybuty, liczbę elementów i brak elementu.
Czym różni się assertEquals w JUnit od TestNG?
Kolejnością argumentów. JUnit oczekuje wartości oczekiwanej jako pierwszej, TestNG jako pierwszej przyjmuje wartość rzeczywistą. Pomyłka nie zmienia wyniku testu, ale odwraca komunikat o błędzie.
Dlaczego asercja pada, choć aplikacja działa?
Najczęściej dlatego, że sprawdza element, zanim aplikacja skończyła go rysować lub ładować dane. Rozwiązaniem jest jawne oczekiwanie na warunek przed asercją, na przykład na konkretny tekst, a nie stałe uśpienie ani zwiększanie limitów czasu.
Co to jest asercja ponawiana?
Asercja, która sama czeka, aż warunek stanie się prawdziwy, do ustalonego limitu czasu. Tak działają asercje w Playwright (expect z toHaveText) i Cypress (should). W Selenium ten sam efekt daje warunek oczekiwania użyty przed zwykłą asercją.
Ile asercji powinien mieć jeden test?
Co najmniej jedną na wyniku biznesowym. Kilka asercji na jednym ekranie jest w porządku, jeśli sprawdzają jedną intencję testu; wtedy warto użyć asercji miękkich. Test, który sprawdza dziesięć niezwiązanych rzeczy, lepiej podzielić.
Czy asercje powinny być w Page Objectach?
Nie. Page Object zwraca wartości ze strony, a test je porównuje z oczekiwaniami. Dzięki temu ta sama klasa strony służy wielu testom z różnymi oczekiwaniami, a padnięcie widać w teście, nie w klasie pomocniczej.
Co zabrać z tego artykułu
01Asercja zamienia skrypt w test. Bez porównania wyniku z oczekiwaniem test przechodzi także wtedy, gdy koszyk pokazuje zero złotych.
02Twarda otwiera test i sprawdza warunki wstępne, miękkie domykają szczegóły jednego ekranu. Miękka bez assertAll nie zgłasza niczego.
03Selenium nie ma własnych asercji. Dostarcza je JUnit, TestNG, pytest albo AssertJ, a różnią się składnią i kolejnością argumentów, nie zasadą.
04Asercja stoi po oczekiwaniu na stan, nie po kliknięciu. Większość „niestabilnych asercji” to asercje przed odpowiedzią serwera.
05Każda asercja ma komunikat z kontekstem i sprawdza jedną rzecz. Przy padnięciu w pipeline to jedyne, co widać.
06Asercje na logice biznesowej należą do testów API i jednostkowych. Przez interfejs sprawdzajcie wynik, który widzi użytkownik.
Wasze testy są zielone, a błędy i tak wychodzą na produkcji? Przejrzymy zestaw pod kątem tego, co naprawdę sprawdza: ile testów kończy się asercją na wyniku biznesowym, ile na obecności elementu, a ile na niczym. Oddamy listę do poprawy w kolejności od najgroźniejszej luki.
Powiązane na blogu Quality Island
- Selenium: co to jest, jak działa i od czego zacząć automatyzację testów
- Explicit Wait vs Implicit Wait: waity w Selenium WebDriver
- Lokalizowanie elementów: selektory w Selenium
- Automatyzacja testów Selenium WebDriver: wzorce projektowe
- Postman: testy integracyjne i testy API w praktyce
- Piramida testów: co to jest, warstwy, proporcje i techniki projektowania testów
Pełna lista źródeł
- ISTQB Glossary, hasła test oracle i expected result
- JUnit 5, User Guide: Assertions
- TestNG, dokumentacja asercji
- pytest, How to write and report assertions
- AssertJ oraz Hamcrest
- Selenium, Waiting Strategies; Playwright, Assertions
- Dane własne Quality Island z projektu dla Argos, e-commerce, liczby potwierdzone przez klienta; ponad 450 000 napisanych testów automatycznych