Co to są testy jednostkowe czarnej skrzynki?

11

Niedawno zdałem ostatni egzamin na kurs inżynierii oprogramowania dla mojego programu magisterskiego i jedno z pytań na egzaminie było następujące:

Unit Testing is considered:
a. White-box Testing
b. Black-box Testing
c. Either

W ciągu moich 7 lat doświadczenia w tworzeniu oprogramowania, testy jednostkowe zawsze przyjmowały podejście „białej skrzynki”. Tester zawsze miał pełną wiedzę na temat implementacji jednostki podczas pisania testów. Testy „czarnej skrzynki” zawsze następowały później w formie testów integracyjnych, systemowych i akceptacyjnych.

Jednak prawidłowa odpowiedź na egzamin (zdaniem profesora) jest taka, że ​​testowanie jednostkowe może być testem białym lub czarnym.

Przeprowadziłem pewne badania i wydaje się, że w wielu przypadkach „testowanie jednostkowe czarnej skrzynki” jest używane do opisania podejścia opartego na pierwszym teście, w którym testy jednostkowe są zapisywane przed kodem. Jednak moim zdaniem jest to nadal testowanie białej skrzynki. Chociaż implementacja jeszcze nie istnieje, każdy, kto pisze test, ogólnie ma całkiem niezły pomysł na to, w jaki sposób zostanie zaimplementowany kod źródłowy.

Czy ktoś może mi wyjaśnić, jak działa testowanie czarnej skrzynki (jeśli to naprawdę jest rzecz) i czym różni się od testowania białej skrzynki?

backcab
źródło
4
jak profesor wyjaśnił to, kiedy zapytałeś ich o to? (zobacz także Dlaczego pytania w trakcie wywiadu sprawiają, że pytania z Software Engineering.SE są kiepskie? )
gnat
„Kto pisze test ma na ogół całkiem dobry pomysł o tym, jak testy będą realizowane” - nie chodzi o to, czy wiesz, jak badanie jest realizowane, ale czy wiesz (biały) lub nie (czarny) w jaki sposób rzeczy testujesz jest zaimplementowany.
Jesper,
@Jesper przepraszam. Chciałem powiedzieć „w jaki sposób zostanie zaimplementowany kod źródłowy”. Naprawiłem to w pytaniu.
backcab
2
While the implementation does not yet exist, whoever is writing the test generally has a pretty good idea about how the source code is going to be implemented.- Tak, ale sam test nie. Testowanie białych skrzynek oznacza testowanie czegoś wewnętrznego w metodzie lub klasie, na przykład wartości zmiennej. Nie oznacza to, że autor testów wie, jak wygląda testowany kod.
Robert Harvey,
1
Powiązane, może być postrzegane jako duplikat: czy TDD formalnie używa testów czarnej skrzynki w celu uzupełnienia testów jednostkowych
Doc Brown

Odpowiedzi:

20

Twój profesor ma rację: testy jednostkowe mogą być albo czarne, albo białe. Różnica polega nie tyle na tym, co wie tester, ale na tym, jak generujesz przypadki testowe.

Podczas testowania czarnej skrzynki patrzysz tylko na interfejs i (jeśli istnieje) specyfikację komponentu. Gdy funkcja ma sygnaturę int foo(int a, int b), mogę natychmiast wygenerować kilka przypadków testowych, po prostu testując interesujące liczby całkowite: zero, jeden, minus jeden, liczby wielocyfrowe, INT_MAX, INT_MAX - 1 i tak dalej. Testy czarnej skrzynki są świetne, ponieważ są niezależne od implementacji. Ale mogą również przegapić ważne przypadki.

Za pomocą testu białej skrzynki patrzę na implementację, tj. Kod źródłowy i generuję z niego przypadki testowe. Na przykład chciałbym uzyskać 100% pokrycia ścieżki dla funkcji. Następnie wybieram wartości wejściowe, aby wszystkie ścieżki były zajęte. Testy białych skrzynek są świetne, ponieważ mogą one wyczerpująco wykonać fragment kodu, z większą pewnością niż testy czarnej skrzynki. Ale mogą testować tylko szczegóły implementacji, a nie ważne zachowanie. W niektórych przypadkach są to wyraźnie strata czasu.

Ponieważ test białej skrzynki pochodzi z implementacji, można go napisać dopiero później. Test czarnej skrzynki pochodzi z projektu / interfejsu / specyfikacji i dlatego można go napisać przed wdrożeniem lub po nim. TDD nie jest ani wyraźnie czarne, ani białe. Ponieważ wszystkie zachowania są najpierw wyrażane przez test, a następnie wdrażany jest minimalny kod dla tego zachowania, TDD daje wyniki w testach podobnych do testu białych skrzynek. Ale gdy spojrzymy na przepływ informacji, testy TDD nie pochodzą z kodu źródłowego, ale z wymagań zewnętrznych. Dlatego TDD jest bardziej podobny do czarnej skrzynki.

amon
źródło
3
„Ponieważ test białej skrzynki pochodzi od implementacji, można go napisać dopiero później” - cóż, jeśli mam zamiar napisać test zakończony niepowodzeniem w stylu TDD dla następnej nowej funkcji, którą chcę dodać do mojej istniejącej funkcji lub klasy , Najpierw zajmuję się bieżącą implementacją, aby dowiedzieć się, co nie jest do tej pory obsługiwane, dzięki czemu mogę zaprojektować bardziej znaczący - początkowo zawodzący - test. Nazywam to podejściem opartym na pierwszej próbie, a nie testem napisanym później. (Niemniej jednak +1 ode mnie).
Doc Brown,
4

Jeśli podejmujesz się programowania opartego na testach, teoretycznie wszystkie testy jednostkowe powinny być czarne. To jest twoje „pierwsze podejście testowe”. Piszesz umowę (interfejs), piszesz testy dla tej umowy, a następnie umowa zostaje spełniona przez wdrożenie. Dlatego test nie wie nic i nie powinien nic wiedzieć o implementacji.

W końcu, kiedy piszesz test, co testujesz? Metody / funkcje publiczne.

Jeśli miałbyś napisać interfejs dla klasy, a następnie napisać testy, a następnie zostałeś potrącony przez autobus, facet, który pisze klasę podczas pobytu w szpitalu, powinien móc to zrobić z twojego interfejsu, prawda? Nie powinien go wyrzucać, pisać własnego interfejsu i testów.

To się w pewnym sensie rozpada, gdy musisz kpić z czegoś, od czego zależy implementacja, ale jeśli znajdziesz się w sytuacji, w której kpisz z czegoś, co nigdy nie jest ujawniane publicznie, to popełniłeś błąd i musisz patrz Dependency Injection i in . Dlatego twierdzę, że testy jednostkowe białych skrzynek, a nie czarne, powinny być wyjątkiem.

Rozważ „Testowanie w toalecie - zachowanie testowe nie jest implementacją” , w którym implementacja klasy jest zmieniona, ale testy powinny być nadal aktualne.

Jeśli jednak musisz upewnić się, że zasięg kodu jest wyższy (tj. Upewnić się, że wszystkie ścieżki warunkowe zostały przetestowane w ramach implementacji), wtedy absolutnie musisz przeprowadzić test jednostkowy białej skrzynki, ponieważ tylko w ten sposób możesz wiedzieć, jakie są twoje ścieżki są patrząc na ścieżki w implementacji.

AdamJS
źródło
2
If you were to write the interface for a class, and then write the tests, and then you get hit by a bus, the guy who writes the class while you're in hospital should be able to do so from your interface, right?-- Nie dokładnie. Większość umów API tak naprawdę tylko podpisy metod, a nie semantykę lub zachowanie.
Robert Harvey,
Masz rację; Uznałem za pewnik, że twój interfejs będzie zawierał specyfikację, z której został napisany, a nie dosłownie tylko tekst MyClassInterface.
AdamJS,
@RobertHarvey to prawda, że ​​większość interfejsów nie opisuje jawnie semantyki ani zachowania, ale myślę, że ogólnie jest to niejawne. Gdyby go nie było, kod wymagający pewnej semantyki nie byłby w stanie polegać na abstrakcji. I nie ma nic do zatrzymania interfejsów, w tym szczegóły semantyki i zachowania jako komentarze / docbloki. Na przykład patrz github.com/php-fig/http-message/blob/master/src/…
bdsl
3

Twierdziłbym, że wszystkie dobrze napisane testy jednostkowe są z natury „czarnymi skrzynkami”. Pewnie, że mogę mieć na myśli implementację, gdy piszę test, ale ta implementacja może się zmienić, gdy refaktoryzuję. Dlatego test powinien używać tylko publicznych interfejsów API podczas testu w celu przetestowania funkcjonalności, a nie implementacji. Nie dbają o szczegóły implementacji, więc testowanie czarnej skrzynki.

Jeśli piszę testy, które mają dostęp do wewnętrznych lub prywatnych aspektów testowanego urządzenia, to testuję szczegóły implementacji: testuję białe pudełko. Ale piszę też kruche testy, które można łatwo przerwać po zmianie implementacji. Dlatego takie testy białych skrzynek są złym pomysłem i należy ich unikać.

Wniosek: jeśli wykonujesz test białej skrzynki z testami jednostkowymi, masz źle skonstruowane testy. Test tylnego pudełka tylko przy tych testach jednostkowych. Twój profesor ma rację: może być albo. Ale tylko jeśli źle zrobione.

David Arno
źródło
1

Właśnie pisałem testy jednostkowe, które przeprowadzają testy czarnej skrzynki. Oznacza to, że testuję metody publiczne w klasie i implikując logikę testowania wyników w metodach prywatnych, które nazywają.

Robię to, zmieniając dane wejściowe na publiczną metodę testowaną jednostkowo i testując oczekiwane wyniki, które są określane lub mutowane przez logikę w obsługiwanych metodach prywatnych, o których implementacji moje „testy jednostkowe” nie muszą nic wiedzieć.

Nic więc nie stoi na przeszkodzie, abyś przeprowadzał testy czarnej skrzynki na testach jednostkowych, a testy zostaną przerwane, jeśli ktoś zadziała z implementacją ukrytej logiki pomocniczej. W rzeczywistości wydaje się, że jest to lepsze, bardziej wydajne podejście niż jednostka białych skrzynek testująca wszystko ze względu na to. Jestem z profesorem.

Shooresh
źródło