Wolę testowanie interfejsu niż testowanie implementacji.
Rozumiem, że prywatne metody są niestabilne
Zależy to od środowiska programistycznego, patrz poniżej.
[prywatne metody] nie powinny się martwić, ponieważ publiczny interfejs API dostarczy wystarczających informacji do weryfikacji integralności obiektu.
Zgadza się, TDD koncentruje się na testowaniu interfejsu.
Metody prywatne są szczegółami implementacji, które mogą ulec zmianie w dowolnym cyklu ponownego czynnikowania. Powinna istnieć możliwość ponownego uwzględnienia współczynnika bez zmiany interfejsu lub zachowania czarnej skrzynki . W rzeczywistości jest to część korzyści TDD, łatwość, z jaką można wygenerować pewność, że zmiany wewnętrzne w klasie nie wpłyną na użytkowników tej klasy.
Cóż, mogę stworzyć obiekt, który ma tylko prywatne metody i wchodzi w interakcje z innymi obiektami, słuchając ich wydarzeń. Byłoby to bardzo zamknięte, ale całkowicie nie do przetestowania.
Nawet jeśli klasa nie ma metod publicznych, to moduły obsługi zdarzeń są interfejsem publicznym i działają przeciwko temu interfejsowi publicznemu , który można przetestować.
Ponieważ zdarzenia są interfejsem, należy je wygenerować, aby przetestować ten obiekt.
Spójrz na użycie fałszywych obiektów jako kleju dla twojego systemu testowego. Powinno być możliwe utworzenie prostego obiektu próbnego, który generuje zdarzenie i odbiera wynikową zmianę stanu (możliwe przez inny obiekt próbny odbiornika).
Ponadto uważanie za złe praktyki dodawania metod w celu testowania.
Absolutnie powinieneś bardzo uważać na ujawnianie stanu wewnętrznego.
Czy to oznacza, że TDD stoi w sprzeczności z enkapsulacją? Jaka jest odpowiednia równowaga?
Absolutnie nie.
TDD nie powinno zmieniać implementacji twoich klas inaczej niż być może je uprościć (poprzez zastosowanie YAGNI z wcześniejszego punktu).
Najlepsza praktyka z TDD jest identyczna z najlepszą praktyką bez TDD, po prostu dowiedz się, dlaczego wcześniej, ponieważ używasz interfejsu podczas jego opracowywania.
Jestem skłonny upublicznić większość lub wszystkie moje metody ...
Byłoby to raczej wylewanie dziecka z kąpielą.
Nie powinno się potrzeba , aby wszystkie metody publiczne, tak aby można rozwijać w sposób TDD. Zobacz moje notatki poniżej, aby sprawdzić, czy twoje prywatne metody naprawdę nie są sprawdzalne.
Bardziej szczegółowe spojrzenie na testowanie metod prywatnych
Jeśli bezwzględnie musisz przeprowadzić test jednostkowy prywatnego zachowania klasy, w zależności od języka / środowiska, możesz mieć trzy opcje:
- Umieść testy w klasie, którą chcesz przetestować.
- Umieść testy w innym pliku klasy / źródłowym i ujawnij metody prywatne, które chcesz przetestować jako metody publiczne.
- Użyj środowiska testowego, które pozwala zachować osobny kod testowy i produkcyjny, a jednocześnie umożliwiać dostęp kodu testowego do prywatnych metod kodu produkcyjnego.
Oczywiście trzecia opcja jest zdecydowanie najlepsza.
1) Umieść testy w klasie, którą chcesz przetestować (nie idealna)
Przechowywanie przypadków testowych w tym samym pliku klasy / źródłowym co testowany kod produkcyjny jest najprostszą opcją. Ale bez wielu dyrektyw lub adnotacji przedprocesowych skończy się to, że kod testowy niepotrzebnie rozszerzy kod produkcyjny, a w zależności od tego, jak zorganizujesz swój kod, możesz przypadkowo ujawnić wewnętrzną implementację użytkownikom tego kodu.
2) Ujawnij metody prywatne, które chcesz przetestować, jako metody publiczne (naprawdę nie jest to dobry pomysł)
Jak sugerowano, jest to bardzo zła praktyka, niszczy enkapsulację i ujawnia wewnętrzną implementację użytkownikom kodu.
3) Użyj lepszego środowiska testowego (najlepsza opcja, jeśli jest dostępna)
W świecie Eclipse 3. można osiągnąć za pomocą fragmentów . W świecie C # moglibyśmy używać klas częściowych . Inne języki / środowiska często mają podobną funkcjonalność, wystarczy ją znaleźć.
Ślepe założenie, że 1. lub 2. są jedynymi opcjami, prawdopodobnie spowodowałoby, że oprogramowanie produkcyjne byłoby nadęte kodem testowym lub nieprzyjemnymi interfejsami klasowymi, które publicznie piorą brudną bieliznę. * 8 ')
- Podsumowując - znacznie lepiej jest jednak nie testować pod kątem prywatnej implementacji.