16

[Oczywiście, pytanie nie jest ograniczony do konkretnego „przyjaciel” realizacji, prosimy jednak podkreślić specyfikę wdrożenia stosownych przypadkach]Korzystanie z "przyjaciel" - deklaracje do testowania jednostkowego. Kiepski pomysł?

Czytając pytań bez odpowiedzi, natknąłem się atrybutem InternalsVisibleTo:

Określa typów, które są zwykle widoczny tylko w bieżącym montażem są widoczne innego zespołu.

C# Programming Guide na MSDN posiada sekcję Friend Assemblies opisujący jak wykorzystać atrybut, aby umożliwić korzystanie z internal metod i typów do innego zespołu.

Zastanawiam się, czy byłoby dobrym pomysłem, aby użyć tego do stworzenia "ukrytego" interfejsu do oprzyrządowania biblioteki do użycia przez zespół testujący jednostkę. Wydaje się, że zwiększa on łączność masowo w obu kierunkach (kod testowy w zespole produkcyjnym, wewnętrzna wewnętrzna wiedza na temat zespołu produkcyjnego w kodzie testowym), ale z drugiej strony może pomóc w tworzeniu drobnoziarnistych testów bez zaśmiecania interfejsu publicznego.

Jakie są Twoje doświadczenia z używaniem deklaracji przyjaciół podczas testowania? Czy to był twój Srebrny Bullet, czy też rozpoczął Marsz Śmierci?

Odpowiedz

13

Użyłem tej techniki w szerokim zakresie - oznacza to, że moje testy jednostkowe mogą testować aspekty biblioteki kodów, które nie są widoczne dla zwykłych konsumentów.

Podczas używania [InternalsVisibleTo] nie zwiększa sprzężenia, uważam, że (niewielki) wzrost jest warta zysków.

Moje testy jednostkowe są już ściśle powiązane z testowanym kodem - chociaż staram się pisać testy, które zapewniają konkretne wyniki, a nie konkretne implementacje, poprzez dostęp do rzeczy niewidocznych dla zwykłych konsumentów, w pewnym stopniu ograniczam implementację.

Idąc w drugą stronę, sprzęgło jest minimalne - posiadaniem atrybut [InternalsVisibleTo] na zespole kodu, a oznakowanie pewne rzeczy jako wewnętrzny zamiast prywatny (lub chroniony wewnętrzną zamiast chroniony) .

(Zauważ, że jestem ignorując tutaj żadnych zmian projektowych, które są wywoływane przez stosowanie testów jednostkowych, która jest zupełnie inna dyskusja.)

Atrybut [InternalsVisibleTo] wymaga silny nazywania swoich zespołów. Jeśli nie robisz tego już, możesz uznać to za nieco uciążliwe, ponieważ silnie nazwany zespół może zależeć tylko od innych mocno nazwanych złożeń, co może skończyć się potrzebą zmiany kilku złożeń.

Uzyskanie odpowiedniego atrybutu może być nieco kłopotliwe, ponieważ musi zawierać klucz publiczny zespołu testowego. IDesign ma przydatne Friend Assembly tool, który tworzy atrybut w schowku, gotowy do wklejenia. Zalecana.

+0

Dzięki za podpowiedź na temat silnego nazewnictwa! Nie byłem (jeszcze) tego świadomy, ale ponieważ uważam, że wszystkie moje zgromadzenia muszą być mocno nazwane wydaniem, nie uważam tego za prawdziwy problem. –

12

Jest to jedyne zastosowanie, jakie kiedykolwiek osobiście zgłosiłem w sprawie InternalsVisibleTo - i rzeczywiście było bardzo, bardzo przydatne.

Nie postrzegam testów jednostkowych jako testów czarnej skrzynki - w pewnym stopniu są one już połączone z wdrożeniem. Możliwość testowania wewnętrznych typów i metod pozwala na znacznie bardziej precyzyjne ustawianie ostrości (mniejsze jednostki).

3

Myślę, że używanie testu InternalsVisibleToAttribute jest całkowicie uzasadnione. Moja "jednostka" w "testowaniu jednostkowym" jest klasą i obejmuje klasy internal, więc chcę je przetestować. I don't want to unit test private methods, chociaż.

Nie sądzę, że stworzenie specjalnego, prywatnego interfejsu tylko do testów jest dobrym pomysłem. Jedną z wartości testów jednostkowych jest to, że daje ona szansę na przemyślenie interfejsu dla twojej klasy z punktu widzenia konsumenta tej klasy; zapewnianie tylnych drzwi zabiera to korzyści.

Moim wyborem jest jednak umieszczenie testów jednostkowych w tym samym zespole, co kod produkcyjny. Zwykle nie wpływa to na mojego klienta, ale upraszcza mi to wszystko, więc robię to. Gdy to zrobię, pytanie InternalsVisibleTo zniknie.

3

Tak naprawdę, testowanie urządzenia to tylko użycie , z którego skorzystałem, aby korzystać z InternalsVisibleToAttribute. Dzięki temu możesz zaimplementować dużą część swoich "prywatnych" metod jako wewnętrzne, aby wystawić je na strukturę testowania jednostkowego w celu bardziej inwazyjnego testowania niezmienników wewnętrznych klasy.

Odniosłem wielki sukces dzięki tej technice. Jeśli nic innego nie pomoże ci zbliżyć się do tego mitycznego celu 100% pokrycia kodu, umożliwiając wywołanie prywatnych metod w sytuacjach, które w przeciwnym razie są niedostępne.

2

Myślę, że kolejny uzasadniony przypadek użycia pojawia się, gdy korzystasz z oddzielnych złożeń podczas łączenia starszego kodu C++ z nowszym kodem C#.

Pobraliśmy zestawy C++, przekonwertowaliśmy je do C++/CLI, a następnie zaimplementowaliśmy nowszy kod w języku C#. Gdy to zrobimy, nadal będziemy używać "wewnętrznych" dla klas/metod w języku C#, które nie są naprawdę publiczne, a następnie udostępnić je starszemu kodowi jako zespoły przyjaciół.