Testy w pipeline: kiedy unit, kiedy integration, a kiedy e2e

3
243
4/5 - (4 votes)

Nawigacja:

Po co układać strategię testów w pipeline zamiast „po prostu testować”

Dlaczego „jakieś testy” w CI/CD to za mało

W wielu zespołach testy w pipeline CI/CD istnieją tylko formalnie. Coś się uruchamia, coś czasem się wywali, ale niewiele z tego wynika. Jedni traktują czerwony pipeline jak techniczną ciekawostkę, inni jak uciążliwą przeszkodę, którą trzeba jak najszybciej „obejść”. Zaufanie do testów spada, a wraz z nim sens całej automatyzacji.

Kluczowy problem polega na tym, że bez przemyślanej strategii trudno odpowiedzieć na podstawowe pytania: które testy mają prawo zablokować wdrożenie, jakie rodzaje błędów mają być wykrywane na jakim etapie oraz ile czasu może to zająć. Gdy wszystko jest wrzucone do jednego worka „tests”, pipeline staje się nieprzewidywalny. Raz zielony, raz czerwony, bez jasnego powodu, z losowymi przerwami w delivery.

Strategia testów w pipeline to świadoma decyzja: co, kiedy i jak testować, aby wynik builda był realnym sygnałem jakości, a nie loterią. Dzięki temu zespół zaczyna traktować pipeline jako wspólne narzędzie do ochrony produkcji, a nie jako narzucony obowiązek z zewnątrz.

Obawy: wolny pipeline, ciągłe „czerwone” i frustracja zespołu

Najczęściej słyszane obawy przy wprowadzaniu bardziej rozbudowanych testów w CI/CD to:

  • „Pipeline będzie trwał za długo” – gdy każdy merge request będzie czekał kilkadziesiąt minut na wynik, deweloperzy zaczną szukać skrótów i wyłączeń.
  • „Ciągle świeci się na czerwono” – flakiness, złej jakości testy e2e, niestabilne środowiska testowe sprawiają, że czerwony status przestaje mieć znaczenie.
  • „Testy blokują funkcjonalny rozwój” – przy braku priorytetów testy próbują łapać wszystko naraz, zamiast skupić się na najbardziej krytycznych obszarach.

Te obawy są uzasadnione, ale w znacznej części wynikają z jednego: braku rozłożenia ciężaru na odpowiednie typy testów. Jeśli większość logiki weryfikowana jest dopiero w testach e2e, pipeline będzie zarówno wolny, jak i kruchy. Gdy ta sama logika zostanie objęta testami jednostkowymi i integracyjnymi, testy e2e mogą być nieliczne, szybkie i bardziej stabilne.

Od „mamy testy” do „pipeline realnie chroni produkcję”

Skuteczny pipeline nie tylko odpalają testy, ale przede wszystkim redukuje ryzyko regresji na produkcji. Różnica między „mamy testy” a „pipeline chroni produkcję” jest podobna do różnicy między posiadaniem alarmu w domu a faktycznym jego uzbrajaniem i reagowaniem na sygnały.

Pipeline, który realnie chroni produkcję, ma kilka charakterystycznych cech:

  • Przewidywalny czas wykonania – zespół wie, że wynik dla merge requestu dostanie w określonym, akceptowalnym czasie (np. 5–15 minut dla głównych testów).
  • Wyraźne quality gates – wiadomo, które typy testów blokują merge/deploy, a które są dodatkowymi sygnałami (np. raport jakościowy, ale bez twardego bloku).
  • Testy odzwierciedlają realne ryzyko biznesowe – najważniejsze ścieżki użytkownika i krytyczne reguły biznesowe są zabezpieczone przynajmniej dwoma warstwami: unit/integration i wybranymi scenariuszami e2e.

Tak zaprojektowany pipeline przestaje być dekoracją. Zespół wie, że przejście przez niego w kolorze zielonym znacznie ogranicza szansę awarii w produkcji – i to w konkretnych obszarach.

Przesuwanie kosztu błędów „w lewo”

Bez zautomatyzowanych testów w pipeline większość problemów wychodzi późno: na środowisku testowym, stagingu, a najgorzej – już po wdrożeniu. Koszt naprawy rośnie wtedy nie tylko przez konieczność hotfixów, ale także przez utratę zaufania użytkowników, pośpiech i bałagan w procesie wydawniczym.

Dobrze ułożona strategia testów w CI/CD pozwala przesunąć wykrywanie błędów jak najbliżej momentu ich wprowadzenia. Idealnie, jeśli zła zmiana zostanie złapana już na etapie commitu (pre-push hooks, szybkie testy jednostkowe), a najpóźniej na etapie głównego pipeline dla merge requestu.

Im wcześniej błąd zostanie znaleziony, tym taniej i spokojniej można go naprawić. Taka zmiana perspektywy – z „naprawiamy po fakcie” na „powstrzymujemy regresje zanim dotrą do produkcji” – jest jednym z największych zysków dobrze ułożonej piramidy testów w pipeline.

Co zrobić, gdy projekt już istnieje i „żyje własnym życiem”

W wielu zespołach sytuacja startowa jest daleka od idealnej: monolit bez testów, setki testów e2e z Selenium, niestabilne środowisko testowe, brak jasnych zasad. Zaczynanie od zera nie wchodzi w grę, bo system działa i musi działać dalej.

W takiej sytuacji sensowne jest podejście iteracyjne:

  • Krok 1: inwentaryzacja – spis istniejących testów (unit, integration, e2e), ocena ich czasu wykonania i awaryjności, identyfikacja duplikatów.
  • Krok 2: szybkie zwycięstwa – separacja najszybszych, najbardziej stabilnych testów jednostkowych i uruchomienie ich jako pierwszej warstwy w pipeline.
  • Krok 3: czyszczenie e2e – usuwanie lub refaktoryzacja oczywiście zbędnych, dublujących lub ekstremalnie niestabilnych scenariuszy e2e.
  • Krok 4: uzupełnianie warstwy integracyjnej – stopniowe dodawanie sensownych testów integracyjnych tam, gdzie brakuje pokrycia pomiędzy unit a e2e.

Transformacja strategii testów w istniejącym projekcie nie musi być rewolucją. Znacznie skuteczniejsze są małe, konsekwentne kroki, które krok po kroku poprawiają stabilność pipeline, zamiast zatrzymywać delivery na kilka tygodni „porządków technicznych”.

Krótkie przypomnienie: unit, integration, e2e – o co w nich chodzi praktycznie

Testy jednostkowe: najmniejszy klocek, największa dźwignia

Test jednostkowy (unit test) sprawdza pojedynczą, wyizolowaną jednostkę logiki – najczęściej funkcję, metodę, niewielki komponent. Chodzi o to, by dany fragment kodu zachowywał się w przewidywalny sposób dla określonych wejść, bez udziału zewnętrznych zasobów (bazy, sieci, systemu plików).

Kluczowe cechy testów jednostkowych:

  • Szybkość – dobrze napisane unity potrafią przejść w setkach lub tysiącach w ciągu sekund.
  • Izolacja – brak zależności od zewnętrznego środowiska; jeśli coś się psuje, problem jest albo w testowanym kodzie, albo w samym teście.
  • Deterministyczność – to samo wejście zawsze daje ten sam wynik, bez losowości i zależności od czasu.

Praktyczny przykład unit testu: funkcja licząca zniżkę dla koszyka na podstawie regulaminu promocji. Nie potrzebuje bazy, nie potrzebuje API – jedynie danych wejściowych i oczekiwanych rezultatów. Taki test daje jasny sygnał, czy logika biznesowa nadal jest zgodna z wymaganiami.

Testy integracyjne: jak elementy dogadują się ze sobą

Test integracyjny sprawdza współdziałanie kilku komponentów naraz – modułów w monolicie, serwisu i bazy danych, serwisu i message brokera, dwóch mikroserwisów komunikujących się po HTTP. Tu celem nie jest już izolacja, ale weryfikacja kontraktów i konfiguracji.

Charakterystyka testów integracyjnych:

  • Wolniejsze od unitów – wymagają podniesienia bazy, brokera, czasem całego kontenera z aplikacją.
  • Wrażliwość na środowisko – konfiguracja, migracje, dane początkowe mają znaczenie.
  • Sprawdzanie konfiguracji – czy mappingi ORM są poprawne, czy kolejki istnieją, czy API zwraca dane w oczekiwanym formacie.

Przykład: test, który uruchamia moduł aplikacji z prawdziwą bazą (np. w Dockerze) i sprawdza, czy zapis i odczyt zamówienia działa poprawnie, z uwzględnieniem transakcji, walidacji i indeksów. To jest już wyraźnie inny poziom niż sama logika biznesowa – tu liczy się interakcja z infrastrukturą.

Testy end-to-end: cały system oczami użytkownika

Test end-to-end (e2e) w kontekście pipeline CI/CD oznacza scenariusz przechodzący przez możliwie pełną ścieżkę użytkownika lub procesu biznesowego, najczęściej przez UI (przeglądarkę) albo publiczne API. Celem jest sprawdzenie, że wszystkie warstwy systemu – od frontendu, przez backend, po bazę i integracje zewnętrzne – razem realizują biznesowy cel.

Właściwości testów e2e:

  • Najwolniejsze – w grę wchodzą przeglądarka, sieć, wiele serwisów, czasem zewnętrzne API.
  • Najbardziej kruche – zależne od stabilności środowiska, danych testowych, opóźnień, kolejności uruchamiania.
  • Najbliżej realnego zachowania – dobrze napisany scenariusz e2e imituje to, co realnie robi użytkownik lub system zewnętrzny.

Przykład: użytkownik otwiera stronę sklepu, loguje się, dodaje produkt do koszyka, przechodzi przez checkout, otrzymuje potwierdzenie zamówienia i e-mail. Ten scenariusz dotyka wielu komponentów naraz i potwierdza, że krytyczna ścieżka zakupowa faktycznie działa.

To samo zachowanie, różne poziomy testów

To samo wymaganie biznesowe można sprawdzić na kilku poziomach. Na przykład: „Rabat 10% dla zamówień powyżej określonej kwoty”.

  • Unit – test funkcji calculateDiscount(), która na podstawie kwoty koszyka zwraca wysokość rabatu.
  • Integration – test modułu zamówień z prawdziwą bazą danych, który sprawdza, czy rabat jest poprawnie zapisywany razem z zamówieniem i naliczany również przy odczycie.
  • e2e – scenariusz UI lub API, w którym użytkownik faktycznie składa zamówienie, widzi naliczony rabat na podsumowaniu i otrzymuje fakturę z prawidłową kwotą.

Strategia testów w pipeline polega m.in. na tym, na którym poziomie zapewnić podstawową ochronę, a na którym tylko potwierdzić, że całość działa razem. Najczęściej opłaca się maksymalnie przesunąć logikę do unitów i wybranych testów integracyjnych, a e2e zostawić jako cienką, krytyczną warstwę.

Ekran laptopa z kodem i debugerem w środowisku developerskim
Źródło: Pexels | Autor: Daniil Komov

Piramida testów vs. „odwrócony lejek” – konsekwencje w CI/CD

Założenia piramidy testów

Klasyczna piramida testów mówi: najwięcej testów jednostkowych u podstawy, mniej testów integracyjnych pośrodku, najmniej testów e2e na szczycie. Ten układ ma bardzo konkretne uzasadnienie w kontekście CI/CD:

  • unity są szybkie i stabilne – można ich mieć setki lub tysiące, bez zabijania pipeline,
  • testy integracyjne są droższe – warto używać ich tam, gdzie faktycznie mają sprawdzać integracje, a nie dublować unitów,
  • e2e są najdroższe i kruche – powinny obejmować tylko krytyczne ścieżki.

Dobrze zaprojektowana piramida sprawia, że pipeline w większości przypadków przerywa się szybko. Jeśli błąd jest oczywisty (np. zepsuta logika biznesowa), złapią go unity. Jeśli to problem z konfiguracją lub bazą – testy integracyjne. Dopiero rzadkie problemy „na styku” całego systemu przechodzą do warstwy e2e.

Odwrócony lejek: gdy większość testów to e2e

W praktyce wiele projektów kończy z tzw. odwróconym lejkiem: niewiele unitów, trochę integracyjnych i ogromna liczba testów e2e przez UI. Konsekwencje dla CI/CD są szybko odczuwalne:

  • Pipeline trwa wieki – każdy merge wymaga przejścia setek scenariuszy e2e uruchamianych sekwencyjnie lub na ograniczonej liczbie agentów.
  • Flaky tests – im więcej testów e2e, tym większe ryzyko przypadkowych awarii niezwiązanych ze zmianą kodu.
  • Brak jasnej informacji zwrotnej – gdy pada e2e, często trudno od razu powiedzieć, czy zawinił frontend, backend, środowisko, dane testowe czy sam test.

Zespół przestaje ufać wynikom pipeline, bo „i tak się coś losowo wysypie”. Naturalną reakcją jest wyłączanie części testów, ignorowanie czerwieni lub obchodzenie pipeline (np. bezpośrednie deploye na produkcję), co znów zwiększa ryzyko awarii.

Wpływ struktury testów na czas i stabilność pipeline

Stosunek liczby testów na poszczególnych poziomach wprost przekłada się na czas wykonania i stabilność pipeline. Dlatego przy projektowaniu strategii testów warto myśleć nie tylko o „pokryciu”, ale i o koszcie uruchomienia każdego typu testów.

Prosty sposób patrzenia na to zagadnienie:

Progi w pipeline: jak zdecydować, co uruchamiać kiedy

Najczęstszy dylemat przy projektowaniu pipeline nie brzmi „czy pisać testy?”, tylko: co odpalać przy każdym commicie, a co zostawić na później. Jeśli do tej pory wszystko leciało zawsze „na raz”, nic dziwnego, że buildy trwają pół godziny i wszyscy się frustrują.

Pomaga myślenie o pipeline jako o ciągu coraz droższych progów, które kod musi pokonać, żeby dolecieć do produkcji. Im wyższy próg, tym mniej zmian do niego dociera.

  • Próg 1 – testy lokalne / pre-commit: podstawowe unity, lint, szybkie checki typów. Idealnie, jeśli da się je uruchomić w sekundach na laptopie.
  • Próg 2 – CI na branchu: pełny zestaw testów jednostkowych i sensowna część integracyjnych. Celem jest wczesne odrzucenie większości problemów.
  • Próg 3 – pre-merge / pre-release: pełny pakiet integracyjny i — w zależności od projektu — podzbiór e2e (np. tylko najbardziej krytyczne ścieżki).
  • Próg 4 – nightly / regresja: szeroka siatka e2e i ciężkie scenariusze, które nie muszą chodzić przy każdym merge’u.

Takie podejście odczarowuje pytanie „kiedy uruchamiać e2e?”. Zamiast jednej, magicznej odpowiedzi pojawia się bardzo praktyczne: „zawsze, ale nie zawsze wszystkie”.

Heurystyka: jaki typ testu dla jakiej zmiany

Kiedy kod jest mały i zespół się zna, decyzje o poziomach testów często są intuicyjne. W większych projektach pomaga zestaw prostych zasad – nie po to, by kogoś ograniczać, tylko by ujednolicić oczekiwania.

Przykładowa heurystyka, którą da się wdrożyć bez rewolucji:

  • Zmiana w czystej logice domenowej (np. kalkulacje, walidacje, reguły biznesowe):
    minimum: nowe lub zmienione testy jednostkowe,
    opcjonalnie: integracyjne tylko wtedy, gdy logika „przecieka” do warstwy bazy, kolejek itp.
  • Zmiana w dostępie do danych / konfiguracji infrastruktury (repozytoria, ORM, connection stringi, mapowania):
    minimum: testy integracyjne sprawdzające zapis/odczyt lub komunikację,
    — unity mają sens głównie przy skomplikowanych mapperach czy transformacjach.
  • Zmiana w kontraktach API / komunikacji między serwisami:
    minimum: testy kontraktowe / integracyjne dla obu stron,
    — e2e potrzebne tylko, jeśli zmiana dotyka krytycznej ścieżki biznesowej.
  • Zmiana w UI bez zmiany logiki backendu:
    minimum: testy komponentów (często traktowane jak „wyższe unity”) i snapshoty,
    — e2e tylko wtedy, gdy dotyczy to głównych scenariuszy użytkownika (np. proces zakupu, logowanie).

Jeśli zespół ma taką „mapę”, łatwiej bronić decyzji: czemu w tym zadaniu powstały wyłącznie unity, a gdzie indziej dokładane są od razu e2e.

Kiedy zatrzymać się na unitach, a kiedy iść wyżej

Sytuacje, w których unit testy w zupełności wystarczą

Nie każdy fragment systemu potrzebuje pełnej orkiestry testów. Są miejsca, gdzie mocne pokrycie unitami daje prawie cały zysk, a dokładanie integracji czy e2e nie wnosi wiele.

Typowe obszary:

  • Czysta logika domenowa, bez pobocznych efektów: liczenie rabatów, reguły scoringu, walidacje formularzy, silniki reguł.
  • Funkcje pomocnicze: parsery, formattery, konwertery jednostek, transformacje danych.
  • Proste komponenty prezentacyjne, które głównie renderują dane w określony sposób, bez złożonych interakcji.

W tych miejscach integracja z infrastrukturą często nie istnieje albo jest tak prosta, że test integracyjny nic nie dodaje. Dużo większą dźwignię daje rozbudowanie scenariuszy unitowych: dane brzegowe, scenariusze błędne, nietypowe kombinacje parametrów.

Sygnalizatory, że samych unitów jest za mało

Jeżeli pojawiają się takie symptomy:

  • „U nas wszystko zielone, ale na testach integracyjnych innego zespołu co chwilę coś pada”.
  • „Na localu przechodzi, na środowisku testowym wyjątek z bazy / brokera / konfiguracji”.
  • „Zmiana w mapowaniu encji rozwaliła pół raportowania, a unity milczą”.

— to zwykle znak, że brakuje testów wyższego poziomu. Logika jest sprawdzona, ale jej „dostarczenie” do bazy, innego serwisu czy UI już nie.

W takiej sytuacji najpierw sięga się po testy integracyjne, bo to one łapią problemy z ORM, migracjami, kolejkami, konfiguracją. E2e zostawia się na koniec, gdy potrzebne jest potwierdzenie, że cała ścieżka, od kliknięcia w UI po zapis w bazie, działa w komplecie.

Jak sensownie dobrać testy integracyjne

Integracja, ale czego z czym?

Termin „test integracyjny” bywa tak szeroki, że każdy rozumie go inaczej. Dla pipeline ważne jest, by były one konkretne i powtarzalne. Dużo pomaga odpowiedź na proste pytanie: „Jaką integrację faktycznie weryfikujemy?”.

Najczęstsze typy integracji w praktyce:

  • Serwis ↔ baza danych: poprawność zapisu/odczytu, transakcje, indeksy, migracje.
  • Serwis ↔ message broker: publikacja i konsumpcja zdarzeń, format payloadu, routing.
  • Serwis ↔ serwis (HTTP, gRPC): zgodność kontraktów, kody odpowiedzi, mapowanie błędów.
  • Serwis ↔ zewnętrzne API: tutaj częściej stosuje się testy kontraktowe z mockiem dostawcy niż „prawdziwe” połączenia.

Jeśli test integracyjny nie potrafi odpowiedzieć jasno: „co dokładnie sprawdzam?”, zwykle zaczyna dryfować w stronę pół-e2e — długi, niestabilny, a dalej bez jasnego sygnału, gdzie leży problem.

Strategia: wąskie, ale głębokie testy integracyjne

Dobre testy integracyjne są wąskie w zakresie (dotykają jednego modułu / serwisu), ale głębokie w tym, jak przechodzą przez infrastrukturę. Przykładowa strategia dla serwisu obsługującego zamówienia:

  • Zamiast jednego, ogromnego testu „od stworzenia zamówienia po wystawienie faktury” — kilka węższych:
    — zapis i odczyt zamówienia w bazie (różne stany, pola opcjonalne),
    — publikacja zdarzenia „OrderCreated” do brokera i jego poprawny format,
    — obsługa zdarzenia „PaymentConfirmed” i aktualizacja statusu.
  • Do tego proste dane startowe: minimalny seed bazy i broker „czysty” na starcie każdego scenariusza.

Takie testy są już droższe niż unity, ale dają konkretną informację: „nie działa zapis w bazie”, „event ma zły format”, „konsument się wywala przy duplikatach”. E2e mogą później tylko potwierdzić, że cały proces biznesowy z tych klocków się składa.

Zbliżenie monitora z kodem i danymi bezpieczeństwa w pipeline testowym
Źródło: Pexels | Autor: Tima Miroshnichenko

Testy e2e: kiedy są naprawdę potrzebne

Kryteria włączenia scenariusza do zestawu e2e w CI

Jeśli w projekcie e2e rozmnożyły się bez kontroli, trudno potem powiedzieć, które są faktycznie potrzebne. Przy porządkach pomaga prosty filtr. Do stałego zestawu e2e w pipeline dobrze trafiają scenariusze, które:

  • Dotyczą kluczowego przychodu lub ryzyka: ścieżka zakupowa, logowanie, reset hasła, potwierdzenie przelewu, wysyłka krytycznych powiadomień.
  • Przekraczają kilka domen lub serwisów: zmiana statusu zamówienia uruchamia wysyłkę maila i zapis do systemu fakturowania.
  • Nie dają się dobrze pokryć niższymi poziomami: np. interakcje w UI, które są wynikiem kombinacji wielu warstw.
  • Mają historię regresji: miejsce, które „ciągle się psuje”, dopóki nie zostanie realnie zabezpieczone.

Reszta scenariuszy e2e nie musi od razu wylecieć do kosza. Część można:

  • przekształcić w testy API (bliżej integracji niż pełnego e2e),
  • odpalać rzadziej (nightly, przed dużym releasem),
  • rozbić na kilka integracyjnych, jeśli głównym celem jest np. weryfikacja mapowań lub przepływu danych.

Stabilność e2e a zaufanie do pipeline

Główny problem z e2e nie polega na tym, że są wolne, tylko że często są niemożliwe do zdiagnozowania. Test raz przechodzi, raz nie. Raz nie wystartował kontener, innym razem timeout, jeszcze innym brak danych startowych.

Aby scenariusze e2e w pipeline miały sens, potrzebują kilku trwałych zasad:

  • Izolacja danych — każdy test przygotowuje sobie dane i sprząta po sobie (lub korzysta z resetu środowiska między scenariuszami).
  • Brak zależności od kolejności — scenariusze nie polegają na tym, że „poprzedni test założył użytkownika”.
  • Wyraźne time-outy i retry tam, gdzie to realne — system faktycznie może mieć opóźnienia, ale nie powinien wisieć 3 minuty bez informacji.
  • Ograniczony zakres asercji — test skupia się na istotnym zachowaniu, a nie na każdym pixelu w UI, który zmienia się co sprint.

Kiedy te zasady są spełnione, nawet stosunkowo mały zestaw e2e zaczyna być naprawdę wartościowy: jeśli coś upadło, jest to sygnał do szybkiej reakcji, a nie „kolejny flaky”.

Przykładowa architektura pipeline z podziałem na typy testów

Etap 1: szybka weryfikacja na każde push

Cel pierwszego etapu: nie marnować czasu na drogie kroki, jeśli kod ma oczywiste błędy. Typowy zestaw:

  • lint, formatowanie, statyczna analiza,
  • pełny zestaw testów jednostkowych,
  • opcjonalnie: kilka najbardziej krytycznych testów integracyjnych (np. smoke test bazy).

Ten etap powinien kończyć się w minutach, nie w dziesiątkach minut. Jeśli trwa zbyt długo, zwykle unity są zbyt ciężkie (np. korzystają z bazy) albo do tego etapu „przemyciły się” scenariusze integracyjne czy e2e.

Etap 2: testy integracyjne na merge request

Gdy kod przejdzie pierwsze sito, można pozwolić sobie na coś droższego. Dla każdego merge requestu (lub dla wybranych gałęzi) seria:

  • uruchomienie usług zależnych (baza, broker, serwisy pomocnicze) w kontenerach,
  • pełny zestaw testów integracyjnych,
  • ewentualne lekkie testy API bez UI (np. smoke testy głównych endpointów).

Jeśli ten etap wykazuje dużo flakiness, często winne jest środowisko: brak izolacji danych, współdzielone zasoby, brak deterministycznego startu kontenerów. Uporządkowanie tych elementów zazwyczaj daje większy zysk niż samo „dokładanie kolejnych testów”.

Etap 3: wąski zestaw e2e przed deployem

Przed deployem do środowiska testowego lub produkcji dobrze sprawdza się niewielki, ale stabilny pakiet scenariuszy e2e:

  • 2–5 najbardziej krytycznych ścieżek użytkownika,
  • scenariusze bezpieczeństwa i autoryzacji (np. brak dostępu do cudzych danych),
  • najważniejsze integracje z systemami zewnętrznymi, o ile da się je odtworzyć.

Ten