Testowanie - testy jednostkowe
Test jednostkowy (ang. unit test) to w programowaniu metoda testowania tworzonego oprogramowania poprzez wykonywanie testów weryfikujących poprawność działania pojedynczych elementów (jednostek) programu - np. metod lub obiektów w programowaniu obiektowym lub procedur w programowaniu proceduralnym. Testowany fragment programu poddawany jest testowi, który wykonuje go i porównuje wynik (np. zwrócone wartości, stan obiektu, wyrzucone wyjątki) z oczekiwanymi wynikami - tak pozytywnymi, jak i negatywnymi (niepowodzenie działania kodu w określonych sytuacjach również może podlegać testowaniu)
Test jednostkowy to fragment kodu, który sprawdza inny fragment kodu”
Więcej: Test jednostkowy
Aksjomaty testowania
Żadnego realnego oprogramowanie nie da się przetestować całkowicie. Test nie udowadnia braku błędów, a udowadnia jedynie to, ze ich nie znaleźliśmy
Testy są czasochłonne
Testowanie jest kosztowne
Testowanie jest ryzykowne
Paradoks pestycydów
Nie wszystkie znalezione błędy zostaną naprawione (za duży koszt, brak czasu, ryzyko naprawy)
Testy są nużące
Testowanie wymaga wyobraźni i złośliwości
Czym są testy jednostkowe?
Testy jednostkowe (ang. unit test) porównują oczekiwany wynik funkcji z rzeczywistym rezultatem. Na przykład sprawdźmy funkcję sumującą dwie liczby całkowite. W łatwy sposób można ustalić dane wejściowe oraz oczekiwany wynik:
Testy czarnej skrzynki.
Cechy
pozwala efektywnie wyszukiwać błędy w istniejącym kodzie
umożliwiają szybką weryfikację nowych elementów programu
ułatwiają pracę zespołowądzięki łatwiejszemu łączeniu różnych fragmentów kodu podanych wcześniej testom
zmusza do lepszego przemyślenia rozwiązań. Musimy dokładnie określić jakie zadania dana metoda ma wykonywać.
oszczędność czasu - testy są w pełni powtarzalne i zautomatyzowane
testy zautomatyzowane można uruchamiać regularnie o określonych porach lub na pewnych etapach produkcji (np. codziennie w nocy, aby rano był dostępny pełny raport)
odporność na błędy regresyjne - błędy powracające po jakiejś modyfikacji kodu
Dobrze napisane testy
Test-driven development
Technika zwinna (agile), zaliczana także do programowania ekstremalnego.
najpierw test sprawdzający dodawaną funkcjonalność (test nieudany)
implementacja funkcjonalności (test udany)
refaktoryzacja napisanego kodu, żeby spełniał on oczekiwane standardy.
Zalety:
szybkie wychwytywanie błędów
zmniejszenie kosztu, błędy wykryte przez autora kodu i poprawiane na bieżąco kosztują niewiele
bardziej przemyślany kod
możliwość przetestowania funkcjonalności bez uruchamiania całego oprogramowania
tworzenie swoistej dokumentacji - test pokazuje jak używać danej funkcjonalności
Źródło: Test-driven development Wstęp do Test Driven Development (MSDN)
Środowiska testowe
Narzędzia i biblioteki wspierające tworzenie testów, ich organizację, automatyzację wykonywania, raportowanie
Java → JUnit, TestNG
PHP → PHPUnit
C → MinUnit, CUnit, (biblioteka assert.h)
c++ → Glib , Boost Test Library, CppUnit, Cantata++
.Net → Visual Studio Unit Testing Framework (w VS od 2005, Proffesional, Ultimate), NUnit
Delphi → DUnit, Fortran → pFUnit
List_of_unit_testing_frameworks
Testy jednostkowe w Visual Studio
Tworzenie testu istniejącej metody:
Create Unit test
Wybieranie metod, dla których zostaną wygenerowane testy jednostkowe
wygenerowany nowy projekt zawierający testy jednostkowe
Automatycznie wygenerowana metoda testująca
Uruchamianie testów → Run Tests
Raport z wykonania testów
Namespace: Microsoft.VisualStudio.TestTools.UnitTesting
Przykład
public class BasicOperations
{
public int Add(int numberA, int numberB)
{
return numberA + numberB;
}
public int Subtract(int numberA, int numberB)
{
return numberA - numberB;
}
public int Multiply(int numberA, int numberB)
{
return numberA * numberB;
}
public int Divide(int numberA, int numberB)
{
return numberA / numberB;
}
}
Typy asercji
Zazwyczaj przyjmuje formę wyrażenia logicznego, które zwraca albo prawdę albo fałsz.
Stanowi więc doskonałe narzędzie, dzięki któremu możemy w prosty sposób, wychwycić błędy w pisanych aplikacjach.
AreEqual / AreNotEqual - czy równe / różne
AreSame / AreNotSame - czy przekazane wartości nie odnoszą się do tego samego obiektu (bada referencje, a nie wartości)
Fail - test jednostkowy jest niezaliczony
Inconclusive -wykonanie testu jest nierozstrzygnięte
IsTrue / IsFalse - czy dostarczona wartość lub wyrażenie są prawdziwe / fałszywe
IsInstanceOfType / IsNotInstanceOfType - czy dostarczona wartość nie jest podanego typu
IsNull / IsNotNull - czy dostarczona wartość nie jest NULL
Zakres dostępu
metody publiczne, bez problemu
metody chronione - nie można w bezpośredni sposób wywołać metody chronionej ze sterownika testu. Rozwiązaniem jest stworzenie klasy opakowującej dziedziczącej po badanej klasie i wywołanie chronionych metod w w dziedziczącej klasie bazowej
metody prywatne są jeszcze trudniejsze do przetestowania. Nie nie można ich wywołać bezpośrednio w kodzie. Jednak modyfikatory public, protected, private mają znaczenie wyłącznie dla kompilatora. Za pomocą mechanizmu refleksji można ominąć ograniczenia i wywołać prywatną metodę.
Pokrycie kodu (code coverage)
Pokrycie kodu mierzy, ile procent kodu zostało sprawdzone przez testy jednostkowego. Przyjmuje się, że dobrze napisane testy powinny mieć pokrycie rzędu przynajmniej 70% .
Wyróżniamy dwa sposoby wyliczania pokrycia:
Pokrycie wyrażeń (ang. statement coverage) – metryka stanowi iloraz liczby linii kodu wywołanych przez testy jednostkowe oraz całkowitej liczby linii kodu. Jeśli jakaś linia nie została pokryta, istnieje zatem ryzyko wystąpienia w niej błędu.
Pokrycie rozgałęzień (ang. branch coverage) – pokrycie nie bada linii kodu, a rozgałęzienia zrealizowane za pomocą np. instrukcji if.
Bibliografia