Wyrażenia regularne w testach automatycznych - praktyczny przewodnik

Testy jednostkowe w Javie: co to jest RangeTest i jak działa. Widać kod testujący zakres liczb.

Napisano przez

Juliusz Król

Opublikowano

4 paź 2026

Spis treści

Gdy trzeba sprawdzić format adresu e-mail, wyciągnąć numer zamówienia z długiego tekstu albo zweryfikować dane w teście automatycznym, zwykłe wyszukiwanie znak po znaku szybko przestaje wystarczać. Właśnie wtedy przydają się wyrażenia regularne, czyli regexy. Poniżej pokazuję, jak działają, z jakich elementów się składają, gdzie pomagają w automatyzacji testów i dlaczego nie zawsze są najlepszym narzędziem.

Regex zamienia opis wzorca tekstowego w praktyczne reguły wyszukiwania

  • Regex to wzorzec opisujący, jaki tekst ma pasować do określonej reguły.
  • Można go używać do wyszukiwania, walidacji, wyciągania i zamiany fragmentów tekstu.
  • W testach automatycznych sprawdza między innymi format danych i zawartość komunikatów.
  • Najważniejsze elementy składni to klasy znaków, kwantyfikatory, kotwice, grupy i alternatywy.
  • Regex nie rozumie znaczenia tekstu, a jego składnia może się różnić zależnie od języka i silnika.

Wyjaśnienie, regex co to jest: schemat dopasowania tekstu z grupami src, dst i mode.

Regex to wzorzec, a nie zwykły ciąg znaków

Regex, od angielskiego regular expression, jest instrukcją opisującą, jak powinien wyglądać szukany tekst. Nie wskazuje wyłącznie konkretnego słowa. Może określać na przykład, że tekst ma zaczynać się od dwóch liter, zawierać pięć cyfr i kończyć się określonym sufiksem.

Prosty wzorzec kot znajdzie dokładnie taki ciąg znaków. Z kolei k.t dopasuje między innymi „kot”, „kat” i „kit”, ponieważ kropka oznacza dowolny pojedynczy znak. To właśnie odróżnia wyrażenie regularne od klasycznego wyszukiwania tekstu.

W praktyce regex może pełnić cztery różne funkcje:

  • wyszukiwanie określonego fragmentu w większym tekście,
  • walidacja, czyli sprawdzenie, czy dane mają właściwy format,
  • ekstrakcja informacji, na przykład numeru faktury z komunikatu,
  • zamiana znalezionych fragmentów na inny tekst.

Ważne rozróżnienie polega na tym, że regex sprawdza głównie strukturę danych, a nie ich prawdziwość. Wzorzec może potwierdzić, że tekst przypomina adres e-mail, ale nie sprawdzi, czy skrzynka rzeczywiście istnieje. W automatyzacji testów takie rozdzielenie ma duże znaczenie.

Jak czytać podstawową składnię wyrażeń regularnych

Na początku symbole wyglądają jak przypadkowy ciąg znaków, ale większość wzorców opiera się na kilku powtarzalnych elementach. Ja zwykle czytam regex od lewej do prawej, rozbijając go na małe reguły zamiast próbować zapamiętać całość naraz.

Element Znaczenie Przykład
. Dowolny pojedynczy znak k.t
\d Cyfra, zwykle od 0 do 9 \d{4}
\s Biały znak, na przykład spacja lub tabulator \s+
[abc] Jeden znak z podanego zbioru [abc]
[^abc] Jeden znak spoza podanego zbioru [^0-9]
+ Co najmniej jedno wystąpienie \d+
* Zero lub więcej wystąpień \s*
? Zero lub jedno wystąpienie -?
{n} Dokładnie n wystąpień \d{5}
{n,m} Od n do m wystąpień \d{2,4}
^ i $ Początek i koniec tekstu ^\d{5}$
| Alternatywa, czyli „lub” kot|pies

Wzorzec ^\d{2}-\d{3}$ pasuje do prostego zapisu kodu pocztowego, na przykład 12-345. Znaki ^ i $ są tu bardzo ważne, ponieważ wymagają dopasowania całego tekstu, a nie tylko jego fragmentu.

Grupy i przechwytywanie danych

Nawiasy okrągłe pozwalają grupować elementy. Wzorzec (\d{4})-(\d{2})-(\d{2}) może znaleźć datę w formacie rok-miesiąc-dzień, a poszczególne grupy pozwalają później odczytać rok, miesiąc i dzień osobno.

Jeżeli grupowanie nie ma służyć przechwytywaniu, można użyć składni (?:...). To drobny szczegół, ale w większych wzorcach pomaga ograniczyć liczbę niepotrzebnych wyników i poprawia czytelność kodu.

Znaki specjalne wymagają ucieczki

Niektóre symbole mają w regexie specjalne znaczenie. Kropka oznacza dowolny znak, więc aby wyszukać prawdziwą kropkę, trzeba zapisać ją jako \.. Podobnie zapis \? oznacza dosłowny znak zapytania.

To jeden z błędów, które widuję najczęściej. Autor chce znaleźć adres internetowy lub nazwę pliku, ale zapomina, że kropka w regexie nie jest zwykłą kropką. W efekcie wzorzec dopasowuje więcej danych, niż powinien.

Jak regex wspiera automatyzację testów

W automatyzacji testów wyrażenia regularne są przydatne wszędzie tam, gdzie wynik może się zmieniać, ale jego format pozostaje przewidywalny. Test nie musi wtedy oczekiwać jednej sztywnej wartości. Może sprawdzić, czy odpowiedź spełnia określoną regułę.

Sprawdzanie komunikatów i identyfikatorów

Załóżmy, że aplikacja wyświetla komunikat Zamówienie #A83921 zostało utworzone. Zamiast porównywać cały tekst znak po znaku, można sprawdzić wzorzec Zamówienie #[A-Z]\d{5} zostało utworzone.

Takie podejście jest odporne na zmianę konkretnego numeru zamówienia, ale nadal wykryje błędny format identyfikatora. To dobry przykład testu, który sprawdza regułę biznesową, a nie przypadkową wartość wygenerowaną podczas jednego uruchomienia.

Walidowanie danych wejściowych

Regex może pomóc sprawdzić, czy pole zawiera numer telefonu, kod pocztowy, identyfikator klienta albo datę. Przykładowy wzorzec dla polskiego kodu pocztowego wygląda tak:

^\d{2}-\d{3}$

W teście warto sprawdzić zarówno przypadki poprawne, jak i błędne. Dla powyższej reguły będą to między innymi 00-950, 12-345, 12345 oraz 12 345. Ostatnie dwa przykłady powinny zostać odrzucone, jeśli aplikacja wymaga zapisu z łącznikiem.

Analizowanie odpowiedzi API i logów

W testach integracyjnych regex może wyciągać token, identyfikator lub numer wersji z odpowiedzi tekstowej. Trzeba jednak uważać, aby nie zastępować nim parsera JSON, XML czy HTML. Jeśli dane mają formalną strukturę, dedykowany parser jest bezpieczniejszy i czytelniejszy.

Regex sprawdza się natomiast przy logach, których format jest prosty i powtarzalny. Wzorzec status=(\d{3}) pozwoli znaleźć kod odpowiedzi HTTP, a grupa przechwytująca umożliwi późniejsze porównanie go z oczekiwaną wartością.

Przykład w Pythonie

W Pythonie do pracy z wyrażeniami regularnymi służy moduł re. Prosty test może wyglądać tak:

import re

komunikat = "Zamówienie #A83921 zostało utworzone"
wzorzec = r"Zamówienie #[A-Z]\d{5} zostało utworzone"

assert re.fullmatch(wzorzec, komunikat)

Użycie fullmatch jasno komunikuje, że cały tekst ma pasować do wzorca. To bezpieczniejsze niż ogólne wyszukiwanie, które mogłoby uznać test za zaliczony tylko dlatego, że poprawny fragment znalazł się w środku błędnego komunikatu.

Wyszukiwanie, walidacja i zamiana wymagają innych podejść

Ten sam regex może być używany do różnych celów, ale nie każdy sposób dopasowania daje taki sam efekt. Najpierw ustalam, czy chcę znaleźć fragment, potwierdzić cały tekst, czy zmienić dane. Dopiero potem dobieram funkcję i kotwice.

Cel Typowe podejście Na co uważać
Wyszukanie fragmentu Wyszukiwanie bez kotwic Może znaleźć dopasowanie w środku dłuższego tekstu
Walidacja całej wartości ^...$ lub odpowiednik pełnego dopasowania Różnice w obsłudze końca linii między silnikami
Wyciągnięcie danych Grupy przechwytujące Zbyt wiele grup utrudnia późniejsze utrzymanie
Zamiana fragmentu Regex oraz tekst zastępczy Referencje do grup mają różną składnię w językach

Przykładowo wzorzec \d+ znajdzie liczby w zdaniu, ale nie sprawdzi, czy całe zdanie składa się wyłącznie z cyfr. Do walidacji całej wartości potrzebny będzie zapis ^\d+$ albo funkcja przeznaczona do pełnego dopasowania.

Przy zamianie można usunąć nadmiarowe spacje wzorcem \s+ i zastąpić je pojedynczą spacją. To praktyczne przy czyszczeniu danych, ale przed wykonaniem operacji na dużym zbiorze zawsze testuję przykłady brzegowe. Jedna zbyt szeroka reguła może zmienić także fragmenty, które miały pozostać nietknięte.

Gdzie wyrażenia regularne mają ograniczenia

Regex jest bardzo dobry w rozpoznawaniu prostych wzorców, ale nie jest uniwersalnym językiem do analizy tekstu. Nie rozumie kontekstu, znaczenia słów ani relacji między elementami dokumentu. Dlatego próba napisania jednego ogromnego wzorca często kończy się kodem trudnym do sprawdzenia i jeszcze trudniejszym do naprawy.

Walidacja adresów e-mail

Da się stworzyć regex, który odrzuci oczywiście błędne adresy e-mail, na przykład pozbawione znaku @. Nie warto jednak próbować odwzorowywać w nim całej formalnej specyfikacji poczty. W praktyce lepiej użyć rozsądnej walidacji formatu, a istnienie adresu potwierdzić przez proces aplikacyjny, na przykład wiadomość aktywacyjną.

HTML, XML i dane zagnieżdżone

Do przetwarzania HTML lub XML lepiej użyć parsera. Regex może zadziałać na bardzo prostym, kontrolowanym fragmencie, ale szybko zawodzi przy atrybutach, zagnieżdżeniach, komentarzach i nietypowym formatowaniu. W testach interfejsu wybieram selektory DOM, role i stabilne identyfikatory zamiast wycinania elementów z kodu strony za pomocą skomplikowanego wzorca.

Wydajność i ryzyko ReDoS

Niektóre złożone regexy mogą działać bardzo długo na odpowiednio przygotowanym tekście. Zjawisko to bywa określane jako catastrophic backtracking, czyli gwałtowny wzrost liczby prób dopasowania. Ma znaczenie zwłaszcza wtedy, gdy wzorzec analizuje dane przesyłane przez użytkownika lub używane w publicznym API.

Żeby ograniczyć ryzyko, unikam niepotrzebnie zagnieżdżonych kwantyfikatorów, testuję długie i nietypowe dane oraz ustawiam limity czasu. Regex używany w teście powinien być nie tylko poprawny, ale też przewidywalny pod względem wydajności.

Przeczytaj również: Playwright po polsku - Stabilne testy E2E od podstaw!

Różnice między silnikami

Składnia nie jest identyczna w JavaScript, Pythonie, Javie, PHP czy narzędziach wykorzystujących PCRE. Różnić się mogą między innymi flagi, obsługa znaków Unicode, lookbehind oraz znaczenie skrótów takich jak \w.

Jeśli test ma działać w kilku technologiach, sprawdzam wzorzec bezpośrednio w każdym używanym środowisku. Szczególnie ostrożnie traktuję \w, bo jego zakres może zależeć od silnika i trybu Unicode. Przy danych użytkownika często bezpieczniej jawnie wskazać dozwolone zakresy znaków.

Jak budować regex, który da się utrzymać

Najlepszy wzorzec to nie zawsze najkrótszy wzorzec. W automatyzacji testów liczy się przede wszystkim to, czy po kilku miesiącach inna osoba zrozumie, co dokładnie jest sprawdzane i dlaczego reguła ma taką postać.

  1. Zdefiniuj cel i zdecyduj, czy chodzi o wyszukiwanie, pełną walidację czy ekstrakcję.
  2. Rozpisz poprawne i błędne przykłady, zanim zaczniesz skracać składnię.
  3. Dodaj kotwice, jeśli dopasowanie ma obejmować całą wartość.
  4. Ograniczaj zakres zamiast używać szerokich konstrukcji typu .* bez wyraźnej potrzeby.
  5. Opisz wzorzec komentarzem albo nazwij stałą tak, aby wskazywała jego przeznaczenie.
  6. Testuj przypadki brzegowe, w tym pusty tekst, bardzo długą wartość, znaki diakrytyczne i dodatkowe spacje.

W testach automatycznych szczególnie dobrze działa zestaw przypadków pozytywnych i negatywnych. Samo sprawdzenie, że poprawny kod przechodzi, nie daje pewności, że aplikacja odrzuca kod z literówką, złą długością albo niewłaściwym separatorem.

Regex warto też przechowywać poza logiką testu, jeśli jest używany w kilku miejscach. Dzięki temu zmiana formatu identyfikatora nie wymaga poprawiania wielu niemal identycznych fragmentów. Dla bardziej złożonych reguł pomocne są testy jednostkowe samego wzorca, niezależne od całego interfejsu aplikacji.

Od prostego wzorca do stabilnego testu

Najkrócej mówiąc, wyrażenie regularne opisuje kształt tekstu. Może znaleźć numer, sprawdzić kod, wyciągnąć fragment odpowiedzi API albo uelastycznić asercję w teście automatycznym. Jego siła wynika z prostych symboli, które można łączyć w precyzyjne reguły.

Najbezpieczniej zaczynać od małego wzorca, testować go na realnych danych i dopiero później dodawać wyjątki. Gdy dane mają złożoną strukturę, lepiej sięgnąć po parser lub selektor właściwy dla danego formatu. Regex robi największą różnicę wtedy, gdy rozwiązuje konkretny problem, a nie wtedy, gdy zastępuje całe narzędzie do analizy danych.

FAQ - Najczęstsze pytania

Wyszukiwanie fragmentu może znaleźć dopasowanie w środku dłuższego tekstu. Walidacja całej wartości wymaga kotwic ^ i $ albo funkcji pełnego dopasowania, takiej jak re.fullmatch w Pythonie. Dlatego wzorzec ^\d+$ sprawdza, czy cała wartość składa się z cyfr, podczas gdy \d+ znajdzie cyfry także w zdaniu.

Zamiast porównywać cały komunikat ze stałą wartością, można opisać jego przewidywalny format. Dla tekstu Zamówienie #A83921 zostało utworzone sprawdzi się wzorzec Zamówienie #[A-Z]\d{5} zostało utworzone. Taki test akceptuje różne numery zamówień, ale nadal wykrywa błędną długość lub format identyfikatora.

Regex nadaje się do prostych i powtarzalnych fragmentów tekstu, na przykład logów zawierających status=200. Przy formalnie ustrukturyzowanych danych lepiej użyć parsera JSON lub XML, a w testach interfejsu selektorów DOM, ról i stabilnych identyfikatorów. Regex szybko staje się zawodny przy zagnieżdżeniach, atrybutach, komentarzach i nietypowym formatowaniu.

Należy unikać niepotrzebnie zagnieżdżonych kwantyfikatorów, testować bardzo długie i nietypowe dane oraz ustawiać limity czasu. Złożone wzorce mogą powodować catastrophic backtracking i wykonywać się bardzo długo. Trzeba też sprawdzać regex bezpośrednio w każdym używanym środowisku, ponieważ silniki różnią się między innymi obsługą Unicode, lookbehind i skrótów takich jak \w.

Oceń artykuł

Ocena: 4.50 Liczba głosów: 2

Tagi:

regex walidacja ekstrakcja parsery redos

Udostępnij artykuł

Juliusz Król

Juliusz Król

Nazywam się Juliusz Król i od 4 lat zajmuję się automatyzacją testów oraz zapewnieniem jakości oprogramowania. Moje zainteresowanie tymi tematami zrodziło się z potrzeby zrozumienia, jak technologia może wspierać procesy tworzenia oprogramowania i jak kluczowe jest zapewnienie jego wysokiej jakości. W swoich tekstach skupiam się na praktycznych rozwiązaniach, które pomagają innym w efektywnym wdrażaniu automatyzacji oraz w rozwiązywaniu problemów związanych z jakością. Dzięki mojemu doświadczeniu staram się przekazywać wiedzę w sposób przystępny i zrozumiały, porównując różne podejścia oraz analizując aktualne trendy w branży. Zawsze dbam o to, aby moje materiały były rzetelne, aktualne i pomocne dla czytelników, którzy pragną rozwijać swoje umiejętności w obszarze QA.

Napisz komentarz