Automatyczne testowanie (IT)Inżynier QA Manualnego

Jakie wyczerpujące metody ręcznego testowania zastosujesz, aby wykryć warunki wyścigu między rezerwacją zapasów, autoryzacją płatności a potwierdzeniem zamówienia, gdy wystąpią podziały sieciowe lub opóźnienia w komunikatach?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź na pytanie

Historia pytania

Tradycyjne podejścia do ręcznego testowania ewoluowały od walidacji monolitycznych transakcji SQL, gdzie jedna baza danych zapewniała spójność. Wraz z przejściem na Mikrousługi i Architekturę opartą na zdarzeniach, zapewnienie jakości napotyka teraz wyzwanie związane z weryfikacją rozproszonych wzorców Saga, w których zmiany stanu rozprzestrzeniają się asynchronicznie przez granice serwisów, co wymaga nowych metod, aby zapewnić integralność danych bez blokad dwuetapowych.

Problem

Główne wyzwanie leży w wykrywaniu warunków wyścigowych i stanów częściowej awarii, gdy gwarancje ACID są izolowane do poszczególnych baz danych serwisów. W szczególności weryfikacja, że rezerwacje zapasów w PostgreSQL, autoryzacje płatności za pośrednictwem zewnętrznych API oraz potwierdzenia zamówień przez tematy Apache Kafka utrzymują spójność w czasie podziałów sieciowych, ponownego zbalansowania konsumentów Kafka lub awarii unieważnienia pamięci podręcznej Redis wymaga zrozumienia kompromisów teoretycznych CAP i okien końcowej spójności.

Rozwiązanie

Kompleksowa metodologia ręcznego testowania inspirowana Chaos Engineering, która łączy precyzyjną manipulację czasową z mapowaniem przejść stanów. Obejmuje to ręczne wprowadzanie opóźnienia w grupach konsumentów Kafka przy użyciu narzędzi Proxy, symulowanie unieważnienia pamięci podręcznej Redis podczas aktywnych transakcji oraz weryfikowanie, że transakcje kompensujące Saga poprawnie cofną operacje, gdy wystąpią awarie w dół, zapewniając, że system utrzymuje spójność bez pozwalania na fantomowe zapasy lub podwójne obciążenia.

Sytuacja z życia

Rynek luksusowych zegarków przygotowywał się do wydania limitowanej edycji 100 ekskluzywnych zegarków, z oczekiwaną jednoczesną popytem od ponad 10,000 użytkowników. Architektura wykorzystywała mikrousługi Spring Boot, gdzie Usługa Zapasów zarządzała zapasami w PostgreSQL, Usługa Płatności integrowała się z API Stripe, a Apache Kafka ułatwiała asynchroniczną komunikację między nimi. Podczas symulacji przedprodukcyjnej zespół odkrył krytyczny błąd, w którym dwóch użytkowników jednocześnie kupiło ostatnią dostępną jednostkę, ponieważ weryfikacja zapasów i rezerwacja miały miejsce w oddzielnych asynchronicznych wiadomościach, tworząc scenariusz podziału umysłu, w którym obie płatności zostały zrealizowane, zanim którakolwiek usługa zamówień potwierdziła potrącenie zapasów.

Rozwiązanie 1: Poziome skalowanie konsumentów Kafka

To podejście polegało na zwiększeniu liczby instancji konsumentów w celu zredukowania opóźnienia przetwarzania wiadomości i zminimalizowania okna dla warunków wyścigu. Główną zaletą było poprawienie przepustowości i zmniejszenie opóźnienia w normalnym obciążeniu. Jednak nie rozwiązało to zasadniczo problemu warunków wyścigu; jedynie statystycznie uczyniło kolizję mniej prawdopodobną, pozostając jednak możliwą podczas szczytowego ruchu lub zdarzeń ponownego zbalansowania konsumentów.

Rozwiązanie 2: Wdrożenie rozproszonych blokad za pomocą Redis Redlock

Ta strategia wprowadziła atomowe mechanizmy blokowania, w których Usługa Zapasów nabywałaby rozproszoną blokadę przed przetworzeniem jakiejkolwiek prośby o płatność. Choć zapobiegało to jednoczesnym modyfikacjom tego samego przedmiotu zapasów, wprowadzało znaczące opóźnienie do procesu płatności, tworzyło potencjalny punkt awarii, jeśli klaster Redis doświadczył podziałów sieciowych oraz skomplikowało scenariusze odzyskiwania awarii, w których blokady mogłyby nie zostać zwolnione z powodu awarii aplikacji.

Rozwiązanie 3: Ręczne wprowadzanie awarii orchestrated z kontrolą partycji Kafka

Ta metodologia wymagała od testerów ręcznego wstrzymywania określonych partycji Kafka przy użyciu narzędzi administracyjnych takich jak Kafdrop, jednocześnie wprowadzając opóźnienie sieciowe za pomocą polityk sieciowych Docker. Umożliwiło to precyzyjne odtworzenie dokładnego okna czasowego między autoryzacją płatności a zobowiązaniem zapasów. Podejście to było czasochłonne i wymagało podwyższonych uprawnień do manipulacji politykami sieciowymi Kubernetes, ale zapewniało deterministyczne odtworzenie warunków wyścigu oraz bezpośrednią obserwację wyzwalaczy transakcji kompensacyjnych Saga.

Wybór rozwiązania i uzasadnienie

Rozwiązanie 3 zostało wybrane, ponieważ tylko deterministyczna interwencja ręczna mogła ujawnić mikroskalowe podatności czasowe między usługami. Poprzez celowe wstrzymanie konsumenta zapasów, jednocześnie pozwalając konsumentowi płatności na przetwarzanie, potwierdziliśmy, że system nie miał blokady rezerwacji przedpłaceniowej oraz że procesy kompensacyjne nie uruchamiały się automatycznie, gdy wykryto konflikty zapasów.

Wynik

Zespół deweloperski wdrożył wzorzec dwuetapowej transakcji z statusem zapasu Oczekujący, który rezerwował zapasy przed przetwarzaniem płatności. Ręczne testowanie następnie potwierdziło, że wymuszenie ponownego zbalansowania Kafka podczas aktywnego zakupu poprawnie wyzwalało kompensację Saga, zwalniając zarówno rezerwacje zapasów, jak i zablokowane płatności bez utraty danych. Kolejne uruchomienie produktu odbyło się pomyślnie, z zerowymi zgłoszeniami podwójnych sprzedaży i wszystkimi 100 jednostkami uwzględnionymi w końcowym bilansie.

Co często umyka kandydatom

Jak weryfikujesz właściwości ACID, gdy Mikrousługi wdrażają Ostateczną spójność zamiast transakcji rozproszonych?

Kandydaci często mylą lokalną zgodność bazy danych ACID z globalną spójnością systemu. W ręcznym testowaniu musisz celowo zaprojektować scenariusze, w których transakcja PostgreSQL pomyślnie kończy się, ale publikacja kolejnej wiadomości Apache Kafka nie powodzi się, co można osiągnąć, stosując podziały sieciowe Docker, aby izolować broker wiadomości. Sprawdź, czy usługa wdraża wzorzec Outbox lub komunikację transakcyjną, aby gwarantować, że zatwierdzenia baz danych i publikacje wydarzeń pozostają atomowe. Sprawdź, czy są osierocone rekordy, wykonując zapytanie do bazy danych bezpośrednio, blokując brokera wiadomości, a następnie potwierdź, że mechanizmy ponownej próby ostatecznie synchronizują stan bez interwencji ręcznej lub uszkodzenia danych.

Co odróżnia testowanie Idempotencji od testowania Dokładnie Raz semantyki w Kolejkach wiadomości, i dlaczego to jest krytyczne dla ręcznego QA?

Wielu testerów błędnie traktuje te koncepcje jako zamienne. Idempotencja zapewnia, że przetwarzanie tej samej wiadomości wielokrotnie daje ten sam wynik co przetworzenie jej raz, co testujesz, ręcznie odtwarzając wiadomość Kafka z Offset Explorer i weryfikując, że nie wystąpiło podwójne obciążenie ani odjęcie zapasów. Dokładnie Raz semantyka zapewnia, że infrastruktura sama zapobiega podwójnej dostawie, co weryfikujesz, obserwując zachowanie transakcyjnego producenta Kafka podczas scenariuszy awarii brokera. Ręczne QA musi weryfikować oba wymiary: że aplikacja radzi sobie z duplikatami w sposób idempotentny oraz że filtry deduplikacji oparte na UUID działają poprawnie, gdy broker rzeczywiście ponownie dostarcza wiadomości z powodu przekroczenia czasu potwierdzenia.

Jak weryfikujesz Transakcje kompensacyjne w ramach wzorca Saga, nie ryzykując integralności finansowej danych produkcyjnych?

Wymaga to skonstruowania izolowanych środowisk testowych, które odwzorowują produkcyjne Schematy i Umowy API, ale wykorzystują dane logowania dla piaskownicy dla dostawców płatności. Ręcznie uruchom sekwencje awarii, kończąc kontenery Docker natychmiast po etapie autoryzacji płatności, ale przed potwierdzeniem usługi zapasów. Zweryfikuj, że proces kompensacyjny poprawnie wydaje zwroty i zwalnia rozproszone blokady Redis. Kandydaci często pomijają weryfikację tego, że sam mechanizm kompensacji może się nie powieść; musisz przetestować, blokując ścieżkę kompensacyjną, na przykład symulując awarię sieciową podczas fazy wycofania i upewnić się, że system wchodzi w wyraźnie zdefiniowany stan alarmowy Kompensacja nieudana z odpowiednimi powiadomieniami monitującymi, a nie w niezdefiniowanym niespójnym stanie, który mógłby prowadzić do niezgodności finansowych.