Programując pod Sharepointa czy inne tego typu badziewie musimy podpisywać nasze assemblies i wrzucać je do GACa. Już dwa razy mnie to "ugryzło" i straciłem w sumie dobre kilka godzin na diagnostykę poniższego scenariusza:
1) piszę testy do funkcjonalności zawartej w podpisanej dllce
2) koduję implementację w tejże dllce
3) uruchamiam testy
4) dostaję wyjątek TypeLoadException czy coś innego w ten deseń mówiącego, że w testowanej dllce nie ma kodu który… przecież tam jest bo dopiero co go napisałem!
W obu scenariuszach w znalezieniu błędu asystował mi opisywany niedawno fuslogvw. Oczywiście przyczyna była, jak można się domyślić, banalna: podczas uruchamiania testów pobierana była dllka z GACa, a nie ta którą dopiero co pięknie i starannie skompilowałem. I której do GACa nie wrzuciłem.
Rozwiązania tego problemu są trzy:
1) dodać rejestrację dllki w GACu (narzędziem Gacutil) do post-build steps… ale to niepotrzebnie zmienia plik .csproj, czego chcę uniknąć
2) ręcznie rejestrować dllkę po każdym buildzie, albo przynajmniej przed każdym uruchomieniem testów… ale to (chociaż można to sprowadzić do prostego 3krotnego stuknięcia w klawiaturę) wydaje mi się głupie, bo "nic co manualne nie jest mi miłe" (oprócz skrzyni biegów).
3) DEVPATH, którym zajmę się dalej
Co to jest to DEVPATH? Może wszyscy naokoło znają ten myk a tylko ja, schowany w głębokiej dev-jaskini, jakoś to przegapiłem, ale tak czy siak jest to dla mnie nowość. Otóż DEVPATH to zmienna środowiskowa, pod którą możemy wstawić lokalizację mającą zrobić "override" na ładowaniu bibliotek z GAC. Wystarczy ustawić ją na odpowiednią ścieżkę, do configa dopisać jeden mały wpis i już! Nasze lokalne dllki są brane do testów, bez konieczności ich każdorazowej rejestracji. O samym DEVPATH i rekomendowanym sposobie użycia możecie poczytać na MSDN. Ale ja, konkretnie do moich potrzeb – czyli do scenariusza TDD z testami odpalanymi Resharperem, zrobiłem to trochę inaczej:
Po pierwsze, zamiast w machine.config ustawiłem <developmentMode /> w sekcji <runtime /> w pliku JetBrains.ReSharper.TaskRunner.CLR4.MSIL.exe.config (który dokładnie plik trzeba zmodyfikować – to pewnie zależy od maszyny, więc próbowałem modyfikować wszystkie "*taskrunner*config" aż znalazłem ten odpowiedni… dodawać chyba nie muszę że warto sobie zrobić jego kopię zapasową? ;) ):
<!– Added by MA to allow using DEVPATH –>
<developmentMode developerInstallation="true"/>
Można to samo zrobić na poziomie machine.config (jak radzi MSDN), ale prawdopodobnie mogłoby to spowodować Sodomę&Gomorę dla innych aplikacji.
Po drugie, ręcznie ustawiłem zmienną środowiskową DEVPATH na output path mojego projektu z testami. Po czym zrestartowałem Visuala. Kombinowałem najpierw z ustawianiem zmiennej w post-build events mojego projektu z testami (ten csproj jestem skłonny edytować) zarówno z SET jak i SETX, ale bez pozytywnego rezultatu. Wytłumaczyłem to sobie tak: tests runner R# jest uruchamiany z poziomu VS, więc przekazywane są do niego zmienne środowiskowe obecne w systemie w momencie startu tegoż. A zmiennych środowiskowych "odświeżyć" się nie da. Co prawda nie do końca łapię dlaczego w takim razie nie działa "set", ale… nie działa. Jakby ktoś znał rozwiązanie tego problemu (albo lepsze wytłumaczenie) to bardzo poproszę o wyjaśnienie w komentarzu.
W DEVPATH znajdzie się testowana dllka… o ile…
O ile w końcu po trzecie, skonfigurowałem referencję na testowany projekt ustawiając "Copy local" na "true". Po czym upewniłem się, że na pewno kopia dllki ląduje gdzie powinna lądować (z niewiadomych względów zadziałało mi to dopiero jak ustawiłem to dwukrotnie).
I już. Piszę, testuję bez martwienia się o GAC. Do GACa wrzucam tylko przy wdrażaniu rozwiązania.
To co wyżej przedstawiłem działa u mnie: gdy mam jeden projekt z testami, gdy używam Resharpera. Dla innych runnerów trzeba zmodyfikować ich własne konfigi (albo właśnie machine.config, chociaż tego bym się raczej obawiał). A przy wielu projektach z testami… pewnie bym skonfigurował output path taki sam dla każdego z nich. Albo bym dokleił kolejne ścieżki do tej zmiennej.
Trochę to skomplikowane. Ale myślałem że się w ogóle takiego czegoś osiągnąć nie da. A się da. Jea.
Ave!
Dlaczego uważasz Sharepointa za badziewie ?
Hail,
Pisałem wiele różnych aplikacji – z pisaniem rozwiązań pod Sharepointa mam najgorsze wspomnienia.
Korzystałem z jeszcze większej liczy aplikacji niż pisałem – z korzystania z Sharepointa mam prawie najgorsze wspomnienia.
sharepoint jako stand alone produkt ktory wymaga jedynie kilku klikow administracyjnych to spoko rzecz. do swoich celow idealny.
sharepoint jako platforma dev? to juz zupelnie inna kwestia. i tu zgadzam sie w 100% z procentem (jezezli chodzi o pisanie, jezeli chodzi o korzystanie to niech zaczna wspierac inne przegladarki a pogadamy)
SET/SETX w post-build step nie zadziała, gdyż post build step jest urchamiany przez cmd odpalane przez VS. Wyniki z tego, że SET/SETX zmieni wartość zmiennej srodowiskowej tego tymczasowego cmd.
Novakov,
SETX właśnie tym różni się od SET że zmienia wartości globalne