Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc

Biblioteka dostępu do TFS i testy jednostkowe

W poście Tfs Spotlight – buduję własny CAB wprowadzającym do mojego projektu TfsSpotlight wspomniałem, że jednym z moich celów jest pisanie testów jednostkowych. Chcę w ten sposób zobaczyć jakie problemy pojawią się podczas pisania testów jednostkowych dla większego i bardziej skomplikowanego projektu niż te, które do tej pory robiłem.

Proces pisania testów jednostkowych nie jest łatwy i co jakiś czas napotykam pewne problemy. Ostatni problem pojawił mi się w momencie, gdy chciałem napisać test dla klasy prezentera, który obsługuje widok konkretnego workitema. Źródłem danych dla tego widoku jest obiekt klasy pochodzącej z biblioteki dostępu do TFS – klasa WorkItem. Jak się szybko okazało napisanie testu jest niemożliwe, jeżeli bierzemy przypadek całkowitego odizolowania. Wszystko to dlatego, że nie mogę ręcznie utworzyć instancji tej klasy. Do tego potrzebne jest połączenie z serwerem (sic!). Moje zamiary spełzły na niczym. W dodatku klasa ta jest sealed, więc Rhino Mocks robie nie radzą. Nie mam zielonego pojęcia jak sobie z tym poradzić.

Wracając do biblioteki TFS pozwalającej na dostęp do serwera to należy zauważyć, że programiści i projektanci tego API zabezpieczyli się przed nieumiejętnym jego wykorzystaniem, aby zapobiec nadmiernemu obciążeniu serwera. Elementy takie jak Project, Query, WorkItem czy ich kolekcje są zaimplementowane w postaci klas, które swoje dane ładują w sposób leniwy. Tym sposobem wyświetlając w tabeli workitemy, pobierane są tylko właściwości wyświetlane w kolumnach. Pozostałe nie zostaną ściągnięte. Takie zachowanie na pewno ogranicza ilość danych przesyłanych z serwera, ale niestety sposób wykonania tych elementów może pozostawiać wiele do życzenia. Wszystkie te klasy o których mowa są sealed, a serwisy nie zostały opisane żadnymi interfejsami definiującymi kontrakty. Wygląda na to, że w tym przypadku nie pomyślano o Zasadzie oddzielenia zagadnień (ang. Separation of Concerns). Podobnie jest z kontrolkami dostarczanymi w bibliotece TFS. Okazuje się, że podpinając im źródło danych one i tak pytają o coś serwer (sic!)

Budując system luźno powiązany praca z takimi komponentami jest bardzo uciążliwa, a w tym przypadku skutecznie uniemożliwia mi pisanie testów. Chociaż trzeba zaznaczyć, że jest światełko w tunelu. Od jakiegoś czasu co raz częściej słyszy się o co raz to nowszych projektach ze stajni MS, które wspominają o testach jednostkowych. Ba, wczoraj Scott Guthrie ogłosił, że Silverlight 2 jest testowany przy pomocy testów jednostkowych (jest ich ponad 2000) i co więcej dostarczają również narzędzi do testowania własnych projektów Silverlight-owych.  Bardzo mnie ten trend cieszy, gdyż może następna wersja biblioteki dostępu do TFS będzie ten trend uwzględniała.

Opublikowane 3 kwietnia 2008 12:42 przez nuwanda

Komentarze:

# re: Biblioteka dostępu do TFS i testy jednostkowe

3 kwietnia 2008 14:49 by Wojciech Gebczyk

Zawsze moeesz uzyc backdoora ;-)

FormatterServices.GetUninitializedObject

i hajda na smoka!

:P

# re: Biblioteka dostępu do TFS i testy jednostkowe

3 kwietnia 2008 15:05 by nuwanda

Test passed :) Dzięki!

# re: Biblioteka dostępu do TFS i testy jednostkowe

3 kwietnia 2008 15:59 by mgrzeg

Wojtek, to faktycznie niezly chwyt :)

# re: Biblioteka dostępu do TFS i testy jednostkowe

4 kwietnia 2008 15:31 by Wojciech Gebczyk

michal, niezly chwyt... ha!

a co z klasa Aaa ponizej?

W normalnym developmencie to raczej nie wybuchie to wyjatkiem null ref exception przy dostepnie do wlasciwosci Value.

Ale po tej "siekierze" FormatterServices.GetUninitializedObject to bum przy get i set.

PS: wiem ze przyklad bezsensu klasy, ale chodzi o to ze kod klasy moze zakladac ze "readonly", "sealed" zadzialaja i _value zawsze bedzie zainicjalizowane. A tu niespodzianka pasqdna... :/

Wystarczy reflectorem zoabczyc co tego uzywa (zaladowac napierw jak najwiecej dllek) a zobaczycie gdzie moze kod wyleciec z takimi zalozeniami.

public sealed class Aaa {

 private readonly string _value = "Aaa";

 public Aaa() {}

 public string Value {

   get {

     _value = value.Trim();

     return _value;

   }

   set {

     if (!_value.Equals(value)) {

       _value = value ?? "";

     }

   }

 }

}

Twój komentarz lub ocena zostały zarejestrowane. Z powodu cachowania i moderacji mogą jednak nie być wyświetlone na stronie od razu.
Komentarze anonimowe wyłączone