Kto z Was nie spotkał się z sytuacją kiedy pisał funkcjonalność do projektu, gdzie trzeba było zrobić małą zmianę w kodzie, a następnie czekać aż projekt się zbuduje, aplikacja zainstaluje na urządzeniu? Dopiero po tych czynnościach można było sprawdzić czy dana funkcjonalność została dobrze zaimplementowana.
Zdaję sobie sprawę, że o ile małe projekty mogą się szybko budować i instalować na urządzeniu, tak większe potrafią zająć więcej czasu.
Przypuśćmy, że w naszej aplikacji jest funkcjonalność, która sortuje liczby od największej do najmniejszej. Jest to co prawda banalny przykład, ale można w łatwy sposób pokazać, jak testować funkcjonalność bez konieczności wgrywania tego na urządzenie. Takich operacji, które można przetestować bez użycia urządzenia jest masa. Dzięki testom zaoszczędzimy czas, który poświęcimy na sprawdzanie tego ręcznie w aplikacji.
Po co są testy jednostkowe?
1. Implementując algorytm możemy przetestować go wrzucając do niego wartości które mogą go "położyć" (np
null).
2. Jeśli napiszemy funkcjonalność, którą nie chcemy aby ktoś zmieniał, pisząc test mamy pewność, że po zmianie funkcjonalności test się wyłoży, a ten ktoś zatrzyma się na chwilę i stwierdzi
"Ciekawe dlaczego ktoś akurat tak to zrobił? Może nie powinienem tego zmieniać?". Unikniemy w tym przypadku niepożądanej zmiany, która może wpłynąć na działanie aplikacji.
Warto w tym miejscu jeszcze wspomnieć, że testy dzielą się na:
- jednostkowe (ten tutorial tego dotyczy) - katalog test
- integracyjne (testujemy np integrację z zewnętrznym serwisem)
- automatyczne (testujemy zachowanie aplikacji, layout'u) - katalog AndroidTest
Nasze testy jednostkowe oprzemy o framework
Junit w wersji 4.12 oraz o bibliotekę wspierającą asercje
AssertJ Android od
square.
Zatem wymagania projektu:
1. Android Studio
2. Java w wersji 7
3. Minimum SKD 19 (takiego użyłem, ale można niżej)
4. Framework
Junit
http://junit.org/junit4/
5. Bibliotek
AssertJ Android
https://github.com/square/assertj-android
Utwórzmy sobie nowy projekt. Po wygenerowaniu nowego projektu, powinniśmy znaleźć taką strukturę katalogów
Interesuje nas katalog '
test' w którym będziemy umieszczać klasy odpowiedzialne za testowanie danej funkcjonalności. Powinna się tam znaleźć klasa
ExampleUnitTest, a w niej już jestem gotowy przykład. Usuwamy tą klasę.
Przechodzimy teraz do pliku
build.gradle w katalogu "
app" i jako dependencies dodajemy dwie pozycje:
compile 'com.squareup.assertj:assertj-android:1.1.1'
testCompile 'junit:junit:4.12'
Synchronizujemy
Gradle i czekamy.
Utwórzmy sobie klasę
Utils w której będziemy wykonywać operacje takie jak sortowanie liczb. Klasa powinna znaleźć się w tym samym katalogu co
MainActiviy. W tej klasie utworzymy sobie metodę, która w parametrze przyjmie liczby z listy nieposortowane i zwróci nam listę liczb posortowaną od największej do najmniejszej. A zatem:
Teraz w
MainActivity utwórzmy sobie listę nieposortowanych liczb i poddajmy ją naszej metodzie sortującej, a następnie wyświetlmy w
textview:
Kiedy mamy już tak przygotowany projekt, przechodzimy do naszej klasy
Utilsi tworzymy do niej test. Użyjemy do tego skrótu
ctrl+shift+T.
Po zatwierdzeniu enterem wyskoczy nam okienko numer 1. Klikamy
OK. W okienku numer 2 zaznaczamy katalog w którym chcemy, aby klasa się utworzyła. Interesuje nas katalog '
test' ponieważ to on odpowiada za testy jednostkowe. Klikamy
OK i mamy wygenerowaną klasę.
W klasie która została utworzona ("
Utils Test") wciskany skrót alt+insert i z okienka dialogowego wybieramy '
Test Method'. Metodę nazywamy '
shouldReturnSortedList'.
Całość wygląda tak:
Piszemy teraz test, który przetestuje naszą metodę '
sortNumbersDescending' z klasy '
Utils'. Do testu będziemy potrzebować nieposortowaną listę (metoda
getFakeList).
Oraz sam test który sprawdzi czy nasza metoda dobrze sortuje.
Uruchamiamy nasz test klikając prawym na klasę i "
Run Utils Test" lub
ctrl+shift+f10.
Jako potwierdzenie dostajemy
Spróbujcie teraz wstawić do listy inne wartości, pobawcie się metodą testującą i np zamiast
assertThat(sortedList.get(0)).isEqualTo(4);
zróbcie
assertThat(sortedList.get(0)).isEqualTo(5);
Uruchomcie test i zobaczcie co się stało 🙂
Teraz jeszcze jako potwierdzenie możecie uruchomić aplikację na urządzeniu, ale cały proces pokazuje, że wcale nie trzeba tego robić.
Jeszcze kilka słów o nazewnictwie metod w testach.
1. Metoda testująca powinna zaczynać się od słów kluczowych takich jak
should.
2. Nazwy metod, obiektów powinny zawierać takie słowa kluczowe jak
fake, stubb, mock.
3. W testach niekoniecznie muszą obowiązywać zasady dobrego programowania. Testy mają być dla was jako sprawdzenie, a nie żeby wyglądały.
P.S Celowo nie daję kodu w formie tekstu tylko jako screen'y aby zmusić Cię do przepisania tego, a nie skopiowania.