Budowanie oprogramowania jest złożonym procesem. Poza opanowaniem różnych narzędzi i języków programowania, jest jeszcze zrozumienie różnych ról związanych z tworzeniem oprogramowania. Jak większość z nas wie, wielkie projekty nie polegają tylko na kodowaniu. Duże projekty angażują również inne zasoby do zbierania wymagań, prototypowania i testowania.
Proces sprawdzania poprawności kodu jest często określany mianem zapewnienia jakości. Jednakże, wyrażenie to jest nieco mylące. Zamiast zapewniać jakość kodu, prawdziwym celem jest jej pomiar – często w miarę rozwoju projektu. Ta subtelna różnica, znana również jako test-driven development (np. TDD), może być zauważona, gdy przyjrzymy się rolom funkcji jakości. Należą do nich między innymi:
WHY UNIT TESTS?
Jak widać, pomiar jakości jest często pogrupowany na działania zautomatyzowane i ręczne. Jako osoba zainteresowana algorytmami, dodatkowy kod znany jako testy jednostkowe działa w celu przetestowania twojego głównego projektu oprogramowania. Testy jednostkowe są zazwyczaj pisane przez programistów i są w centrum uwagi w środowisku TDD. Na przykład, testy jednostkowe są niezbędne przy tworzeniu tej książki. Korzystając z iOS XCTest Framework, przejrzyjmy, jak testy jednostkowe działają w Swift.
WORKING WITH XCTEST
Jeśli zapoznałeś się z koncepcjami Swift omówionymi w książce, nauka pisania testów jednostkowych powinna być prosta. Jak już mówiliśmy, testy jednostkowe służą do ćwiczenia kodu, który nie ma interfejsu użytkownika końcowego. Dla zilustrowania przyjrzyjmy się przypadkom testowym, które ćwiczą strukturę danych Stack.
Pomimo że książka nie omawia szczegółów zintegrowanego środowiska programistycznego Xcode (IDE), należy zauważyć, że testy mogą być wykonywane według funkcji, klasy lub celu. Korzystając z Xcode, testy jednostkowe tworzy się poprzez dodanie nowego celu testowego do głównego projektu kodu. Po skonfigurowaniu, testy jednostkowe mogą być wykonywane z IDE lub wiersza poleceń.
Zasady testowania
Choć nie jest to wymagane, uważa się za najlepszą praktykę, jeśli plik testu jednostkowego ściśle odpowiada konwencji nazewnictwa naszego pliku (plików) implementacji. W naszym przypadku, będziemy używać StackTest.swift. Aby uzyskać dostęp do podstawowych metod i właściwości Stack z naszego głównego projektu, plik będzie również zawierał testowalną deklarację importu:
Podobnie jak inne frameworki testów jednostkowych, XCTest działa poprzez integrację cech języka Swift z określonymi funkcjami związanymi z testami. Istotne metody są zgrupowane razem jako asercje. Podczas tworzenia testów, kompilator rozpozna testy jednostkowe z funkcjami poprzedzonymi słowem kluczowym test.
W przeciwieństwie do zwykłych funkcji Swift, testy jednostkowe są celowo zaprojektowane jako samodzielne jednostki logiki. W rezultacie, metody testowe nie przyjmują argumentów i nie zwracają wartości. Alternatywnie, dane testowe mogą być zarządzane za pomocą metod pomocniczych i sekwencji inicjalizacji / rozbiórki. Rozważmy następującą sytuację:
PLANOWANIE TESTÓW
Jak wspomniano, główną operacją struktury danych Stack jest dodawanie i usuwanie elementów. Zamiast pisać pojedynczą funkcję do testowania wszystkich operacji, nasz plan testowy izoluje każdą główną operację stosu za pomocą własnego testu. Jak widać w przypadku testPushStack, asercja XCTAssertTrue sprawdza poprawność inicjalizacji zmiennej Stack.count. Kolejny krok polega na przećwiczeniu Stack.push poprzez iterację przez tablicę elementów NumberList. Aby zweryfikować, że każdy test wykorzystuje te same dane, numberList jest wypełniana za pomocą metody setup klasy XCTestCase.
Mając zaimplementowany test jednostkowy dodawania elementów Stack, możemy napisać następny test usuwania elementów: