Mój pipeline CI/CD przechodził pomyślnie przez 3 miesiące — a potem przeczytałem logi
Zielone znaczniki wyboru dają poczucie satysfakcji. Każdy pull request przeszedł pomyślnie. Każde wdrożenie zadziałało.
Potem użytkownik zgłosił niedziałającą funkcję. Była zepsuta od tygodni.
Otworzyłem logi pipeline'u. Nasze pomyślne buildy nas okłamywały.
Nasz proces wyglądał idealnie:
- Linting
- Testy jednostkowe
- Testy integracyjne
- Build
- Deploy
Każdy krok miał 100% skuteczności przez wiele miesięcy.
Przycisk eksportu nie reagował na kliknięcie. Nie pojawiał się żaden błąd. Dotarłem do zmiany sprzed 11 tygodni. Pipeline przeszedł pomyślnie. Code review zostało zatwierdzone. Funkcja była zepsuta od samego początku.
Problem nie leżał w naszym kodzie. Leżał w naszym kodzie testowym.
Nasze testy integracyjne używały mocków do wszystkiego. Zamockowaliśmy cały serwis eksportu. Test sprawdzał mocka zamiast rzeczywistego kodu. Mock zawsze zwracał status sukcesu.
Wpadliśmy w pułapkę nadmiernego mockowania:
- Testy jednostkowe: Mockowanie wszystkiego, aby odizolować jednostkę. To jest w porządku.
- Testy integracyjne: Mockowanie wszystkiego dla szybkości. To jest błąd.
- Testy E2E: Przegapiły ten konkretny przepływ.
Nasze testy integracyjne były po prostu kosztownymi testami jednostkowymi. Weryfikowały, czy nasze mocki działają. Nie weryfikowały, czy nasz kod działa.
Wprowadziłem trzy zmiany, aby to naprawić:
Ogranicz mocki do testów jednostkowych. Testy integracyjne muszą łączyć się z rzeczywistymi bazami danych, API i systemami plików. Jeśli test jest wolny, nie ukrywaj tego za pomocą mocka. Wykorzystaj tę prędkość jako sygnał do optymalizacji.
Dodaj testy kontraktowe. Zapewniają one, że Twoje mocki odpowiadają rzeczywistemu zachowaniu serwisu. Jeśli mock zwróci dane, których nie zwróciłby rzeczywisty serwis, test kontraktowy zakończy się niepowodzeniem.
Śledź rzeczywiste pokrycie kodu. Przestaliśmy patrzeć na proste wskaźniki sukcesu. Sprawdzaliśmy, co testy faktycznie sprawdzają. Nasze wskaźniki pokrycia spadły z 94% do 67%. To była nasza najbardziej uczciwa metryka.
Zielony pipeline nie oznacza, że Twój kod działa. Oznacza, że Twoje testy przeszły pomyślnie. To dwie różne rzeczy.
Najniebezpieczniejsze błędy to te, o których Twój pipeline mówi, że są w porządku.
Zadaj sobie te pytania:
- Czy moje testy wyłapują błędy, czy tylko potwierdzają działanie mocków?
- Czy moje testy integracyjne faktycznie integrują?
- Jeśli usunę wszystkie mocki, ile testów nadal przejdzie pomyślnie?
- Czy mierzę pokrycie, czy pewność?
Pipeline, który nigdy nie zawodzi, nie jest niezawodny. Jest nietestowany.
Źródło: https://dev.to/kollittle/my-cicd-pipeline-passed-for-3-months-then-i-read-the-logs-4mbj
