W zarządzaniu projektami według modelu kaskadowego procesy programowania i testowania dzieli się na dwa różne etapy: programiści kompilują funkcję, a następnie „przerzucają ją przez płot” do zespołu odpowiedzialnego za zapewnianie jakości (QA), który przeprowadza testy. Zespół QA opracowuje i wykonuje szczegółowe plany testów. Zgłasza również usterki wykryte podczas żmudnego sprawdzania regresji w dotychczasowych funkcjach, które mogły powstać w wyniku prowadzenia nowych prac.
Wiele zespołów wykorzystujących te kaskadowe lub inne tradycyjne modele testowania zauważa, że w miarę rozwoju produktu wykładniczo zwiększa się również liczba testów i coraz trudniej nadążyć z zapewnianiem jakości. Product ownerzy stają w obliczu trudnego wyboru: opóźnienie wydania lub skrócenie testowania. (Zgadnijcie, która opcja zwycięża w 99% przypadków). W międzyczasie programiści zaczynają już pracę nad czymś innym. W związku z tym nie tylko rośnie dług techniczny, ale dodatkowo rozwiązanie każdej usterki wymaga czasochłonnego zmieniania kontekstu przy przechodzeniu między dwoma częściami bazy kodu. To tylko pogarsza sytuację.
Na domiar złego, zespoły QA są zazwyczaj wynagradzane w oparciu o liczbę wykrytych błędów, co spycha programistów na pozycję defensywną. A co, gdyby istniał lepszy sposób na zmniejszenie liczby błędów w kodzie, przy jednoczesnym wyeliminowaniu kompromisów, na jakie muszą iść product ownerzy — korzystny zarówno dla programistów, jak i dla zespołów QA? Czy nie spowodowałby on ogólnej poprawy jakości oprogramowania?
Poznajcie testowanie Agile i DevOps.
Przejście z tradycyjnych metod testowania na metody Agile
Celem zespołów Agile i DevOps jest trwałe dostarczanie nowych funkcji o wysokiej jakości. Jednak tradycyjne metody testowania po prostu nie wpisują się w ramy postępowania Agile ani DevOps. Tempo prac programistycznych wymaga nowego podejścia, które pozwoli zapewnić wysoką jakość każdej kompilacji. Sposób testowania, jaki stosujemy w Atlassian, jest zgodny z zasadami Agile. Przyjrzyj się bliżej naszemu podejściu do testowania razem z Penny Wyatt, starszą kierowniczką zespołu QA Jira Software.
Podobnie jak w przypadku narastającego zadłużenia na karcie kredytowej, zaczyna się od drobnych trudności, ale szybko się pogłębia i pozbawia zespół krytycznej zwinności. Aby przeciwdziałać powiększaniu długu technicznego, w Atlassian zachęcamy naszych programistów, aby zostali specjalistami w dziedzinie jakości (a nawet tego oczekujemy). Uważamy że programiści wnoszą kluczowe umiejętności, które pomagają podnosić jakość naszych produktów:
- Programiści doskonale radzą sobie z rozwiązywaniem problemów z kodem.
- Programiści, którzy piszą własne testy, są bardziej zainteresowani ich naprawą, gdy zawiodą.
- Programiści, którzy znają wymagania dotyczące funkcji i wynikające z nich potrzeby testowe, zasadniczą tworzą lepszy kod.
Jesteśmy przekonani, że każda historyjka użytkownika w backlogu wymaga zarówno opracowania kodu funkcji, jak i kodu zautomatyzowanego testu. Choć w niektórych zespołach to programistom przydziela się zadanie opracowania kodu funkcji, a zautomatyzowanymi testami zajmuje się zespół odpowiedzialny za przeprowadzanie testów, naszym zdaniem znacznie skuteczniej jest powierzyć obydwa zadania jednemu inżynierowi.
Zróżnicuj podejście do błędów w nowych funkcjach i regresji w istniejących funkcjach. Jeśli błąd zostanie wykryty w trakcie prac programistycznych, postaraj się zrozumieć jego przyczynę, napraw go i dopiero przejdź dalej. Jeśli dojdzie do regresji (czyli sytuacji, w której wcześniej coś działało, ale już nie działa), wówczas prawdopodobnie problem pojawi się ponownie. Utwórz automatyczny test, aby chronić produkt przed taką regresją w przyszłości.
Zastosowanie tego modelu nie oznacza, że programiści pracują sami. Ważne, aby do zespołu włączyć również inżynierów QA. Osoby odpowiedzialne za zapewnianie jakości wnoszą do procesu opracowywania funkcji ważną perspektywę. Dobry inżynier QA wie, gdzie zazwyczaj kryją się błędy, i może doradzić programistom, jak unikać przykrych niespodzianek.
Element ludzki dzięki testowaniu eksploracyjnemu
W naszych zespołach programistycznych członkowie zespołu odpowiedzialni za zapewnianie jakości pracują razem z programistami podczas testowania eksploracyjnego. Jest to cenna praktyka w procesie programistycznym, która pozwala wyeliminować poważniejsze błędy. Podobnie jak w przypadku przeglądów kodu, także ta sytuacja stwarza okazje do upowszechniania wiedzy na temat testowania wśród członków zespołu programistycznego. Gdy programiści stają się lepszymi testerami, początkowe wersje kodu zawierają mniej błędów.
Tylko czy testy eksploracyjne nie są testami ręcznymi? Nie. A przynajmniej nie w takim sensie, jak ręczne testy regresywne. Testowanie eksploracyjne to oparte na ryzyku krytyczne podejścia do testowania, dzięki któremu osoba przeprowadzająca testy może wykorzystać swoją znajomość zagrożeń, szczegółów dotyczących wdrożenia oraz potrzeb klientów. Świadomość tych zagadnień na wcześniejszych etapach procesu testowania umożliwia programiście lub inżynierowi QA błyskawiczne i kompleksowe wykrywanie problemów, bez konieczności opracowywania skryptów przypadków testowych, szczegółowych planów testów czy wymagań. Naszym zdaniem jest to znacznie bardziej skuteczne niż tradycyjne testy ręczne, ponieważ możemy wprowadzić wnioski z sesji testowania eksploracyjnego z powrotem do pierwotnego kodu i automatycznych testów. Testy eksploracyjne przekazują również wiedzę na temat obsługi funkcji w sposób niedostępny w testowaniu skryptowym.
Zapewnianie jakości wymaga połączenia testowania eksploracyjnego i automatycznego. Podczas opracowywania nowych funkcji testy eksploracyjne pozwalają zapewnić, że nowy kod spełnia standardy jakości w ujęciu szerszym niż same testy automatyczne. Chodzi tu nie tylko o solidne zabezpieczenie przed regresjami, które można uzyskać dzięki testowaniu automatycznemu, ale także o łatwość użycia, atrakcyjność wizualną czy ogólną przydatność funkcji.
Zmiana bywa trudna, naprawdę trudna
Przytoczę tutaj prywatną anegdotę, która dobrze podsumowuje moje doświadczenia z testowaniem Agile. Pamiętam, jak na początku kariery zarządzałem zespołem inżynierskim, który wykazywał silny opór przed pisaniem testów automatycznych, ponieważ zdaniem jego członków „to zadanie zespołu QA”. Po kilku iteracjach zawierających błędy w kodzie i wysłuchaniu wszystkich argumentów za tym, że automatyczne testowanie spowolni zespół, postawiłem na swoim: cały nowy kod miał być sprawdzany za pomocą testów automatycznych.
Już po jednej iteracji jakość kodu zaczęła się poprawiać. A programista, który najbardziej stanowczo sprzeciwiał się pisaniu testów, okazał się tym, który wkroczył do akcji, gdy okazało się, że test zakończył się niepowodzeniem. W ciągu kilku kolejnych iteracji liczba automatycznych testów wzrosła, ich zakres objął różne przeglądarki, a nasza kultura programistyczna uległa poprawie. Fakt, przygotowanie funkcji trwało dłużej, ale liczba błędów i poprawek spadła drastycznie, co ostatecznie pozwoliło nam oszczędzić mnóstwo czasu.
Zmiany na ogół są trudne. Tak jak większość rzeczy wartych zachodu. Jeśli jednak zabierzesz się ostro do pracy i stworzysz dla siebie nowe wzorce, pozostanie tylko jedno pytanie: „Dlaczego nie zrobiliśmy tego wcześniej?”.