Skocz do zawartości

Robimy fajne filmy o Androidzie na YouTube! Daj nam suba!

Coderoid

Piszmy testy jednostkowe!

Polecane posty

Coderoid   
Otrzymana reputacja: 206
Coderoid
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 
folder.png
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:
sort_Method.png
Teraz w MainActivity utwórzmy sobie listę nieposortowanych liczb i poddajmy ją naszej metodzie sortującej, a następnie wyświetlmy w textview:
mainactivity.png
Kiedy mamy już tak przygotowany projekt, przechodzimy do naszej klasy Utils i tworzymy do niej test. Użyjemy do tego skrótu ctrl+shift+T. 
create_Test.png
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ę. 
create_Test2.png
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:
created_Empty_Test_Method.png
Piszemy teraz test, który przetestuje naszą metodę 'sortNumbersDescending' z klasy 'Utils'. Do testu będziemy potrzebować nieposortowaną listę (metoda getFakeList). 
fake_List.png
Oraz sam test który sprawdzi czy nasza metoda dobrze sortuje.
test.png
Uruchamiamy nasz test klikając prawym na klasę i "Run Utils Test" lub ctrl+shift+f10.
Jako potwierdzenie dostajemy
testpassed.png
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. 
 
  • Lubię to! 2

Udostępnij link do tego posta


Odnośnik do posta
Udostępnij na stronach
szamot   
Otrzymana reputacja: 1
szamot

Chociaż sama zachęta do pisania testów zasługuje na uznanie i oklaski, to za przedostatnie zdanie należy się pluton egzekucyjny...

Dnia 13.08.2016 o 11:23, Coderoid napisał:
3. W testach niekoniecznie muszą obowiązywać zasady dobrego programowania. Testy mają być dla was jako sprawdzenie, a nie żeby wyglądały. 

Ponieważ sam mam niewielkie doświadczenie jeśli chodzi o testy, to oddam głos dla wujka Boba:
"Kilka lat temu zostałem poproszony o kierowanie zespołem, który wcześniej zdecydował, że jego kod testujący nie powinien być utrzymywany zgodnie z tymi samymi standardami jakości co kod produkcyjny. Programiści dali sobie przyzwolenie na łamanie reguł w testach jednostkowych. Myślą przewodnią było "szybki i brudny". (...)

Jednak zespół nie zorientował się, że korzystanie z takich testów odpowiada... brakowi testów, o ile nie jest czymś gorszym. Problem wynika z tego, że testy muszą się zmieniać wraz z ewoluowaniem kodu produkcyjnego. Im gorsze są testy, tym trudniej je zmieniać. Im bardziej zagmatwany jest kod testujący, tym większe prawdopodobieństwo, że spędzimy więcej czasu na dodawaniu nowych testów do pakietu niż na pisaniu nowego kodu produkcyjnego."
We wspomnianym projekcie, koszt zmian w kodzie ciągle wzrastał, programiści winili za to testy, więc kierownictwo kazało je usunąć, co spowodowało, że w kodzie było coraz więcej nieoczekiwanych błędów, programiści bali się cokolwiek zmienić i ostatecznie zostali z zagmatwanym i pełnym błędów kodem produkcyjnym i sfrustrowanym klientem.
"Morał z tej historii jest prosty: kod testów jest tak samo ważny jak kod produkcyjny. Nie jest to obywatel drugiej kategorii. Wymaga przemyślenia, zaprojektowania i uwagi. Musi być utrzymywany zgodnie z takimi samymi zasadami co kod produkcyjny."
 

Co do zdania "testy mają być dla was" warto jeszcze wspomnieć inną uwagę wujka Boba, a mianowicie, że nie jest powiedziane, że wiecznie będziemy pracować nad naszym kodem, może go dostać ktoś inny, a wtedy powinien być tak dobry jakim sami chcielibyśmy go zastać.


Cytaty pochodzą z książki Czysty Kod, podręcznik dobrego programisty autorstwa Roberta C. Martina

Zdecydowanie podpisuję się pod tytułem tego wątku, przy uwzględnieniu tego co zacytowałem powyżej.
Pozdrawiam

  • Lubię to! 1

Udostępnij link do tego posta


Odnośnik do posta
Udostępnij na stronach

Żeby dodać komentarz, musisz założyć konto lub zalogować się

Tylko zarejestrowani użytkownicy mogą dodawać komentarze

Dodaj konto

Załóż nowe konto. To bardzo proste!

Zarejestruj nowe konto

Zaloguj się

Posiadasz już konto? Zaloguj się tutaj.

Zaloguj się teraz


  • Przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników, przeglądających tę stronę.

×