Moim zdaniem testy jednostkowe należy umieścić w oddzielnym zestawie od kodu produkcyjnego. Oto tylko kilka wad umieszczania testów jednostkowych w tym samym zestawie lub zespołach co kod produkcyjny:
- Testy jednostkowe są dostarczane z kodem produkcyjnym. Jedyną rzeczą dostarczaną z kodem produktu jest kod produkcji.
- Zestawy będą niepotrzebnie rozdęte przez testy jednostkowe.
- Testy jednostkowe mogą wpływać na procesy kompilacji, takie jak kompilacja automatyczna lub ciągła.
Naprawdę nie znam żadnych zalet. Posiadanie dodatkowego projektu (lub 10) nie jest oszustwem.
Edycja: Więcej informacji na temat budowy i wysyłki
Zalecałbym ponadto, aby każdy zautomatyzowany proces kompilacji umieszczał testy produkcyjne i jednostkowe w różnych lokalizacjach. W idealnym przypadku proces kompilacji testów jednostkowych działa tylko wtedy, gdy kompiluje się kod produkcyjny i kopiuje pliki produktu do katalogu testów jednostkowych. Zrobienie tego w ten sposób skutkuje rozdzieleniem faktycznych bitów do wysyłki itp. Ponadto uruchamianie automatycznych testów jednostkowych w tym momencie dla wszystkich testów w określonym katalogu jest dość trywialne.
Podsumowując, oto ogólny pomysł na codzienne tworzenie, testowanie i wysyłanie bitów i innych plików:
- Kompilacja produkcyjna jest uruchamiana, umieszczając pliki produkcyjne w określonym katalogu „produkcyjnym”.
- Twórz tylko projekty produkcyjne.
- Skopiuj skompilowane bity i inne pliki do katalogu „produkcyjnego”.
- Skopiuj bity i inne pliki do katalogu kandydata do wydania, nazywanego też świątecznym katalogiem wydania "Release20081225".
- Jeśli kompilacja produkcyjna powiedzie się, zostanie uruchomiona kompilacja testów jednostkowych.
- Skopiuj kod produkcyjny do katalogu "testy".
- Twórz testy jednostkowe w katalogu „testy”.
- Uruchom testy jednostkowe.
- Wysyłaj powiadomienia o kompilacji i wyniki testów jednostkowych do programistów.
- Gdy kandydat do wydania (taki jak Release20081225) zostanie zaakceptowany, wyślij te bity.
#if
. Ten niestandardowy symbol można przełączać za pomocą parametrów wiersza polecenia kompilatora w skryptach oprogramowania CI. Zobacz msdn.microsoft.com/en-us/library/4y6tbswk.aspx .Osobny projekt, ale w tym samym rozwiązaniu. (Pracowałem nad produktami z oddzielnymi rozwiązaniami dla kodu testowego i produkcyjnego - to okropne. Zawsze przełączasz się między nimi).
Powody oddzielnych projektów są takie, jak podają inni. Zwróć uwagę, że jeśli używasz testów opartych na danych, możesz skończyć z dość znaczną ilością wzdęć, jeśli umieścisz testy w zestawie produkcyjnym.
Jeśli potrzebujesz dostępu do wewnętrznych elementów członkowskich kodu produkcyjnego, użyj InternalsVisibleTo .
źródło
[assembly:InternalsVisibleTo("UnitTestProjectName")]
doAssemblyInfo.cs
pliku projektu .Nie rozumiem częstego sprzeciwu wobec wdrażania testów z kodem produkcyjnym. Prowadziłem zespół przy małym mikrokapie (urósł z 14 do 130 osób). Mieliśmy około pół tuzina aplikacji Java i uznaliśmy, że BARDZO wartościowe jest wdrażanie testów w terenie w celu wykonania ich na określonymmaszyna, która wykazywała niezwykłe zachowanie. Przypadkowe problemy pojawiają się w terenie i możliwość rzucenia kilku tysięcy testów jednostkowych w tajemnicę przy zerowych kosztach była nieoceniona i często diagnozowana problemy w ciągu kilku minut ... w tym problemy z instalacją, niestabilne problemy z pamięcią RAM, problemy specyficzne dla maszyny, problemy z niestabilną siecią, itd., itd. Myślę, że przeprowadzenie testów w terenie jest niezwykle wartościowe. Ponadto losowe problemy pojawiają się w przypadkowych momentach i dobrze jest mieć testy jednostkowe, które już tam czekają na wykonanie w jednej chwili. Miejsce na dysku twardym jest tanie. Tak jak staramy się zachować razem dane i funkcje (projekt OO), myślę, że jest coś fundamentalnie cennego w utrzymywaniu kodu i testów razem (funkcja + testy, które sprawdzają poprawność funkcji).
Chciałbym umieścić moje testy w tym samym projekcie w C # / .NET / Visual Studio 2008, ale nadal nie zbadałem tego wystarczająco, aby to osiągnąć.
Dużą zaletą trzymania Foo.cs w tym samym projekcie co FooTest.cs jest to, że programiści są stale przypominani o tym, że w klasie brakuje testu rodzeństwa! To zachęca do lepszych praktyk kodowania opartych na testach ... dziury są bardziej widoczne.
źródło
Umieść testy jednostkowe w tym samym projekcie, co kod, aby uzyskać lepszą hermetyzację.
Możesz łatwo przetestować metody wewnętrzne, co oznacza, że nie upublicznisz metod, które powinny być wewnętrzne.
Również bardzo fajnie jest mieć testy jednostkowe blisko kodu, który piszesz. Podczas pisania metody można łatwo znaleźć odpowiednie testy jednostkowe, ponieważ znajdują się one w tym samym projekcie. Podczas budowania zestawu zawierającego testy unitTest wszelkie błędy w module unitTest spowodują wystąpienie błędu kompilatora, dlatego należy aktualizować najbardziej aktualny plik, aby tylko zbudować. Posiadanie unittest w osobnym projekcie może spowodować, że niektórzy programiści zapomną o zbudowaniu projektu unittest i przez jakiś czas przegapią zepsute testy.
Możesz też usunąć testy jednostkowe z kodu produkcyjnego, używając tagów kompilacji (IF #Debug).
Automatyczne testy integracji (wykonane w NUnit) powinny znajdować się w osobnym projekcie, ponieważ nie należą do żadnego pojedynczego projektu.
źródło
Release
kompilacji i kilka "heisenbugów" może się z nimi zmierzyć.InternalsVisibleTo
pozwala na testowanie wewnętrznych metod z oddzielnego projektu testowegoDebug
,Approval
iRelease
; i skompiluj zatwierdzenie ze wszystkimi optymalizacjami wersji. Ponadto, zazwyczaj testy jednostkowe nie są świetne w wykrywaniu błędów heisenbugów (z mojego doświadczenia). Zwykle potrzebujesz do tego specjalnych testów regresji integracji - i możesz je umieścić obok siebie.Po spędzeniu trochę czasu w projektach TypeScript, gdzie testy są często umieszczane w pliku wraz z testowanym kodem, wolałem to podejście niż oddzielanie ich:
Więc kiedy niedawno zacząłem nowy projekt .NET Core, chciałem sprawdzić, czy możliwe jest naśladowanie tej struktury w projekcie C # bez wysyłania testów lub zestawów testowych z ostateczną wersją.
Jak dotąd wydaje się, że umieszczanie następujących wierszy w pliku projektu działa dobrze:
Powyższe zapewnia, że w
Release
konfiguracji wszystkie wymienione pliki*.Tests.cs
zostaną wykluczone z kompilacji, a także, że wymagane odniesienia do pakietów testów jednostkowych zostaną usunięte.Jeśli nadal chcesz mieć możliwość testowania jednostkowego klas w ich konfiguracji wydania, możesz po prostu utworzyć nową konfigurację pochodną o
Release
nazwie coś w rodzajuReleaseContainingTests
.Aktualizacja: Po pewnym czasie używania tej techniki okazało się, że pomocne jest dostosowanie ikon w VS Code, aby testy (i inne rzeczy) wyróżniały się nieco bardziej w panelu eksploratora:
Aby to zrobić, użyj rozszerzenia Material Icon Theme i dodaj coś podobnego do następującego do preferencji JSON VS Code:
źródło
Moje testy jednostkowe zawsze są realizowane w osobnym projekcie. W rzeczywistości do każdego projektu, który mam w swoim rozwiązaniu, towarzyszy osobny projekt testowy. Kod testowy nie jest kodem aplikacji i nie powinien być z nim przeplatany. Zaletą trzymania ich w osobnych projektach - przynajmniej przy użyciu TestDriven.Net - jest to, że mogę kliknąć prawym przyciskiem myszy projekt testowy i uruchomić wszystkie testy w tym projekcie, testując całą bibliotekę kodu aplikacji jednym kliknięciem.
źródło
Jeśli używany jest framework NUnit , istnieje dodatkowy powód, aby umieścić testy w tym samym projekcie. Rozważmy następujący przykład kodu produkcyjnego zmieszanego z testami jednostkowymi:
Testy jednostkowe służą tutaj jako dokumentacja i specyfikacja testowanego kodu. Nie wiem, jak osiągnąć taki efekt samodokumentowania, z testami umieszczonymi w osobnym projekcie. Użytkownik funkcji musiałby szukać testów, aby zobaczyć te przypadki testowe, co jest mało prawdopodobne.
Aktualizacja : Wiem, że takie użycie
TestCase
atrybutu nie było zamierzone przez twórców NUnit, ale dlaczego nie?źródło
Waham się między tym samym projektem a różnymi projektami.
Jeśli wydajesz bibliotekę, problem jest z publikacją kodu testowego wraz z kodem produkcyjnym, w przeciwnym razie zwykle tak nie jest (chociaż zanim spróbujesz, istnieje silna bariera psychologiczna).
Umieszczając testy w tym samym projekcie, łatwiej jest mi przełączać się między testami a testowanym przez nie kodem oraz łatwiej je refaktoryzować / przenosić.
źródło
Umieściłem je w osobnych projektach. Zgodnie z ogólną zasadą, nazwa zestawu odzwierciedla nazwę przestrzeni nazw. Jeśli więc istnieje projekt o nazwie Company.Product.Feature.sln, ma on dane wyjściowe (nazwę zespołu) Company.Product.Feature.dll. Projekt testowy to Company.Product.Feature.Tests.sln, dając plik Company.Product.Feature.Tests.dll.
Najlepiej jest trzymać je w jednym rozwiązaniu i kontrolować dane wyjściowe za pomocą Configuration Manager. Mamy nazwaną konfigurację dla każdej z głównych gałęzi (programowanie, integracja, produkcja) zamiast używania domyślnych debugowania i wydania. Po skonfigurowaniu konfiguracji możesz je dołączyć lub wykluczyć, klikając pole wyboru „Kompiluj” w menedżerze konfiguracji. (Aby uzyskać Configuration Manager, kliknij prawym przyciskiem myszy rozwiązanie i przejdź do Configuration Manager). Zwróć uwagę, że czasami znajduję CM w programie Visual Studio, w którym występują błędy. Kilka razy musiałem przejść do plików projektu i / lub rozwiązania, aby wyczyścić utworzone cele.
Ponadto, jeśli używasz kompilacji zespołowej (i jestem pewien, że inne narzędzia do kompilacji .NET są takie same), możesz powiązać kompilację z nazwaną konfiguracją. Oznacza to, że jeśli na przykład nie utworzysz testów jednostkowych dla kompilacji „produkcyjnej”, projekt kompilacji może również znać to ustawienie i nie tworzyć ich, ponieważ zostały oznaczone jako takie.
Poza tym, kiedyś XCopy wypadło z maszyny budującej. Skrypt po prostu pomija kopiowanie czegokolwiek o nazwie * .Tests.Dll przed wdrożeniem. To było proste, ale działało.
źródło
Powiedziałbym, że trzymaj je oddzielnie.
Oprócz innych wymienionych powodów, posiadanie kodu i testów razem wypacza numery pokrycia testów. Podczas raportowania pokrycia testów jednostkowych - raportowane pokrycie jest większe, ponieważ testy są objęte podczas uruchamiania testów jednostkowych. Podczas raportowania pokrycia testów integracyjnych raportowane pokrycie jest niższe, ponieważ testy integracji nie uruchomiłyby testów jednostkowych.
źródło
Naprawdę inspiruje mnie framework do testów jednostkowych biblioteki Flood NN autorstwa Roberta Lopeza. Używa innego projektu dla każdej pojedynczej klasy testowanej przez jednostkę i ma jedno rozwiązanie przechowujące wszystkie te projekty, a także główny projekt, który kompiluje i uruchamia wszystkie testy.
Zadbany jest też układ projektu. Pliki źródłowe znajdują się w folderze, ale folder projektu VS znajduje się poniżej. Pozwala to na tworzenie różnych podfolderów dla różnych kompilatorów. Wszystkie projekty VS są dostarczane z kodem, więc każdy może bardzo łatwo uruchomić dowolny lub wszystkie testy jednostkowe.
źródło
Wiem, że to bardzo stare pytanie, ale chciałbym dodać tam swoje doświadczenie. Niedawno zmieniłem nawyk testowania jednostkowego z oddzielnych projektów na ten sam.
Czemu?
Po pierwsze, staram się zachować taką samą strukturę folderów głównego projektu jak projekt testowy. Tak więc, jeśli mam plik poniżej
Providers > DataProvider > SqlDataProvider.cs
, tworzę tę samą strukturę w moich projektach testów jednostkowych, takich jakProviders > DataProvider > SqlDataProvider.Tests.cs
Ale kiedy projekt staje się coraz większy, gdy przenosisz pliki z jednego folderu do drugiego lub z jednego projektu do drugiego, synchronizacja ich z projektami testów jednostkowych staje się bardzo kłopotliwa.
Po drugie, nie zawsze jest łatwo przejść od klasy do testowania do klasy testów jednostkowych. Jest to jeszcze trudniejsze w przypadku JavaScript i Python.
Niedawno zacząłem ćwiczyć, że każdy utworzony przeze mnie plik (na przykład
SqlDataProvider.cs
) tworzę kolejny plik z przyrostkiem Test, np.SqlDataProvider.Tests.cs
Na początku wydaje się, że spowoduje to rozdęcie plików i odniesień do bibliotek, ale w dłuższej perspektywie na pierwszy rzut oka wyeliminujesz syndrom przenoszenia plików, a także upewnisz się, że każdy pojedynczy plik, który jest kandydatem do testowania, będzie miał plik pary z
.Tests
przyrostkiem. Umożliwia łatwe przeskakiwanie do pliku testowego (ponieważ znajduje się on obok siebie) zamiast przeglądania oddzielnego projektu.Możesz nawet napisać reguły biznesowe, aby przeskanować projekt i zidentyfikować klasę, która nie ma pliku .Tests, i zgłosić je właścicielowi. Możesz również łatwo wskazać programowi uruchamiającemu testy, aby kierował na
.Tests
klasy.Szczególnie w przypadku Js i Python nie będziesz musiał importować referencji z innej ścieżki, możesz po prostu użyć tej samej ścieżki do testowanego pliku docelowego.
Używam tej praktyki od jakiegoś czasu i myślę, że jest to bardzo rozsądny kompromis między rozmiarem projektu a łatwością jego utrzymania i krzywą uczenia się dla nowych uczestników projektu.
źródło
Jak odpowiedzieli inni - umieść testy w osobnych projektach
Jedną rzeczą, o której nie wspomniano, jest fakt, że w rzeczywistości nie można uruchomić
nunit3-console.exe
niczego poza.dll
plikami.Jeśli planujesz przeprowadzić testy za pośrednictwem TeamCity, będzie to stanowić problem.
Załóżmy, że masz projekt aplikacji konsolowej. Podczas kompilacji zwraca plik wykonywalny
.exe
dobin
folderu.Z poziomu
nunit3-console.exe
nie byłbyś w stanie uruchomić żadnych testów zdefiniowanych w tej aplikacji konsolowej.Innymi słowy, aplikacja konsolowa zwraca
exe
plik, a biblioteka klas zwracadll
pliki.Właśnie się dzisiaj ugryzłem i to jest do bani :(
źródło
Niedawno wdrażałem w dockerze. Nie widzę wartości w posiadaniu oddzielnego projektu, gdy plik Dockerfile może łatwo skopiować katalog / src i opuścić katalog / test. Ale jestem nowy w dotnet i być może czegoś brakuje.
źródło
Osobne projekty, chociaż zastanawiam się ze sobą, czy powinny mieć ten sam svn. W tej chwili udostępniam im oddzielne repozytoria svn, jedno o nazwie
„MyProject” - dla samego projektu
i jeden dzwonił
„MyProjectTests” - do testów związanych z MyProject.
Jest to dość przejrzyste i ma tę zaletę, że zatwierdzanie projektu i zatwierdzanie testów jest całkiem oddzielne. Oznacza to również, że w razie potrzeby możesz przekazać svn projektu, bez konieczności publikowania testów. Oznacza to również, że możesz mieć katalogi branch / trunk / tag dla swoich testów i projektu.
Ale jestem coraz bardziej skłonny do posiadania czegoś podobnego do następującego, w jednym repozytorium svn, dla każdego projektu.
Chciałbym wiedzieć, co inni myślą o tym rozwiązaniu.
źródło