Czy powinienem unikać metod prywatnych, jeśli wykonuję TDD?

99

Właśnie uczę się TDD. Rozumiem, że prywatne metody są nie do przetestowania i nie powinny się martwić, ponieważ publiczny interfejs API dostarczy wystarczających informacji do weryfikacji integralności obiektu.

Przez jakiś czas rozumiałem OOP. Rozumiem, że prywatne metody sprawiają, że obiekty są bardziej enkapsulowane, a przez to bardziej odporne na zmiany i błędy. Dlatego powinny być używane domyślnie i tylko te metody, które mają znaczenie dla klientów, powinny być upublicznione.

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.

Ponadto uważanie za złe praktyki dodawania metod w celu testowania.

Czy to oznacza, że ​​TDD stoi w sprzeczności z enkapsulacją? Jaka jest odpowiednia równowaga? Jestem skłonny upublicznić większość lub wszystkie moje metody ...

szczenię
źródło
9
Zła praktyka i rzeczywistość w branży oprogramowania to różne zwierzęta. Idealna sytuacja jest najczęściej zniekształconą rzeczywistością w świecie biznesu. Rób to, co ma sens, i trzymaj się tego przez całą aplikację. Wolałbym mieć złą praktykę niż smak miesiąca rozłożony na całą aplikację.
Aaron McIver
10
„metody prywatne są niestabilne”? Który język? W niektórych językach jest to niewygodne. W innych językach jest to całkowicie proste. Czy twierdzisz również, że zasada projektowania enkapsulacji musi być zawsze wdrażana za pomocą wielu prywatnych metod? To wydaje się nieco ekstremalne. Niektóre języki nie mają prywatnych metod, ale wciąż wydają się mieć ładnie zamknięte projekty.
S.Lott,
„Rozumiem, że prywatne metody sprawiają, że obiekty są bardziej enkapsulowane, a przez to bardziej odporne na zmiany i błędy. Dlatego powinny być używane domyślnie, a tylko te metody, które mają znaczenie dla klientów, powinny być upublicznione”. Wydaje mi się, że to kontrapunkt z punktu widzenia tego, co TDD próbuje osiągnąć. TDD to metodologia programowania, która prowadzi do stworzenia prostego, wykonalnego i otwartego na zmiany projektu. Wyszukiwanie „z prywatnego” i „tylko reklamować ...” jest całkowicie odwrócone. Zapomnij, że istnieje coś takiego jak prywatna metoda na przyjęcie TDD. Później wykonaj je w razie potrzeby; w ramach refaktoryzacji.
herby
Więc @gnat, myślisz, że to powinno zostać zamknięte jako duplikat pytania, które powstało z mojej odpowiedzi na to pytanie? * 8 ')
Mark Booth

Odpowiedzi:

50

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:

  1. Umieść testy w klasie, którą chcesz przetestować.
  2. Umieść testy w innym pliku klasy / źródłowym i ujawnij metody prywatne, które chcesz przetestować jako metody publiczne.
  3. 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.
Mark Booth
źródło
5
Nie jestem pewien, czy zgodziłbym się z którąkolwiek z trzech sugerowanych przez ciebie opcji. Wolę testować tylko interfejs publiczny, jak powiedziałeś wcześniej, ale upewnić się, że dzięki temu stosowane są prywatne metody. Jedną z zalet tej metody jest znalezienie martwego kodu, co jest mało prawdopodobne, jeśli wymusisz na kodzie testowym przerwanie normalnego używania języka.
Mag
Twoje metody powinny zrobić jedną rzecz, a test nie powinien uwzględniać implementacji w żaden sposób. Metody prywatne są szczegółami implementacji. Jeśli testowanie tylko metod publicznych oznacza, że ​​testy są testami integracji, oznacza to, że masz problem z projektem.
Mag
Co powiesz na ustawienie metody jako domyślnej / chronionej i utworzenie testu w projekcie testowym z tym samym pakietem?
RichardCypher
@RichardCypher To faktycznie tak samo jak 2), ponieważ zmieniasz specyfikację metody, aby idealnie dostosować się do niedoboru w środowisku testowym, więc zdecydowanie słaba praktyka.
Mark Booth,
75

Oczywiście możesz mieć metody prywatne i oczywiście możesz je przetestować.

Albo jest jakiś sposób na uruchomienie prywatnej metody, w którym to przypadku możesz to przetestować, albo nie ma sposobu na uruchomienie prywatnej, w takim przypadku: dlaczego, do cholery, próbujesz ją przetestować, po prostu usuń to cholerstwo!

W twoim przykładzie:

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.

Dlaczego miałoby to być niestabilne? Jeśli metoda zostanie wywołana w reakcji na zdarzenie, wystarczy, że test poda obiektowi odpowiednie zdarzenie.

Nie chodzi o brak prywatnych metod, chodzi o to, by nie zerwać enkapsulacji. Możesz mieć metody prywatne, ale powinieneś je przetestować za pomocą publicznego interfejsu API. Jeśli publiczny interfejs API jest oparty na zdarzeniach, użyj zdarzeń.

W przypadku bardziej powszechnego przypadku metod prywatnych pomocników można je przetestować za pomocą publicznych metod, które je wywołują. W szczególności, ponieważ możesz pisać tylko kod, aby przejść test zakończony niepowodzeniem, a twoje testy testują publiczny interfejs API, cały nowy kod, który piszesz, zwykle będzie publiczny. Metody prywatne pojawiają się tylko w wyniku refaktoryzacji metody wyodrębniania , gdy są wyciągane z już istniejącej metody publicznej. Ale w takim przypadku oryginalny test, który testuje metodę publiczną, obejmuje również metodę prywatną, ponieważ metoda publiczna wywołuje metodę prywatną.

Tak więc zwykle prywatne metody pojawiają się tylko wtedy, gdy są wyodrębnione z już przetestowanych metod publicznych, a zatem również są już przetestowane.

Jörg W Mittag
źródło
3
Testowanie metodami publicznymi działa dobrze przez 99% czasu. Wyzwaniem jest 1% czasu, w którym twoja pojedyncza metoda publiczna ma za sobą kilkaset lub tysiące linii złożonego kodu, a wszystkie stany pośrednie są specyficzne dla implementacji. Gdy stanie się wystarczająco skomplikowany, próba trafienia we wszystkie skrajne przypadki z metody publicznej staje się co najwyżej bolesna. Alternatywnie, testowanie przypadków skrajnych przez przerwanie enkapsulacji i ujawnienie większej liczby metod jako prywatnych lub przez użycie kludge, aby testy wywoływały metody prywatne bezpośrednio, skutkuje kruchymi przypadkami testowymi, a także brzydkością.
Dan Neely
24
Duże, złożone metody prywatne to zapach kodu. Implementacja, która jest tak złożona, że ​​nie można jej z łatwością rozłożyć na części składowe (z interfejsami publicznymi), stanowi problem w testowalności, który ujawnia potencjalne problemy projektowe i architektoniczne. 1% przypadków, w których prywatny kod jest ogromny, zwykle skorzysta z przeróbek w celu dekompozycji i ujawnienia.
S.Lott
13
@Dan Neely taki kod jest całkiem nie do przetestowania niezależnie - i część pisania testów jednostkowych wskazuje na to. Wyeliminuj stany, podziel klasy, zastosuj wszystkie typowe refaktoryzacje, a następnie napisz testy jednostkowe. Również z TDD, jak do tego doszedłeś? Jest to jedna z zalet TDD, pisanie testowalnego kodu staje się automatyczne.
Bill K
Przynajmniej internalmetody lub metody publiczne w internalklasach powinny być testowane bezpośrednio dość często. Na szczęście .net obsługuje tę InternalsVisibleToAttributemetodę, ale bez niej testowanie tej metody byłoby PITA.
CodesInChaos
25

Kiedy tworzysz nową klasę w swoim kodzie, robisz to, aby odpowiedzieć na niektóre wymagania. Wymagania mówią, co musi zrobić kod, a nie jak . Ułatwia to zrozumienie, dlaczego większość testów odbywa się na poziomie metod publicznych.

Poprzez testy weryfikujemy, czy kod działa zgodnie z oczekiwaniami , generuje odpowiednie wyjątki, gdy jest oczekiwany itp. Naprawdę nie obchodzi nas, w jaki sposób kod jest implementowany przez programistę. Chociaż nie obchodzi nas implementacja, czyli sposób, w jaki kod robi to, co robi, warto unikać testowania metod prywatnych.

Jeśli chodzi o testowanie klas, które nie mają żadnych publicznych metod i wchodzą w interakcję ze światem zewnętrznym tylko poprzez zdarzenia, możesz to również przetestować, wysyłając, poprzez testy, zdarzenia i słuchając odpowiedzi. Na przykład, jeśli klasa musi zapisać plik dziennika za każdym razem, gdy odbierze zdarzenie, test jednostkowy wyśle ​​zdarzenie i sprawdzi, czy plik dziennika został zapisany.

Wreszcie, w niektórych przypadkach testowanie metod prywatnych jest całkowicie poprawne. Dlatego na przykład w .NET możesz testować nie tylko klasy publiczne, ale także prywatne, nawet jeśli rozwiązanie nie jest tak proste jak w przypadku metod publicznych.

Arseni Mourzenko
źródło
4
+1 Jedną ważną cechą TDD jest to, że zmusza Cię do przetestowania, czy WYMAGANIA są spełnione, zamiast testowania, że ​​METODY robią to, co według ciebie robisz. Tak więc pytanie „Czy mogę przetestować metodę prywatną” jest nieco sprzeczne z duchem TDD - zamiast tego pytanie może brzmieć: „Czy mogę przetestować wymaganie, którego implementacja obejmuje metody prywatne”. Odpowiedź na to pytanie jest oczywiście twierdząca.
Dawood ibn Kareem
6

Rozumiem, że prywatne metody są niestabilne

Nie zgadzam się z tym stwierdzeniem lub powiedziałbym, że nie testujesz metod prywatnych bezpośrednio . Metoda publiczna może wywoływać różne metody prywatne. Być może autor chciał mieć „małe” metody i rozpakować część kodu w sprytnie nazwaną metodę prywatną.

Bez względu na sposób pisania metody publicznej kod testowy powinien obejmować wszystkie ścieżki. Jeśli po testach odkryjesz, że jedna z instrukcji gałęzi (if / switch) w jednej prywatnej metodzie nigdy nie była objęta twoimi testami, oznacza to, że masz problem. Albo przegapiłeś przypadek i implementacja jest prawidłowa LUB implementacja jest niepoprawna, a gałąź ta nigdy nie powinna istnieć.

Dlatego często używam Cobertura i NCover, aby upewnić się, że mój test metody publicznej obejmuje również metody prywatne. Nie krępuj się pisać dobrych obiektów OO metodami prywatnymi i nie pozwól, aby TDD / Testowanie poszło ci na drodze w takich sprawach.

Jalayn
źródło
5

Twój przykład jest nadal doskonale testowalny, dopóki używasz wstrzykiwania zależności w celu zapewnienia instancji, z którymi współdziała Twój CUT. Następnie możesz użyć makiety, wygenerować interesujące zdarzenia, a następnie obserwować, czy CUT podejmuje właściwe działania w zależności od swoich zależności.

Z drugiej strony, jeśli masz język z dobrą obsługą zdarzeń, możesz pójść nieco inną ścieżką. Nie podoba mi się, gdy obiekty same subskrybują zdarzenia, zamiast tego mam fabrykę, która tworzy obiekt, łącząc zdarzenia z publicznymi metodami obiektu. Łatwiej jest przetestować i sprawia, że ​​zewnętrznie widać, na jakie zdarzenia należy przetestować CUT.

Chris Pitman
źródło
To świetny pomysł - „... mieć fabrykę, która tworzy zdarzenia łączące obiekty z publicznymi metodami obiektu. Łatwiej jest przetestować i sprawia, że ​​z zewnątrz widać, na jakie rodzaje zdarzeń należy przetestować CUT. „
szczenię
5

Nie powinieneś rezygnować z prywatnych metod. Korzystanie z nich jest całkowicie uzasadnione, ale z perspektywy testowania trudniej jest przetestować bezpośrednio, bez przerywania enkapsulacji lub dodawania kodu specyficznego dla testów do twoich klas. Sztuką jest zminimalizowanie rzeczy, o których wiesz, że powodują skurcze jelit, ponieważ czujesz, jakbyś zabrudził kod.

To są rzeczy, o których pamiętam, aby spróbować osiągnąć równowagę.

  1. Zminimalizuj liczbę używanych prywatnych metod i właściwości. Większość rzeczy, które musisz zrobić w swojej klasie, i tak trzeba ujawnić publicznie, więc zastanów się, czy naprawdę musisz uczynić tę sprytną metodę prywatną.
  2. Zminimalizuj ilość kodu w swoich prywatnych metodach - naprawdę powinieneś to zrobić i tak - i przetestuj pośrednio, gdzie możesz, poprzez zachowanie innych metod. Nigdy nie spodziewasz się uzyskać 100% pokrycia testowego i być może będziesz musiał ręcznie sprawdzić kilka wartości za pośrednictwem debuggera. Korzystanie z prywatnych metod w celu zgłaszania wyjątków można łatwo przetestować pośrednio. Nieruchomości prywatne mogą wymagać przetestowania ręcznie lub inną metodą.
  3. Jeśli pośrednie lub ręczne sprawdzanie nie pasuje do ciebie, dodaj chronione zdarzenie i dostęp przez interfejs, aby odsłonić niektóre rzeczy prywatne. To skutecznie „zagina” zasady enkapsulacji, ale unika potrzeby faktycznego wysyłania kodu, który wykonuje twoje testy. Wadą jest to, że może to spowodować dodatkowy dodatkowy kod wewnętrzny, aby mieć pewność, że zdarzenie zostanie uruchomione w razie potrzeby.
  4. Jeśli uważasz, że metoda publiczna nie jest wystarczająco „bezpieczna”, sprawdź, czy istnieją sposoby na zaimplementowanie pewnego rodzaju procesu sprawdzania poprawności w swoich metodach, aby ograniczyć ich użycie. Są szanse, że podczas zastanawiania się nad tym albo wymyślisz lepszy sposób na wdrożenie swoich metod, albo zobaczysz, że inna klasa zaczyna nabierać kształtu.
  5. Jeśli masz wiele prywatnych metod wykonujących „rzeczy” dla swoich metod publicznych, być może nowa klasa czeka na wyodrębnienie. Możesz to przetestować bezpośrednio jako oddzielną klasę, ale zaimplementować jako złożony prywatnie w klasie, która go używa.

Pomyśl bocznie. Dbaj o to, by twoje zajęcia były małe, a metody mniejsze, i używaj dużej ilości kompozycji. To brzmi jak więcej pracy, ale w końcu skończysz z bardziej indywidualnie testowanymi przedmiotami, twoje testy będą prostsze, będziesz mieć więcej opcji korzystania z prostych prób w miejsce prawdziwych, dużych i złożonych obiektów, miejmy nadzieję, że dobrze- podzielony na fragmenty i luźno powiązany kod, a co ważniejsze, dajesz sobie więcej opcji. Utrzymywanie drobnych rzeczy zazwyczaj oszczędza Twój czas, ponieważ zmniejszasz liczbę rzeczy, które musisz indywidualnie sprawdzać w każdej klasie, i naturalnie redukujesz spaghetti z kodem, które czasami mogą się zdarzyć, gdy klasa staje się duża i ma dużo współzależne zachowanie kodu wewnętrznie.

S.Robins
źródło
4

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.

Jak ten obiekt reaguje na te zdarzenia? Przypuszczalnie musi wywoływać metody na innych obiektach. Możesz to przetestować, sprawdzając, czy te metody zostaną wywołane. Wywołaj obiekt próbny, a następnie możesz łatwo stwierdzić, że robi to, czego oczekujesz.

Problem polega na tym, że chcemy jedynie przetestować interakcję obiektu z innymi obiektami. Nie obchodzi nas, co dzieje się wewnątrz obiektu. Więc nie, nie powinieneś mieć więcej publicznych metod niż wcześniej.

Winston Ewert
źródło
4

Walczyłem również z tym samym problemem. Naprawdę, sposób na obejście tego jest następujący: w jaki sposób oczekujesz, że reszta twojego programu będzie się komunikować z tą klasą? Sprawdź swoją klasę odpowiednio. Zmusi cię to do zaprojektowania klasy w oparciu o sposób, w jaki reszta programu się z nią łączy, i w rzeczywistości zachęci do enkapsulacji i dobrego zaprojektowania twojej klasy.

Szansa
źródło
3

Zamiast prywatnego użytku domyślny modyfikator. Następnie możesz przetestować te metody indywidualnie, a nie tylko w połączeniu z metodami publicznymi. Wymaga to, aby twoje testy miały taką samą strukturę pakietu jak główny kod.

siamii
źródło
... zakładając, że jest to Java.
Dawood ibn Kareem
lub internalw .net.
CodesInChaos,
2

Kilka prywatnych metod zwykle nie stanowi problemu. Po prostu testujesz je za pomocą publicznego interfejsu API, tak jakby kod był wprowadzony do twoich publicznych metod. Nadmiar prywatnych metod może być oznaką słabej spójności. Twoja klasa powinna ponosić jedną spójną odpowiedzialność i często ludzie wybierają metody prywatne, aby wyglądać na spójne tam, gdzie tak naprawdę ich nie ma.

Na przykład może istnieć moduł obsługi zdarzeń, który wykonuje wiele wywołań bazy danych w odpowiedzi na te zdarzenia. Ponieważ oczywistą złą praktyką jest tworzenie instancji modułu obsługi zdarzeń w celu wykonywania wywołań bazy danych, istnieje pokusa, aby wszystkie wywołania związane z bazą danych były metodami prywatnymi, kiedy naprawdę należy je rozdzielić do osobnej klasy.

Karl Bielefeldt
źródło
2

Czy to oznacza, że ​​TDD stoi w sprzeczności z enkapsulacją? Jaka jest odpowiednia równowaga? Skłaniam się teraz do upublicznienia większości lub wszystkich moich metod.

TDD nie stoi w sprzeczności z enkapsulacją. Weź najprostszy przykład metody lub właściwości gettera, w zależności od wybranego języka. Powiedzmy, że mam obiekt klienta i chcę, aby zawierał pole identyfikatora. Pierwszy test, który zamierzam napisać, to taki, który mówi coś w stylu „customer_id_initializes_to_zero”. Definiuję moduł pobierający do zgłaszania niezaimplementowanego wyjątku i obserwowania, jak test się nie powiódł. Następnie najprostszą rzeczą, jaką mogę zrobić, aby przejść test, jest to, aby getter zwrócił zero.

Stamtąd przechodzę do innych testów, prawdopodobnie tych, w których identyfikator klienta jest rzeczywistą, funkcjonalną dziedziną. W pewnym momencie prawdopodobnie muszę utworzyć prywatne pole, z którego korzysta klasa klienta, aby śledzić, co powinien zwrócić moduł pobierający. Jak dokładnie to śledzić? Czy to proste int? Czy mogę śledzić ciąg, a następnie przekonwertować go na int? Czy śledzę 20 ints i je uśredniam? Świat zewnętrzny to nie obchodzi - a twoje testy TDD nie obchodzą. To jest zamknięty szczegół.

Myślę, że nie zawsze jest to od razu oczywiste przy uruchamianiu TDD - nie testujesz, jakie metody działają wewnętrznie - testujesz mniej szczegółowe obawy klasy. Więc nie chcesz testować tej metody, która DoSomethingToFoo()tworzy instancję Bar, wywołuje na niej metodę, dodaje dwie do jednej z jej właściwości itp. Testujesz, że po zmutowaniu stanu obiektu zmienił się niektóre akcesorium stanu (albo nie). Oto ogólny wzór twoich testów: „kiedy wykonam X na testowanej klasie, mogę później obserwować Y”. Sposób, w jaki dostaje się do Y, nie jest przedmiotem zainteresowania testów, i to właśnie jest zamknięte i dlatego TDD nie stoi w sprzeczności z kapsułkowaniem.

Erik Dietrich
źródło
2

Unikaj używania? Nie.
Unikaj rozpoczynania od ? Tak.

Zauważyłem, że nie pytałeś o to, czy możesz mieć abstrakcyjne klasy z TDD; jeśli zrozumiesz, jak powstają klasy abstrakcyjne podczas TDD, ta sama zasada dotyczy również metod prywatnych.

Nie możesz bezpośrednio testować metod w klasach abstrakcyjnych, tak jak nie możesz bezpośrednio testować metod prywatnych, ale dlatego nie zaczynasz od klas abstrakcyjnych i metod prywatnych; zaczynasz od konkretnych klas i publicznych interfejsów API, a następnie refaktoryzujesz wspólną funkcjonalność.


źródło