Żaden tutorial nigdy też nie pisze o tym jak testować te elementy. Pamiętam, że jak pisałem edytor do 4programmers.net i chciałem dodać autocomplete, to w całej dokumentacji nie było ani słowa o tym jak przetestować ten autocomplete. Zeszło mi jakieś 40h żeby to samemu wykminić.
To samo tyczy się wszelkich innych integracji lub providerów: sms, maile, kolejki, e-money, oAuth - wszystkie te dokumentacje są pełne przypadków użycia - ale kiedy się użyje tej biblioteki w swoim projekcie, i chce się napisać dobry test pod te integracje, to dokumentacja o tym milczy. Dla przykładu: https://github.com/smsglobal/smsglobal-php mamy w Sms Global Api rozdział "Verify OTP", który pisze że weryfikacja OTP jest "bardzo prosta", bo wystarczy jedna metoda. Ale jak wysłać fake'owe OTP w testach, żeby zweryfikować usera? No właśnie, o całkowita cisza - musisz sam na to wpaść, i jak już napiszesz dobry test który faktycznie umie wysłać fake'owe OTP, to bardzo prawodpodobne że kod który powstanie będzie bardzo różny od przykładu z dokumentacji.
Jedynym nieznaczącym nic wyjątkiem są frameworki (laravel, django, spring, RoR), które podają mniej niż minimum przykładów z testami, ale to nie jest i tak na temat bo te testy nie tyczą się samego frameworka, tylko naszej aplikacji w tym frameworków, czyli problem nadal ten sam.
Nawet tutoriale z głupią aplikacją konsolową brzmią:
- Tutorial: Żeby użyć argumentów, użyj
sys.argv
- to jest bardzo, bardzo proste!
- User: No dobra, ale jak napisać test pod to?
- Tutorial:
Co jest w ogóle dodatkowo śmieszne, bo dochodzimy do momentu odwróconego wnioskowania. Początkujący programiści często wytykają jak np użycie input()
oraz println()
jest "łatwe", bo mało pisania; a dodanie konstruktora i wstrzyknięcie klasy jest "trudne" bo jest dużo pisania; podczas gdy żeby przetestować input()
/println()
to trzeba się nieźle narobić wstawiając fake'owe stdin/stdout i martwiąc się o spacje, entry i kodowanie; a żeby przetestować taką klasę to
wystarczy anonimowa implementacja.
Kolejną częstą ofiarą są np biblioteki które w jakiś sposób integrują w system na którym działamy, np operują na plikach lub zmiennych środowiskowych. Dobrym przykładem jest gdzie ArgumentParser
z pythona umie się dopasować szerokością odpowiedzi do szerokości terminala. W dokumentacji jest to opisane jako "bardzo proste oraz automatyczne". Niby racja. Ale napisanie testu pod to wymaga spawnowania procesu z przekazaniem zmiennej środowiskowej, żeby w ogóle zrekreować to zachowanie w środowisku testowym, nie ma żadnej flagi do przekazania.
Innym przykładem są wszelkie rozwiązania które są "szybkie i proste", np hooki w reacie: useState()
, useEffect()
. Dokumentacja reacta opisuje testowanie komponentów snapshotami, ale te snapshoty w ogóle nie testują hooków: czyli mamy do wyboru albo zostawić je nieprzetestowane, albo praktycznie napisać je samemu od nowa, żeby móc napisać testy pod nie.
Jeśli dokumentacja już zrobi łaskę i napisze chociaż słowo o testowaniu, to często też łamie enkapsulacje. W Laravelu w dokumentacji ORM' jest malutki rozdział o tym jak podmienić ORM i modele tak żeby nie strzelały do bazy (co jest określone jako "can be helpful when testing", ho, ho), ale to przecież całkowicie łamie enkapsulacje naszego kodu i przywiązuje testy do implementacji. Nie ma całkowicie opisanego jak to poprawnie przetestować - czyli w sposób niezależny od ORM'a, np bazą in-memory.
Jeśli weźmie się testowanie każdej biblioteki na poważnie, to każda dokumentacja pod tym względem jest worse then useless - bo jeśli będziesz followować taką dokumentację i tutorial, to bardzo prawdopodobne że wytworzysz nietestowalny kod.