Przy okazji artykułów dotyczących testowania, chciałbym poruszyć kwestię optymalizacji samych testów i uruchamiania testów z odpowiednimi parametrami. Bazując na ilości komentarzy i wątków w internecie, w których szuka się sposobu na optymalizację testów, stwierdziłem że napiszę ten artykuł i zamieszczę w nim rozwiązanie problemu, z którym ostatnio walczyłem.

W artykule poruszę tylko kwestię uruchamiania testów, pomijając sam proces pisania testów.

Testy i problem z zasobami

W projekcie, nad którym pracuję, wraz z rosnącą liczbą testów okazuje się, że z czasem zaczyna brakować zasobów na komputerze, gdy uruchamiamy testy całej aplikacji. Uruchomiony PhpStorm, przeglądarka, komunikator itd… Doszło do tego, że aby uruchomić testy, trzeba było zamknąć niektóre aplikacje albo po prostu pogodzić się z tym, że nasz komputer zostanie na jakiś czas „zablokowany”, gdy zaczynało brakować RAMu…

Ograniczenie liczby „workerów”

Pierwszym, bardzo prostym sposobem, który może pomóc jest ograniczenie liczby jednocześnie uruchamianych procesów testowania („workerów”).
Jest daje nam taką możliwość, o czym możemy przeczytać na stronie z oficjalną dokumentacją – https://jestjs.io/docs/cli#–maxworkersnumstring

Zdefiniować liczbę uruchamianych procesów możemy poprzez dodanie parametru:

--maxWorkers

Polecam przetestować ten parametr, bo może się okazać, że wcale większa liczba workerów nie daje nam gwarancji, że testy wykonają się szybciej. Paradoksalnie mniejsza liczba jednoczesnych procesów może szybciej przeprocesować testy, bo komputer jest mniej obciążony. Z drugiej strony mniejsza liczba jednoczesnych testów daje nam możliwość normalnej pracy na komputerze, a testy działają „w tle”… Po prostu maksymalne zużycie pamięci nie blokuje nam komputera. 🙂

Node.js, Carbage collection i Jest heap usage

Node.js umożliwia nam skorzystanie z mechanizmu Garbage Collection, czyli narzędzia do usuwania nieużywanych obiektów, które powinny zmniejszać użycie zasobów. W tym celu należałoby użyć node z parametrem --expose-gc

node --expose-gc

To jeszcze nie koniec, bo należy zmusić bibliotekę Jest do pokazania nam ile pamięci zostało użyte podczas wykonywania danego testu. W tym celu skorzystamy z parametru --logHeapUsage, który opisany jest tutaj: https://jestjs.io/docs/cli#–logheapusage

Dopiero teraz, gdy w node użyjemy --expose-gc, a wraz z uruchamianiem testów do Jest dodamy flagę --logHeapUsage całość powinna zużywać znacznie mniej zasobów. Gdy uruchomimy narzędzie, które będzie śledziło użycie, będzie widać jak zasoby są sukcesywnie „oddawane”. Jak do Jest dołożymy jeszcze parametr, określający liczbę „workerów”, to jesteśmy w stanie znacząco zoptymalizować zużycie pamięci podczas wykonywania testów.

Końcowa komenda, podsumowanie

Napisałem trochę o każdym parametrze z osobna, warto teraz wszystko złożyć w całość. Nasza finalna komenda mogłaby wyglądać w ten sposób…

node --expose-gc ./node_modules/.bin/jest --logHeapUsage --maxWorkers 3

Podsumowując jeszcze raz… expose-gc daje nam możliwość użycia Garbage collection z node.js, logHeapUsage z Jest zrzuca nam ilość użytej pamięci dla testu, zaś maxWorkers z biblioteki Jest daje możliwość ograniczenia liczby procesów uruchamianych jednocześnie.

Czy możemy użyć parametrów osobno?
Według mnie nie bardzo. Użycie parametru osobno nie chciało działać i użycie pamięci było porównywalne jak bez dodania parametrów… Nawet dokumentacja Jest dla parametru logHeapUsage mówi nam:
(…) Use together with –runInBand and –expose-gc in node.

Dlatego dopiero, gdy użyłem parametrów --expose-gc, --logHeapUsage oraz --maxWorkers razem, widać było znaczą różnicę. Wygląda na to, że --expose-gc daje nam możliwość skorzystania z Garbage collection, ale żeby node poprawnie poradził sobie z optymalizacją, musi też wiedzieć ile tej pamięci zostało użyte przez Jest, stąd konieczność użycia logHeapUsage.

Ograniczenie pamięci w kontenerze Dockera

Podczas walki z tym problemem, podjąłem jeszcze próbę ograniczenia zasobów bezpośrednio na kontenerze Dockera. W zasadzie ograniczenie zasobów kontenera działało, tylko kiedy testy zużywały zbyt dużo zasobów niż dostępne było dla kontenera, kontener został po prostu „ubijany”. Nie testowałem zatem dalej tego rozwiązania, gdyż poprzednie wydaje się działać całkiem OK i jesteśmy w stanie odpowiednio dostosować parametry do własnych zasobów…

Jeżeli macie jakieś inne sposoby jak można poradzić sobie z tym problemem, napiszcie proszę. Dzięki i mam nadzieję, że ktoś z Was wykorzysta ten sposób i poziom irytacji podczas testowania znacznie spadnie. Teraz też wiecie dlaczego obraz artykułu zawiera zdjęcie śmieciarki! 😉

Źródła:
Obraz: https://unsplash.com/photos/zOPAWuqrtiM

Jest: https://jestjs.io/
Node: https://nodejs.org/