Osiągnęliśmy punkt w naszym projekcie, w którym mamy prawie tysiąc testów, a ludzie przestali męczyć się z ich uruchomieniem przed sprawdzeniem, ponieważ trwa to tak długo. W najlepszym wypadku przeprowadzają testy, które są związane z fragmentem kodu, który zmienili, aw najgorszym sprawdzają to bez testowania.
Uważam, że ten problem wynika z faktu, że rozwiązanie rozwinęło się do 120 projektów (zwykle wykonujemy znacznie mniejsze projekty i to dopiero drugi raz, gdy robimy TDD poprawnie), a czas kompilacji + testu wydłużył się do około 2-3 minut na mniejszych maszynach.
Jak obniżyć czas wykonywania testów? Czy są jakieś techniki? Udajesz więcej? Udajesz mniej? Może większe testy integracyjne nie powinny uruchamiać się automatycznie podczas uruchamiania wszystkich testów?
Edycja: w odpowiedzi na kilka odpowiedzi używamy już CI i serwera kompilacji, dlatego wiem, że testy się nie powiodły. Problem (właściwie symptom) polega na tym, że ciągle otrzymujemy wiadomości o nieudanych kompilacjach. Przeprowadzanie częściowych testów jest czymś, co robi większość ludzi, ale nie wszyscy. a jeśli chodzi o testy, są one naprawdę dobrze wykonane, używają podróbek do wszystkiego i nie ma w ogóle IO.
źródło
Odpowiedzi:
Możliwym rozwiązaniem byłoby przeniesienie części testowej z maszyn programistycznych do konfiguracji ciągłej integracji ( na przykład Jenkins ) za pomocą oprogramowania do kontroli wersji o dowolnym smaku ( git , svn itp.).
Kiedy trzeba napisać nowy kod, dany programista utworzy gałąź dla wszystkiego, co robią w repozytorium. Wszystkie prace zostaną wykonane w tej gałęzi i mogą zatwierdzić swoje zmiany w gałęzi w dowolnym momencie, nie psując głównego wiersza kodu.
Po zakończeniu danej funkcji, naprawy błędu lub czegokolwiek, nad czym pracują, gałąź może zostać z powrotem połączona z magistralą (lub jak wolisz to zrobić), w której przeprowadzane są wszystkie testy jednostkowe. Jeśli test się nie powiedzie, scalenie zostanie odrzucone, a programista zostanie powiadomiony, aby mógł naprawić błędy.
Możesz także zlecić serwerowi CI przeprowadzanie testów jednostkowych dla każdej gałęzi funkcji, gdy dokonywane są zatwierdzenia. W ten sposób programista może wprowadzić pewne zmiany, zatwierdzić kod i pozwolić serwerowi na uruchomienie testów w tle, podczas gdy nadal będą pracować nad dodatkowymi zmianami lub innymi projektami.
Świetny przewodnik po jednym ze sposobów przeprowadzenia takiej konfiguracji można znaleźć tutaj (specyficzny dla git, ale powinien działać w przypadku innych systemów kontroli wersji): http://nvie.com/posts/a-successful-git-branching-model/
źródło
Większość testów jednostkowych powinna trwać mniej więcej 10 milisekund. Mając „prawie tysiąc testów” jest nic i powinien być może kilka sekund, aby uruchomić.
Jeśli nie są, powinieneś przestać pisać wysoce sprzężone testy integracyjne (chyba, że tego właśnie potrzebuje kod) i zacząć pisać dobre testy jednostkowe (zaczynając od dobrze oddzielonego kodu i właściwego użycia podróbek / makiet / skrótów itp.). To sprzężenie wpłynie na jakość testu i czas potrzebny na ich napisanie - więc nie chodzi tylko o skrócenie czasu wykonywania testu.
źródło
py.test
) robi mnóstwo magii w tle, a wszystko to czysty kod Pythona („100x wolniej niż C ”), przeprowadzenie około 500 testów w moim projekcie zajmuje mniej niż 6 sekund na powolnym netbooku sprzed kilku lat. Liczba ta jest z grubsza liniowa pod względem liczby testów; podczas gdy istnieje pewne obciążenie początkowe, jest ono amortyzowane we wszystkich testach, a obciążenie ogólne na test wynosi O (1).Jest kilka metod, które wykorzystałem do rozwiązania podobnego problemu:
Ponadto możesz użyć następujących narzędzi, aby ułatwić sobie życie i przyspieszyć testy
pnunit
konfiguracja CI z kilkoma węzłami.źródło
0. Słuchaj swoich programistów.
Jeśli nie przeprowadzają testów, oznacza to, że postrzegają koszt (oczekiwanie na uruchomienie testów, radzenie sobie z fałszywymi awariami) na wartość wyższą niż wartość (natychmiastowe wykrywanie błędów). Zmniejsz koszty, zwiększ wartość, a ludzie będą przeprowadzać testy przez cały czas.
1. Sprawdź, czy testy są w 100% wiarygodne.
Jeśli kiedykolwiek zdarzy Ci się test, który zakończy się niepowodzeniem z fałszywymi negatywami, zrób to natychmiast. Napraw je, zmień, wyeliminuj, bez względu na wszystko, aby zagwarantować 100% niezawodności. (Można mieć zestaw niewiarygodnych, ale wciąż przydatnych testów, które można uruchomić osobno, ale główny zestaw testów musi być niezawodny).
2. Zmień swoje systemy, aby zagwarantować, że wszystkie testy przebiegną cały czas.
Użyj systemów ciągłej integracji, aby upewnić się, że tylko zatwierdzające przekazywanie zostaną włączone do głównej / oficjalnej / wydania / dowolnej gałęzi.
3. Zmień swoją kulturę na wartość 100% pozytywnych testów.
Naucz lekcji, że zadanie nie jest „wykonane”, dopóki nie przejdzie 100% testów i zostanie ono włączone do głównej / oficjalnej / wydania / dowolnej gałęzi.
4. Wykonaj testy szybko.
Pracowałem nad projektami, w których testy trwają sekundę, oraz nad projektami, w których trwają cały dzień. Istnieje silna korelacja między czasem potrzebnym do uruchomienia testów a moją produktywnością.
Im dłużej trwają testy, tym rzadziej będziesz je uruchamiać. Oznacza to, że dłużej będziesz otrzymywać informacje zwrotne o wprowadzanych zmianach. Oznacza to również, że będziesz przechodził dłużej między zatwierdzeniami. Częste zatwierdzanie oznacza mniejsze kroki, które łatwiej jest scalić; łatwiej jest śledzić historię zatwierdzeń; łatwiej znaleźć błąd w historii; cofanie jest również łatwiejsze.
Wyobraź sobie testy, które działają tak szybko, że nie przeszkadza ci automatyczne uruchamianie ich za każdym razem, gdy kompilujesz.
Szybkie przeprowadzanie testów może być trudne (o to poprosił OP, prawda!). Oddzielenie jest kluczem. Fałszywe / fałszywe są w porządku, ale myślę, że możesz to zrobić lepiej, dokonując refaktoryzacji w celu uczynienia fałszywych / fałszywych fałszywymi. Zobacz blog Arlo Belshee, zaczynając od http://arlobelshee.com/post/the-no-mocks-book .
5. Spraw, aby testy były przydatne.
Jeśli testy nie zawiodą, kiedy spieprzysz, to po co? Naucz się pisać testy, które wychwycą błędy, które prawdopodobnie stworzysz. Jest to umiejętność sama w sobie i będzie wymagała dużej uwagi.
źródło
Kilka minut jest OK na testy jednostkowe. Należy jednak pamiętać, że istnieją 3 główne typy testów:
Są one wymienione w kolejności prędkości. Testy jednostkowe powinny być szybkie. Nie złapią każdego błędu, ale ustalają, że program jest przyzwoicie zdrowy. Testy jednostkowe powinny zostać uruchomione za 3 minuty lub krócej lub przyzwoity sprzęt. Mówisz, że masz tylko 1000 testów jednostkowych i trwają 2-3 minuty? Cóż, to chyba OK.
Rzeczy do sprawdzenia:
Upewnij się jednak, że testy jednostkowe i testy integracyjne są osobne. Testy integracyjne będą zawsze wolniejsze.
Upewnij się, że testy jednostkowe przebiegają równolegle. Nie ma powodu, aby nie, jeśli są to prawdziwe testy jednostkowe
Upewnij się, że testy jednostkowe są „niezależne”. Nigdy nie powinni uzyskiwać dostępu do bazy danych lub systemu plików
Poza tym twoje testy nie brzmią teraz tak źle. Jednak dla porównania, jeden z moich przyjaciół w zespole Microsoft ma 4000 testów jednostkowych, które przebiegają w niecałe 2 minuty na przyzwoitym sprzęcie (i jest to skomplikowany projekt). Możliwe są szybkie testy jednostkowe. Eliminowanie zależności (i kpiąc tylko tyle, ile potrzeba) jest najważniejsze, aby uzyskać szybkość.
źródło
Przeszkol programistów w zakresie Personal Software Process (PSP), pomagając im zrozumieć i poprawić ich wydajność, stosując większą dyscyplinę. Pisanie kodu nie ma nic wspólnego z trzaskaniem palcami na klawiaturze, a następnie naciśnij przycisk kompilacji i odprawy.
W przeszłości PSP było bardzo popularne, gdy kompilacja kodu była procesem, który zajmował dużo czasu (godziny / dni na komputerze mainframe, więc wszyscy musieli udostępniać kompilator). Ale kiedy osobiste stacje robocze stały się potężniejsze, wszyscy zaczęliśmy akceptować ten proces:
Jeśli pomyślisz przed wpisaniem, a następnie po wpisaniu, przejrzyj to, co napisałeś, możesz zmniejszyć liczbę błędów przed uruchomieniem kompilacji i zestawu testów. Naucz się nie naciskać kompilacji 50 razy dziennie, ale może raz lub dwa, wtedy nie ma to większego znaczenia, że kompilacja i czas testowania zajmuje kilka minut dłużej.
źródło
Jeden możliwy sposób: podziel swoje rozwiązanie. Jeśli rozwiązanie ma 100 projektów, jest to niemożliwe do zarządzania. To, że dwa projekty (powiedzmy A i B) używają wspólnego kodu z innego projektu (powiedzmy Lib), nie oznacza, że muszą być w tym samym rozwiązaniu.
Zamiast tego możesz utworzyć rozwiązanie A z projektami A i Lib, a także rozwiązanie B z projektami B i Lib.
źródło
Jestem w podobnej sytuacji. Mam testy jednostkowe, które testują komunikację z serwerem. Testują zachowanie z limitami czasu, anulują połączenia itp. Cały zestaw testów trwa 7 minut.
7 minut to stosunkowo krótki czas, ale nie jest to coś, co zrobisz przed każdym zatwierdzeniem.
Posiadamy również zestaw automatycznych testów interfejsu użytkownika, których czas działania wynosi 2 godziny. To nie jest coś, co chcesz uruchamiać codziennie na swoim komputerze.
Co więc robić?
Ważne jest: wszystkie testy powinny być uruchamiane często, ponieważ ważne jest, aby znaleźć błędy. Jednak nie jest absolutnie konieczne, aby je znaleźć przed zatwierdzeniem.
źródło
Chociaż twój opis problemu nie daje dokładnego wglądu w bazę kodu, myślę, że mogę spokojnie powiedzieć, że twój problem jest dwojaki.
Naucz się pisać odpowiednie testy.
Mówisz, że masz prawie tysiąc testów i masz 120 projektów. Zakładając, że co najwyżej połowa tych projektów to projekty testowe, masz 1000 testów do 60 projektów kodu produkcyjnego. To daje około 16-17 testów pr. projekt!!!
To prawdopodobnie ilość testów, które musiałbym przeprowadzić w ramach systemu produkcyjnego w zakresie około 1-2 klas. Więc jeśli nie masz tylko 1-2 klas w każdym projekcie (w takim przypadku struktura projektu jest zbyt drobnoziarnista), twoje testy są zbyt duże, obejmują zbyt dużo gruntu. Mówisz, że to pierwszy projekt, w którym właściwie robisz TDD. Powiedzmy, że liczby, które podajesz, wskazują, że tak nie jest, nie robisz właściwości TDD.
Musisz nauczyć się pisać odpowiednie testy, co prawdopodobnie oznacza, że musisz nauczyć się, jak sprawić, by kod był testowalny. Jeśli nie możesz znaleźć doświadczenia w zespole, aby to zrobić, sugerowałbym zatrudnienie pomocy z zewnątrz, np. W postaci jednego lub dwóch konsultantów pomagających Twojemu zespołowi przez 2-3 miesiące w nauce pisania testowalnego kodu i małych minimalne testy jednostkowe.
Dla porównania, w projekcie .NET, nad którym obecnie pracuję, możemy przeprowadzić około 500 testów jednostkowych w czasie krótszym niż 10 sekund (i nie zostało to nawet zmierzone na maszynie o wysokiej specyfikacji). Gdyby to były twoje dane, nie bałbyś się ich uruchamiać lokalnie tak często.
Naucz się zarządzać strukturą projektu.
Podzieliłeś rozwiązanie na 120 projektów. To według moich standardów oszałamiająca ilość projektów.
Jeśli więc sensowne jest posiadanie takiej liczby projektów (co wydaje mi się, że tak nie jest - ale twoje pytanie nie zawiera wystarczających informacji, aby dokonać właściwej oceny tego), musisz podzielić projekty na mniejsze elementy, które można budować, wersjonować i wdrażać osobno. Tak więc, gdy programista uruchamia jednostkę zestawu testów, musi jedynie przeprowadzić testy dotyczące komponentu, nad którym aktualnie pracuje. Serwer kompilacji powinien zadbać o sprawdzenie, czy wszystko integruje się poprawnie.
Ale podzielenie projektu na wiele komponentów budowanych, wersjonowanych i wdrażanych osobno wymaga z mojego doświadczenia bardzo dojrzałego zespołu programistów, zespołu, który jest bardziej dojrzały niż mam wrażenie, że twój zespół jest.
Ale w każdym razie musisz coś zrobić ze strukturą projektu. Podziel projekty na osobne komponenty lub rozpocznij scalanie projektów.
Zadaj sobie pytanie, czy naprawdę potrzebujesz 120 projektów?
ps Może chcesz sprawdzić NCrunch. To wtyczka Visual Studio, która automatycznie uruchamia test w tle.
źródło
Test JUnit ma zwykle być szybki, ale niektóre z nich muszą po prostu trochę potrwać.
Na przykład test bazy danych zwykle trwa kilka razy, aby zainicjować i zakończyć.
Jeśli masz setki testów, nawet jeśli są one szybkie, ich uruchomienie wymaga dużo czasu.
Co można zrobić, to:
1) Zidentyfikuj kluczowe testy. Te dla najważniejszych części bibliotek i tych, które najprawdopodobniej zawiodą po zmianach. Tylko te testy powinny być uruchamiane zawsze podczas kompilacji. Jeśli jakiś kod jest często łamany, jego testy powinny być obowiązkowe, nawet jeśli jego wykonanie zajmuje dużo czasu, z drugiej strony, jeśli jakaś część oprogramowania nigdy nie spowodowała problemu, możesz bezpiecznie pominąć testy dla każdej kompilacji.
2) Przygotuj serwer ciągłej integracji, który uruchomi wszystkie testy w tle. Od Ciebie zależy, czy zdecydujesz się budować co godzinę lub budować po każdym zatwierdzeniu (drugi ma sens tylko wtedy, gdy chcesz automatycznie wykryć, czyje zatwierdzenie spowodowało problemy).
źródło
Problemy, które widziałem:
a) Używanie MKOl do budowania elementów testowych. 70 sekund -> 7 sekund po zdjęciu pojemnika.
b) Nie wyśmiewanie wszystkich klas. Trzymaj testy jednostkowe w jednym elemencie. Widziałem testy, które wędrują przez kilka klas. To nie są testy jednostkowe i znacznie bardziej prawdopodobne jest uszkodzenie.
c) Profiluj je, aby dowiedzieć się, co się dzieje. Odkryłem, że konstruktor budował rzeczy, których nie potrzebowałem, więc zlokalizowałem je i skróciłem czasy działania.
d) Profil. być może kod nie jest zbyt dobry i możesz zyskać na skuteczności dzięki recenzji.
e) Usuń zależności. Utrzymanie małego testowego pliku wykonywalnego skróci czas ładowania. Użyj biblioteki interfejsu i kontenerów IOC, aby uruchomić ostateczne rozwiązanie, ale główne projekty testowe powinny mieć tylko zdefiniowaną bibliotekę interfejsów. Zapewnia to separację, ułatwia testowanie, a także zmniejsza odcisk stopy testowej.
źródło
Czuję twój ból i natknąłem się na kilka miejsc, w których szybkość budowy można znacznie poprawić. Jednak zalecana przeze mnie liczba polega na dokładnym pomiarze, aby dowiedzieć się, gdzie twoja wersja trwa najdłużej. Na przykład mam kompilację z około 30 projektami, których uruchomienie zajmuje nieco ponad minutę. To jednak tylko część obrazu. Wiem też, które projekty najdłużej trwają, co pomaga skoncentrować moje wysiłki.
Rzeczy, które pochłaniają czas budowy:
Biblioteki próbne albo używają odbicia, albo wstrzykują kod za pomocą bibliotek kodów bajtowych, aby wygenerować próbkę. Jest to bardzo wygodne, ale zużywa czas testu. Jeśli generujesz symulacje w pętli w teście, może to dodać mierzalny czas do testów jednostkowych.
Istnieją sposoby rozwiązania problemów:
Gdy Twoje rozwiązanie zawiera ponad 100 projektów, masz kombinację kodu biblioteki, testów i kodu aplikacji. Każda z bibliotek może być własnym rozwiązaniem z powiązanymi testami. Jet Brains Team City to serwer kompilacji CI, który działa również jako serwer Nuget - i jestem pewien, że nie jest to jedyny. Daje to elastyczność przenoszenia bibliotek, które prawdopodobnie nie są często zmieniane, do własnych rozwiązań / projektów i używania Nuget do rozwiązywania zależności w kodzie aplikacji. Mniejsze rozwiązania oznaczają, że możesz szybko i bezproblemowo wprowadzać zmiany w bibliotece i cieszyć się korzyściami płynącymi z głównego rozwiązania.
źródło
Czy twoje środowisko testowe może działać gdziekolwiek? Jeśli to możliwe, użyj przetwarzania w chmurze, aby uruchomić testy. Podziel testy na N maszyn wirtualnych. Jeśli czas uruchomienia testów na pojedynczej maszynie wynosi T1 sekund, to czas na uruchomienie ich w podziale, T2, może zbliżyć się do T2 = T1 / N. (Zakładając, że każdy przypadek testowy zajmuje tyle samo czasu.) I musisz płacić za maszyny wirtualne tylko wtedy, gdy ich używasz. Więc nie masz garści testowych maszyn siedzących w jakimś laboratorium gdzieś 24 godziny na dobę. (Chciałbym móc to zrobić tam, gdzie pracuję, ale jesteśmy powiązani z konkretnym sprzętem. Brak maszyn wirtualnych dla mnie.)
źródło