Testowanie to nieco zapomniana już sztuka ?

Czytałem ostatnio o teście ciążowym, który zamiast 20 centów amerykańskich kosztuje 7 dolarów i robi dokładnie to samo (tzn. pozwala na jedno badanie), ale... wynik wyświetla na ekranie LCD zamiast w postaci kreseczek. Co ciekawe, maszynka w środku może mieć obliczeniową porównywalną lub większą niż pierwszy IBM PC i zawiera takie elementy jak mikroprocesor, bateria, itp. (Crysis na tym nie pójdzie, ale Doom zapewne już tak).

Fake, nie fake, ale przypomniała mi się również taka oto komórka:

(zgodnie z prośbą z Wikipedii podaję źródło: by Mustaraamattu - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=32521130)

i to, że obecnie w smartphonie od biedy można pisać dłuższe teksty, oglądać filmy i robić to, co kiedyś było w sferze marzeń.

O ile jednak kiedyś bardzo wielu obecnych czterdziestolatków miało głęboką wiedzę techniczną i potrafiło pisać dema, skrypty i robić tysiące różnych rzeczy z ówczesnymi komputerami i urządzeniami, to dziś w sumie mało kto zastawia się "jak to działa" i najczęściej tylko "konsumuje treści" (szczytem umiejętności bywa naklepanie czegoś w JavaScript).

Świat się zmienił i zmieniły się również metody związane z tworzeniem oprogramowania - z dbania o jego prędkość i małą wielkość (wymuszoną przez ograniczenia technologii) przeszliśmy raczej do trybu "if doesn't work, think about better hardware" albo trybu "don't risk with breaking compatibility".

Uzależniliśmy się od serwisów takich jak Google czy YouTube (i nie mówię nawet o filmikach rozrywkowych - pomyślmy, że dzisiaj np. zabrakłoby tych wszystkich materiałów historycznych, których na pewno nie zobaczyliśmy w inny sposób), równocześnie w tym świecie w wielu portalach codziennie słyszy się o problemach z Windows 10, Android czy Android Auto (ewentualnie o tym, jak z mozołem są one ulepszane w pocie czoła milionów programistów).

Nowego znaczenia nabrały słowa takie jak "premium", "optymalizacja" czy "bezpieczeństwo", ale co tam - najważniejsze, żeby regularnie można było czytać o nowych wersjach.

- Postęp jest postęp. - Ktoś powie.

Zgadzam się, nie zmienia to jednak faktu, że również w dziedzinie testowano pewne procedury stworzono i opisano wiele lat temu, a wiele z obecnych wytworów wygląda tak, jakby nigdy nie przeszło jakiegokolwiek sprawdzenia na etapie produkcji.

- Ale zaraz... firmy tworzą ludzie. - Ktoś doda. - Czy oni nie widzą, co się dzieje?

Pozostawię to bez odpowiedzi.

Sam m.in. wspominałem o wątpliwym przydomku PRO dysku Samsung 980 PRO, o dosyć zastanawiącej polityce tej firmy w stosunku do komórek, o pewnych zachowaniach pewnej płyty głównej firmy Asrock (duże VCore i szopki z UEFI), o takiej sobie jakości (wielu) monitorów, różnych pułapkach marketingowych i mądrościach, które wciąż krążą wśród ludu, problemach Mozilli i Firefox Preview (który obecnie stał się wersją "stabilną" na Androidzie), śmiesznie wolnym uaktualnianiu mikrokodu CPU przez Microsoft (i obejściu tego problemu), zachowaniach Microsoft i Google względem rozwiązywania błędów, Thunderbolcie i sterownikach grafiki niebieskich do Windows 10, jak również o młodych i dynamicznych zespołach i o tym, że pewne projekty doszły do końca cyklu swojego rozwoju.

W wielu obszarach doszliśmy do muru i obecny postęp jest niestety iluzoryczny, za to wiele koszmarków jak nieszczęsny test najwyraźniej znajduje nabywców (np. są chętni na Samsunga Note 20 z procesorem Exynos).

Ludzie, którzy to wszystko kupują, przenoszą potem pewne wzorce do swojej pracy (np. "skoro konsumenci nie mówią zbyt mocno o braku wsparcia, to również u nas je skrócimy")

Jak już sobie to wyjaśniliśmy, to teraz zastanówmy się trochę nad tym, jak w tym świecie może wyglądać testowanie oprogramowania od kuchni w sytuacji, gdy jest ono tworzone w modelu katedry.

Rodzaje testów

W największym uproszczeniu można powiedzieć, że testy można podzielić na manualne (z akcjami wykonywanymi przez człowieka) i automatyczne (gdzie uruchamiany jest jakiś automat, skrypt albo fragment kodu).

Innym podziałem jest podział na testy biało i czarnoskrzynkowe (przy pierwszych bierze się pod uwagę kod, przy drugich testowany element traktuje się jak skrzynkę, która po podaniu odpowiedniego sygnału ma odpowiedzieć z góry wyliczoną wartością).

W zależności od zasięgu testowania najczęściej wyróżnia się:

  • unit test (testy jednostkowe) - gdzie sprawdza się najmniejsze elementy typu funkcja czy procedura
  • component testing (testy modułowe) - sprawdzenie całych modułów
  • testy systemowe - sprawdzenie całego systemu (end-to-end testing, czyli tak naprawdę rzut okiem od strony użytkownika)

Można jeszcze mówić np. o

  • testach wydajności (performance testing) - sprawdzeniu reakcji elementów na nagłe zwiększenie obciążenia, pracę z dużą ilością danych czy określenie, ilu użytkowników/ile danych może maksymalnie obsłużyć dany komponent albo system
  • testach eksploracyjnych - testowaniu wykonywanym przez człowieka, który nie ma z góry ustalonego planu i bazując na swoim doświadczeniu sprawdza (na ile to możliwe) zgodność aplikacji z wymaganiami, ogólnie przyjętymi normami dla danej klasy aplikacji albo ze zwykłym zdrowym rozsądkiem
  • testach bezpieczeństwa
  • testowaniu akceptacyjnym (UAT) - zazwyczaj wykonywanym z przedstawicielami klienta czy użytkownika oprogramowania, którzy poniekąd potwierdzają zgodność aplikacji z wymaganiami
  • testach regresji - gdzie ponownie wykonujemy testy przeznaczone dla aplikacji (po to, żeby sprawdzić, czy nie pojawiły się nowe błędy w jej nowym wydaniu)
  • sanity check - krótkie sprawdzenie podstawowych funkcji (np. tego, czy aplikacja w ogóle startuje)

Nasz przypadek

Przyjmijmy teraz, że mamy hipotetyczną wielką firmę i zespół testerski, w którym wysoce wykwalifikowani fachowcy są przydzieleni do wykonywania odpowiednio testów manualnych, automatycznych czy wydajności i wykonują je na różnych etapach projektu. Niektórzy z nich dodatkowo mają dostęp do narzędzia do raportowania błędów używanego przez klientów oprogramowania i obsługują to, co się tam pojawia.

Ludzie ci są rozliczani poprawnie z tego, jak bardzo testowane jest oprogramowanie (np. badany jest stopień pokrycia wymagań testami, ewentualnie patrzymy na odpowiednie pokrycie testami wszystkich ścieżek kodu) i przestrzegane są wszystkie procedury wymagane prawem (w przypadku systemów związanych np. z życiem ludzkim musi być wdrożone to, co przewidują odpowiednie certyfikaty)

Co może pójść nie tak?

Spróbuję teraz przedstawić kilka zupełnie hipotetycznych sytuacji:

Testowanie traktowane jest jako dopust boży

Tak się składa, że testerzy najczęściej nie tworzą "rzeczywistego" kodu ani aplikacji, które można pokazać na prezentacjach. Ich produktem są "tylko" wpisy w narzędziach testerskich i raporty, jak również narzędzia testerskie i różnego rodzaju skrypty czy frameworki do testowania (chociaż w firmie, gdzie testowanie nie jest brane na poważnie, bym się tego nie spodziewał).

Jeśli pominiemy sytuacje, gdy firma ma pracowników i sprzedaje czas ich pracy na zewnątrz, to w każdej innej sytuacji ludzie ci są po stronie "koszty". Proszę zauważyć, że możnaby ewentualnie zarobić też na sprzedaży frameworków do testowania, ale... bywa to coraz trudniejsze w czasie, gdzie wiele z nich jest za darmo (do tego te frameworki nie mogą odsłaniać tajemnic firmy i muszą być na tyle ogólne, żeby komuś się przydały).

Chcę tu jasno powiedzieć - oczywiście wszyscy wiemy, że dobre testowanie pozwala uniknąć takich problemów jak utrata wiarygodności czy pozwy, niemniej jednak są to najczęściej wielkości niemierzalne i nieuwzględniane w budżetach, w których mamy wspomniane "koszty".

Testowanie w dłuższym okresie czasu nie wykazało poważnych błędów w ostatecznej wersji produktu

Załóżmy, że nasz zespół działa jak palce jednej ręki. Raporty o tym spływają do managerów, którzy uznają, że pracowników można wykorzystać w inny sposób i przesuwają ich gdzieś indziej (np. zastępując ich tańszymi odpowiednikami z zagranicy).

Pozostali w zespole ludzie mają wtedy więcej pracy (chociażby z wzdrożeniem nowych kolegów) i ich motywacja potrafi się wtedy mocno zmienić.

I kto za to płaci?

Praca jest wykonywana dobrze, ale nikt jej nie docenia

Ślęczenie nad danymi (nie będę tu rozgraniczał ról na analityka i testera), szukanie dziury w całym i "czepianie się", pisanie jakichś tam skryptów i ich interpretacja wymagają często i gęsto ekwilibrystycznych popisów.

Problem pojawia się, gdy całość nadzoruje osoba z zupełnie innym (tzn. nietechnicznym) wykształceniem, która nie potrafi lub nie może tego docenić.

A jak frustracja dochodzi do zenitu i dobrze pracująca osoba decyduje się zmienić pracę, to... nie muszę chyba mówić, że może to wpłynąć na morale i jakość testowania w zespole?

W zespole są (zbyt) doświadczeni testerzy

Osoby z dłuższym stażem znają systemy i technologie, co więcej - wiele z nich przeszło przez wykonywanie różnego rodzaju testów i doskonale potrafi również kodować (jedna ze starych zasad testerskich mówi, że tester powinien wiedzieć na temat programów więcej niż programista).

I chociaż w dzisiejszych czasach (specjalizacja w jednym języku i frameworku) trudno w to uwierzyć, to myślę, że wciąż można spotkać specjalistów starszej daty, którzy znają niejeden dialekt...

Z jednej strony jest to cecha pożądana, z drugiej strony po iluś latach testowania pewne rzeczy na pewno widać na pierwszy rzut oka i ludzie tacy z automatu mogą zgłaszać setki raportów o błędach. Należy pamiętać, że płaci im się poniekąd za wykonywanie ich obowiązków, a nie przymykanie oczu... A że człowiek starszej daty, to i potrafi i chce pracować... a to oczywiście może wpłynąć na opóźnienie projektu.

Powiedziałbym nawet, że zapotrzebowanie na takich specjalistów jest przy projektach związanych przede wszystkim z życiem ludzkim, ale obecnie nawet Boeing 737 MAX "został zaprojektowany przez klaunów zarządzanych przez małpy"...

Widzę tylko swój mały światek

W idealnej sytuacji tester po zobaczeniu błędu w miejscu A powinien przejrzeć aplikację i zobaczyc, czy tej samej usterki nie ma w miejsach B, C i D.

Jak często tak się dzieje? Pozostawię to jako pytanie retoryczne.

Konflikty między developerami i testerami

Ludzie są ludźmi - jedni piszą kod (często dopracowany do najmniejszej linijki i zgodny ze wszelkimi zaleceniami), drudzy natomiast przychodzą i zaczynają ten kod przeglądać, komentować, a co gorsza poprawiać...

Przy pełnym profesjonaliźmie nie ma oczywiście mowy o żadnych niesnaskach, ale... szczególnie "w młodym i dynamicznym zespole" od czasu do czasu może jednak trafić się coś takiego, co potrafi zaburzyć relacje zawodowe na długi czas.

A gdzie konflikty, to dochodzi potem do działań korygujących (czytaj - przeniesienia określonych osób do innych projektów).

Błędy mają źle ustawioną ważność i zawartość

Zapewne chlebem powszednim w zespole testerskim są niekompletne i źle opisane zewnętrzne raporty błędów. Pół biedy, jeśli osoby rozmawiające "ze światem" mają odpowiednie umiejętności miękkie i potrafią dopytać się o istotne szczegóły, jak również wiedzą, jak właściwie ustawić ważność danego raportu (bo znają system).

A co, jeśli postawimy tam najtańszych pracowników z firmy zewnętrznej? 

Do tego dodajmy fakt, że spojrzenie z różnych pozycji (manager, programista, tester, kierownik testów, itd.) może powodować, że dana rzecz będzie miała inną wagę... i ping-pong gotowy.

W przypadku opóźnień tnie się zakres testów

Dawno temu podstawowym sposobem był V model.

Załóżmy, że pierwsze fazy potrwały dłużej, a my już obiecaliśmy na zewnątrz nową wersję produktu... Co się wtedy tnie?

Inna sprawa, że teraz mamy oczywiście Agile, gdzie wszystko dzieje się szybko i dynamicznie... załóżmy, że mamy spotkania daily i różne związane z tym cudowności, a czasu na pracę coraz mniej.

Czy coś się wtedy zmienia?

Przy okazji może pojawić się wtedy problem związany z tym, co wszyscy lubimy. Nazwijmy to zupełnie przypadkowo jako...

Przesadne przywiązanie do metodyk i procedur

Prosta sprawa - firma określa pewne zasady i np. przyjmuje, że błędy mają mieć wszystko opisane w odpowiednim szablonie. To poniekąd dobre, że mamy określić tyle informacji, ile tylko się da (wersja systemu operacyjnego, programu, konfiguracja, kroki do wykonania, itp.).

Problem jednak zaczyna się, gdy zgłoszenia są odrzucane z tak błahych powodów jak zła wielkość liter albo brak któregoś szczegółu. W sytuacji idealnej dany błąd powinien zostać oczywiście odtworzony w zespole testerskim... ale wpierw tam musi trafić.

To zaś potrafi nie dziać się odpowiednio szybko, gdy...

Słońce nigdy nie zachodzi w projekcie

Załóżmy sobie, że jedna część zespołu pracuje w czasie europejskim, druga indyjskim, a trzecia amerykańskim. To oznacza mniej więcej tyle, że rano działamy z kolegami z Azji, a wieczorem z ludźmi np. z USA.

Problem zaczyna się, gdy np. ci pierwsi zdecydują się zadać pytanie na koniec swojego dnia... Dla nas oznacza to mniej więcej tyle, że nad danym zagadnieniem będziemy się mogli pochylić dopiero dnia następnego (w skrajnym wypadku).

Przykład: zgłaszamy błąd, przychodzi pytanie, odpowiadamy i następnego dnia widzimy kolejne pytanie na temat błędu, odpowiadamy i kolejna runda przechodzi na kolejny dzień.

Nie wszyscy powinni testować

Praca ta wymaga ułańskiej fantazji, ale również drobiazgowości, dokładności i ciekawości świata (przede wszystkim nieustannego pytania się "a co by było gdyby?"). Zamiana jednej kropki albo przecinka może czasem zniweczyć wielotygodniowy wysiłek poświęcony przy przygotowaniu testów, a brak asertywności jest po prostu dyskwalfikujący.

Tu nie ma miejsca na bylejakość... i na parytety.

Projekty muszą iść równocześnie

Wszystko można zautomatyzować i zmechanizować

Tak się składa, że testy automatyczne są bardzo użyteczne... mają jednak bardzo wielką wadę - testują określone ścieżki i potencjalnie w pewnym momencie mogą przestać wykazywać jakiekolwiek błędy

Jest to opisane przez zasadę "pesticide paradox", która mówi wprost - jeżeli wykonujemy testy w ten sam sposób, w końcu przestaniemy dostawać informacje o jakichkolwiek błędach (stąd ważne jest pozostawienie czynnika ludzkiego).

Jak pisałem wcześniej, na testowaniu czasem próbuje się oszczędzać - można na infrastrukturze (np. tworząc bardzo jednolite maszyny testowe, na których nie da się sprawdzić różnych przypadków testowych) albo również na poziomie/czasie osób, które testy automatyczne piszą.

A wtedy co z tego, że mamy te nieszczęsne testy, które zawsze pokazują "pass"?

Brak infrastruktury

Zacznijmy od testów wydajnościowych:

  1. o ile dużo się zmieniło na rynku w ostatnich latach (jest JMeter, LoadRunner z licencją do 50 użytkowników itp.), to niektóre technologie wciąż wymagają dosyć drogiego oprogramowania do uruchamiania testów albo monitorowania
  2. środowisko do testów powinno być maksymalnie zbliżone do produkcyjnego, a przynajmniej pozwalać na jasne przeskalowanie wyników testów (istnieją różne metody szacowania i jeżeli otrzymujemy jakiś wynik liczbowy, to powinniśmy wiedzieć, przez ile mamy ten wynik przemnożyć czy podzielić, żeby dostać wartość tego wyniku dla środowiska produkcyjnego)

Przy automatyzacji testów jest dosyć podobnie - potrzebne są różne aplikacje testerskie (częściowo darmowe, częściowo nie) i różnorodny sprzęt, ewentualnie ileś maszyn do uruchamiania skryptów.

Pamiętajmy też o jednym - wiele z obecnych na rynku aplikacji np. do zgłaszania błędów czy opisywania testowania nie ma tak podstawowych funkcji jak opisywanie rzcezy w sposób strukturalny (nie ma tam drzewa i trudno połapać się "co jest co")

W skrajnym wypadku mamy więc do czynienia, że nie ma na czym pracować...

Kombinowanie

Powyżej wielokrotnie przewijało się słowo kodowanie, a kod jak to kod może być dobry lub zły. Wyobraźmy sobie, że nasza automatyzacja testów wymaga tysiąca kroków... a terminy gonią i trzeba wybrać, co jesteśmy w stanie przetestować.

Podsumowanie

Wszystko co opisałem wyżej to oczywiście karykaturalnie przerysowane sytuacje hipotetyczne (za wszystkie niezmierzone podobieństwa i uproszczenia bardzo przepraszam), całość jednak powstała na podstawie relacji, artykułów i różnych źródeł i nie ma na celu dyskredytowanie wysiłku milionów ciężko pracujących ludzi, tylko wskazanie, że testowanie nie robi się magicznie samo (pewnych rzeczy nie można skracać) i że jest ileś rzeczy w samym procesie, które mogą zawieść.

Na pewno duże projekty to obecnie przedsięwzięcia, gdzie oprócz testowania ważne jest również wiele innych elementów - jakość technologii, programowania, zarządzania, marketingu, itp. (może kiedyś napiszę o tym kilka słów). 

Przykład: niektórzy uzasadniają, że Windows 10 jest problematyczny, bo Microsoft ma obsłużyć miliony urządzeń i to sterowniki są niedopracowane. Jest to częściowo prawda, choć z drugiej strony system operacyjny nie powinien zajmować się pierdyliardem różnych niepotrzebnych rzeczy, tylko robić to, co powinien - możliwie mocno niwelować niedoskonałości pracy osób trzecich i trzymać w ryzach to, co schrzanili. Jeśli architektura jest zła do bólu, to nawet najlepsze testowanie nie pomoże... Żeby tak tu był chociaż jakiś mikrokernel... Aż chce się powiedzieć - echhh, staryś, a głupiś Marcinie... że jeszcze w takie cuda wierzysz...

Ze wszystkim stoją konkretne pieniądze (które jednak trzeba mieć) i praca (którą trzeba wykonać).

(aż się nie mogę powstrzymać, żeby nie zacytować tu pewnego mema o tytule "changing the face of coding", który jest o kodowaniu, ale bardzo na czasie - https://duckduckgo.com/?q=changing+the+face+of+coding&t=canonical&...

Co jest również istotne, to fakt, że komputery to bestie, które wciąż najczęściej operują wyłącznie na zerach i jedynkach. Ciekawe, że również przy takim uproszczeniu pewne usterki daje się zauważyć nawet w materiałach pewnej organizacji zajmującej się jakością (było tak przynajmniej w 2014).