View page as slide show

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

  • Ż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

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.

  • 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
  • Niezależność oraz izolacja
    • sprecyzowany fragment kodu,
    • nie można pisać testów badających kilka funkcji naraz,
    • makiety obiektów,
    • niezależność od zewnętrznych zasobów)
  • Przejrzystość (testy mogą posłużyć jako dokumentacja)
  • Szybkość

Technika zwinna (agile), zaliczana także do programowania ekstremalnego.

  1. najpierw test sprawdzający dodawaną funkcjonalność (test nieudany)
  2. implementacja funkcjonalności (test udany)
  3. 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)

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

  • 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
    • Assert
    • ExpectedExceptionAttribute
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;
        }
    }

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
  • 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 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.
  • VS Test → Edit Test Settings → Local
    • Data and Diagnostic → Code Coverag
    • Configure - wybór źródła danych do analizy