Alternatywa dla wskaźnika „Podanie / zepsuta kompilacja”?

14

W przypadku ciągłej integracji wykonującej testy przy każdym zatwierdzeniu powszechną najlepszą praktyką jest przechodzenie wszystkich testów przez cały czas (aka „nie przerywaj kompilacji”).

Mam z tym pewne problemy:

Na przykład nie można pomóc projektowi typu open source, tworząc testy odpowiadające biletom. Wiem, że jeśli zgłoszę żądanie ściągnięcia do projektu typu open source zawierającego test zakończony niepowodzeniem, kompilacja zostanie oznaczona jako nieudana, a projekt nie będzie chciał scalić jej z repozytorium, ponieważ „przerwie kompilację”.

I nie wierzę, że źle jest mieć nieudane testy w twoim repozytorium , to jak mieć otwarte problemy w twoim trackerze. To tylko rzeczy czekające na naprawę.

To samo dotyczy firmy. Jeśli pracujesz z TDD, nie możesz pisać testów, zatwierdzać, a następnie pisać kodu logicznego, który spełnia test. Oznacza to, że jeśli napisałem 4-5 testów na swoim laptopie, nie mogę wykonać ich przed wyjazdem na wakacje. Nikt nie może odebrać mojej pracy. Nie mogę ich nawet „udostępnić” koledze, chyba że wysyłam je na przykład pocztą elektroniczną. Uniemożliwia to również pracę z jedną osobą piszącą testy, a drugą z modelem.

Wszystko to, żeby powiedzieć, czy niewłaściwie używam / nie rozumiem procesu kompilacji / ciągłej integracji? Wydaje mi się, że „przejście” / „przejście” jest zbyt wąskim wskaźnikiem.

Czy istnieje sposób na zapewnienie ciągłej integracji i kompatybilności TDD?

Może istnieje standardowe rozwiązanie / praktyka pozwalające rozróżnić „nowe testy” (które mogą zawieść) i „testy regresyjne” (które nie powinny zawieść, ponieważ kiedyś działały)?

Matthieu Napoli
źródło
1
Miej wskaźnik, który pokazuje, czy liczba nieudanych testów wzrosła (czerwona) lub spadła (zielona) w ciągu ostatniej godziny (lub mniej więcej).
Joachim Sauer
2
Nie jestem specjalistą TDD / ALM (stąd komentarz, a nie odpowiedź), ale myślę, że twój problem można rozwiązać za pomocą prywatnych gałęzi / gałęzi funkcji. Czy pracujesz nad funkcją A? Rozgałęź go, pracuj nad gałęzią (ze współpracownikami), a kiedy skończysz - połącz go w stale zintegrowany pień.
Avner Shahar-Kashtan
@ JoachimSauer Tak, ale czy taka metryka jest znormalizowana / stosowana w jakimkolwiek dużym projekcie? Próbuję zrozumieć, dlaczego większość projektów (i narzędzi CI) działa w ten sposób.
Matthieu Napoli
Myślę, że poprawnym kryterium dla „testów, które mogą się nie powieść” nie są „nowe testy”, ale „testy na znane otwarte problemy”. Widzę, w jaki sposób te testy są przydatne - mogę również dowiedzieć się, w jaki sposób te testy NIE są przydatne w kompilacji CI, ponieważ zanieczyszczają one znaczenie testu pozytywnego / negatywnego (chcesz uruchomić testy, dla których ktoś faktycznie spędził czas) aby je przekazać).
Joris Timmermans
@MadKeithV Dokładnie
Matthieu Napoli

Odpowiedzi:

12

Rozumiem, do czego zmierzasz, ale tego rodzaju problemy zazwyczaj rozwiązuje się na inne sposoby. Jest dobry powód, dla którego jest to standardowy protokół. Jeśli ktoś prześle kod, który się nie kompiluje, każdy , kto zaktualizuje jego kod, będzie miał program, który się nie kompiluje . Obejmuje to programistów, którzy obecnie pracują nad czymś zupełnie innym i znajdują się w sytuacji, w której muszą poczekać, zanim będą mogli skompilować i przetestować to, nad czym pracują.

Standardowy protokół polega na tym, że można zatwierdzać zmiany nawet w przypadku pełnej lub nawet niepełnej pracy, o ile kompiluje się , aby programiści mogli aktualizować swój kod każdego dnia, jeśli to konieczne.

Nadal jednak widzę, o co ci chodzi. Czasami chcesz zatwierdzić, aby po prostu zapisać swój kod. W tym celu większość repozytoriów źródłowych obsługuje rozgałęzianie. Pozwala to utworzyć prywatną gałąź, pracować nad nią bez przeszkadzania innym, a następnie połączyć się z pniem po zakończeniu pracy. Umożliwia to zatwierdzanie w dowolnym momencie bez luzu związanego z powodowaniem awarii kompilacji.

Jeśli to nie jest odpowiednie, GIT pozwala na zatwierdzanie (wypychanie) repozytoriów na twoim komputerze lokalnym, ale możliwe jest, że repozytorium może być gdziekolwiek. Możesz utworzyć repozytorium dla potencjalnie częściowej / niekompletnej pracy oraz inne repozytorium dla zakończonej pracy, aw tym repozytorium możesz dodać kompilację nocną.

Ponownie nie mogę wystarczająco podkreślić wagi. Nigdy nie wysyłaj uszkodzonego kodu do pnia! Twój wkład nie może wpływać na pracę innych programistów.

Edytować

Widzę, że chciałeś przerwać testy, ale moim skromnym zdaniem różnica jest niewielka. Celem całego testu jest ustalenie, czy dany aspekt programu przejdzie, czy nie. Jeśli zawsze zawiedzie i nic nie zrobisz, test, w tradycyjnym zastosowaniu testów jednostkowych, nic nie da. Jeśli użyjesz go do wykonania innej metryki, która niekoniecznie pociąga za sobą „nieudane” zatwierdzenie, jeśli jeden z takich testów się nie powiedzie, zdecydowanie zalecam znalezienie innego sposobu na zrobienie tego samego.

W przeciwnym razie ryzykujesz, że test nigdy nie zostanie wzięty pod uwagę lub jeśli spowoduje to niepowodzenie kompilacji, że inni programiści zignorują kompilacje nieudane. Ważniejsze jest, aby programiści zdali sobie sprawę, kiedy złamali kompilację, niż wykonanie testu, który nie oferuje prawdziwego wglądu i może skutkować jedynie złymi praktykami.

Neil
źródło
1
Rzeczywiście masz rację dzięki gałęziom tematów. Ale nigdy nie mówię o popełnianiu zepsutego kodu, tylko o niepowodzeniu testów. Na przykład mógłbym pomóc projektowi open source, tworząc testy dla przychodzących biletów, nawet jeśli nie wiem, jak je naprawić. To oszczędza trochę czasu dla opiekunów.
Matthieu Napoli
Jeśli pracuję nad tym samym projektem co Ty, a Ty prześlesz test zakończony niepowodzeniem, mam teraz kompilację z testem zakończonym niepowodzeniem. Mogę skończyć z usunięciem testu, ponieważ ta funkcja nie jest jeszcze zaimplementowana, lub zdecydować się na implementację tej funkcji i skończyć na tępieniu kodu i marnowaniu czasu. Gdyby istniała taka kultura, tego rodzaju reakcji można by uniknąć, ale wtedy wszyscy by to zrobili, a więc nawet po przejściu wszystkich testów, nie wszystkie moje. W takim przypadku kompilacja zawsze miałaby niepomyślne testy. Nie widzę plusów.
Michael Shaw
the build would always have failing testsdokładnie! Ale czy to takie złe? Naszą jedyną miarą jest „kompilacja jest zepsuta czy nie”, ale twój kod może być pełen znanych błędów , więc to tak naprawdę nic nie znaczy, z wyjątkiem braku regresji. W idealnym świecie każdy problem z trackerem zostałby przetestowany (odtwarzanie jest łatwiejsze niż naprawianie). Plusem jest więc to, że 35 testów / 70% wszystkich testów przechodzi, że oddział A poprawia go do 40 testów (80%) bez regresji, a oddział B ma regresje. Dzisiaj można tylko powiedzieć, że Master i Oddział A są w porządku, a Oddział B jest zepsuty.
Matthieu Napoli
@Matthieu Widzę o co ci chodzi. Wygląda na to, że potrzebujesz specjalnej kategorii lub czegoś, co mówi „hej, jeśli ten test się nie powiedzie, to jest ok. Wiemy o tym. Ale nadal chcemy, aby został uruchomiony, a jeśli przejdzie, to jest jeszcze lepiej i powinniśmy usunąć specjalną kategorię, ponieważ teraz obchodzi nas, czy się zepsuje ”
Earlz
@Ellz Dokładnie! Zastanawiam się: „czy ktoś to gdzieś robi? I czy istnieją narzędzia, które to obsługują (biblioteki CI i biblioteki testów jednostkowych?”) Ponieważ jeśli po prostu skategoryzuję te testy za pomocą klasycznych narzędzi CI i testów jednostkowych, kompilacja zawsze i tak się nie powiedzie i nie zobaczę różnicy między testami, które się nie powiodły, więc nie będzie to przydatne: /
Matthieu Napoli
4

Biorąc pod uwagę gałąź główną z nieudanymi testami, jak możesz być pewien - bez porównania tej listy z poprzednimi kompilacjami - że nie wprowadziłeś błędów?

Samo śledzenie liczby nieudanych testów jest niewystarczające: możesz naprawić jeden test i przerwać inny. A jeśli jesteś na wakacjach, nie będzie jasne dla innych, którzy patrzą na wadliwą wersję.

Utrzymuj swoją główną gałąź w czystości i przez cały czas. Pracuj w oddziale. Trzymaj oddział pod kontrolą CI, w osobnej pracy, i nie zdawaj testów na zadowolenie twojego serca. Tylko nie psuj mistrza.

Poproś recenzenta oddziału, aby połączył Twój oddział tylko wtedy, gdy przejdzie wszystkie testy. (Mocniej: niech recenzent będzie mógł scalić twój oddział tylko wtedy, gdy wynik scalenia gałęzi w master przejdzie wszystkie testy!)

Frank Shearar
źródło
2
Simply tracking the number of failing tests is insufficientto nie jedyna możliwa metryka. Na przykład: Branch-A improves it to 40 tests (80% passing) with no regression. Brak regresji oznacza, że ​​wcześniejsze testy zawsze kończą się pomyślnie. Krótko mówiąc, test może się nie powieść, o ile nigdy się nie powiedzie. Wydaje mi się, że brakuje nam dobrych rzeczy, ograniczając się do zakazania nieudanych testów w głównych gałęziach. (oczywiście wymagałoby to narzędzi działających inaczej: testów jednostkowych, CI, ...)
Matthieu Napoli
Nadal stoję przy swoim punkcie: mistrz powinien zawsze być zielony, ponieważ jest jasny i jednoznaczny. Testy markerów nie powiodły się ... w gałęzi funkcji. CI może ciągle przypominać ludziom o zaległych błędach.
Frank Shearar
Myślę, że to, co proponuje Matthieu, to nieco inna definicja „zielonego”, nie odbiegająca od tego, że mistrz zawsze jest zielony. Nie jest dla mnie oczywiste, że to nie ma sensu - oczywiście potrzebowałoby trochę niezupełnie trywialnych narzędzi do śledzenia. (Potrzebujesz cofnąć zmianę, która spowodowała, że ​​ten test przeszedł
pomyślnie
NUnit ma koncepcję testu ignorowanego. To może być alternatywa: nie uciekają, więc nie zawodzą, ale nadal są zgłaszane jako ignorowane.
Frank Shearar,
2

Istnieją sposoby rozwiązania problemów bez wyrzucania dobrze rozumianych i akceptowanych praktyk dotyczących ciągłej integracji.

Zacznę od problemu przeprowadzenia „zepsutego testu”, który odpowiada biletowi. Jednym z rozwiązań jest utworzenie jednego lub więcej testów zrywających, które ujawniają problem, a następnie naprawienie problemu , aby można je było połączyć z powrotem w główny wiersz kodu. Drugim rozwiązaniem są zepsute testy, ale użyj jakiegoś rodzaju flagi ignorowania, aby nie uruchomiły się i nie przerwały kompilacji. Ewentualnie dodaj komentarz lub specjalną adnotację, która czyni bardzo oczywistym, że jest to zepsuty test Ticket#N. Dołącz także notatkę do samego biletu, która odnosi się do utworzonych testów, które czekają na niezapisanie i uruchomienie. Pomogłoby to osobie naprawiającej bilet, ale również nie stanowiłoby czerwonej flagi dla osoby, która przejdzie test.

I na następny problem z TDD. TDD polega na napisaniu małego testu, a następnie napisaniu małego fragmentu kodu, aby ten test przeszedł pomyślnie . Następnie iteruj, aż będziesz mieć mały moduł funkcjonalny. Wydaje mi się, że jeśli napiszesz 4-5 testów, to pojedziesz na wakacje, być może robisz to źle. Możesz sparować program z kimś w taki sposób, aby jeden z was napisał test, a drugi odpowiedni kod. Nie powinieneś jednak używać głównego repozytorium linii kodu do dzielenia się tym kodem między sobą, zanim gotowy moduł będzie gotowy do zatwierdzenia. Jak sugerowali inni, wspólny oddział rozwiązałby tam twoje problemy.

Próba przełamania ciągłej integracji mantry może prowadzić do nieoczekiwanych i przerażających ścieżek. Na przykład, co oznaczałoby pokrycie kodu w tego typu środowisku ? Jak deweloperzy nie czuliby, że system ma wiele zepsutych okien ? Jak dokonać zmiany, uruchomić test i wiedzieć, czy faktycznie psują coś nowego, czy to tylko stare rzeczy?

c_maker
źródło
Nie potrzebujesz żadnych narzędzi do dzielenia się z osobą, z którą programujesz w parach - po prostu oddaj klawiaturę. Jeśli używasz różnych komputerów, cóż, nie ma w tym nic złego, to po prostu nie „parowanie”.
Christopher Creutzig
1

Myślę, że twoim podstawowym problemem jest to, że włączasz testowe WYNIKI jako część kompilacji. Chociaż oczywiście niektórzy się z tobą zgadzają, inni nie. Przerwanie kompilacji następuje, gdy się nie kompiluje. Nie wtedy, gdy nie buduje się bez błędów.

Zastanów się nad dużym projektem, takim jak Windows lub Linux, a nawet czymś takim jak Firefox - czy uważasz, że dostarczają one wolne od błędów? Oczywiście nie. Teraz te projekty nie robią TDD, ale to naprawdę nie ma znaczenia - TDD nie zmienia dwóch podstawowych faktów: istnieją błędy i ich usunięcie zajmuje dużo czasu. Czas, którego projekt (open source lub nie) po prostu nie może zmarnować na błędy o niskim priorytecie. KDE ostatnio miało błąd, który został naprawiony ponad dekadę. Kiedy ostatni raz słyszałeś, jak ktoś powiedział: „Cieszę się, że czekaliśmy dekadę na wysłanie naszego projektu”?

TDD, w pewnym sensie, prawdopodobnie sprawia, że ​​łatwiej jest wysyłać z błędami - ponieważ lepiej rozumiesz, czym jest wada. Jeśli potrafisz precyzyjnie zdefiniować przyczynę błędu, masz doskonałą podstawę do zważenia kosztów jego usunięcia.

Radzę znaleźć projekt, który nie miałby nic przeciwko czerwieni wśród zieleni.

jmoreno
źródło
1
 > a common best practice is to have all the tests passing (green) at all times.

Wolę, aby wszystkie testy nie zawiodły (nie czerwone).

Za pomocą tej nieco innej definicji można również zdefiniować testy

  • jeszcze nie zaimplementowane (szary w nunit, jeśli istnieje NotImplementedException)
  • wiadomo, że kończy się niepowodzeniem = „musi to zrobić” poprzez oznaczenie / oznaczenie testu jako ignorowanego (żółty)

Po sprawdzeniu ich w repozytorium twoja ciągła kompilacja nie jest zepsuta, a zatem ważna.

k3b
źródło
0

Można rozważyć dwie różne „koncepcje” kompilacji CI.

  1. Regularne kompilacje CI. Zwykła kompilacja CI powinna kompilować i uruchamiać tylko te testy, dla których został napisany kod, aby je przekazać, tak aby raporty CI o pozytywnym / negatywnym wyniku testu były wyraźnym, jednoznacznym wskaźnikiem regresji w stosunku do wcześniej zaakceptowanego stanu kodu.
  2. „Przyszła” wersja CI. Ta kompilacja kompiluje i uruchamia tylko te testy, dla których nie został napisany żaden specjalny kod, aby je przekazać. Istnieje kilka powodów, dla których warto przeprowadzić taki test:

    • Testy można dodawać do konkretnych przypadków awarii z modułu śledzenia problemów, dla których nie podjęto jeszcze próby naprawy. Wyraźnie przydatne jest posiadanie skodyfikowanego, działającego testu na problem, nawet bez poprawki.

    • Dodano testy dla nowej wymaganej funkcjonalności, która nie została jeszcze zaimplementowana.

    • Często łatwiej jest wiedzieć, jak przetestować awarię lub funkcję, niż wiedzieć, jak zaimplementować tę funkcję lub naprawę, a oddzielenie dwóch kroków przez przekazanie testu kontroli źródła może być przydatne, aby upewnić się, że nie zostaną utracone żadne informacje.

Podobnie jak w „standardowym” CI, w normalnym trybie rozwoju zespół będzie patrzył tylko na wyniki codziennej kompilacji zwykłej kompilacji.

Zespół może również obserwować ewolucję przypadków testowych od kompilacji „przyszłego” CI - szczególnie po to, aby sprawdzić, czy jakiekolwiek zmiany wprowadzone w zwykłym CI nie naprawią problemów z kompilacji „przyszłej”, co może wskazywać na ważną problem podstawowy lub ulepszenie projektu.

Wreszcie, jeśli członek zespołu ma dodatkowy czas, może zająć się naprawieniem jednego z problemów z „przyszłości”, a jeśli uda mu się przenieść go do „zwykłego” (podczas aktualizacji statusu narzędzia do śledzenia problemów).

Joris Timmermans
źródło
0

I nie wierzę, że źle jest mieć nieudane testy w twoim repozytorium, to jak mieć otwarte problemy w twoim trackerze. To tylko rzeczy czekające na naprawę.

Problemem nie są nieudane testy, to prosty, pozbawiony kontekstu wskaźnik regresji. Aka: jako programista mogę sprawdzić pojedynczy wskaźnik i wiedzieć, czy wprowadziłem regresję czy łamanie kodu.

W momencie wprowadzenia koncepcji „miękkich” awarii (jest w porządku, pracujemy nad tym / jeszcze nie zaimplementowaliśmy / czekamy na nową wersję / przejdzie ona ponownie, gdy ta druga kompilacja zostanie naprawiona), potrzebujesz wszyscy, którzy mogą uruchomić lub spojrzeć na test, aby poznać oczekiwany stan. Co w wystarczająco dużym zespole zmienia się z godziny na godzinę: wskaźnik przestaje mieć znaczenie. W mniejszym kontekście (na przykład test integracji prywatnej zespołu), myślę, że to jest jak dług techniczny i jest w porządku - wystarczy zarządzać.

Sposób, w jaki większość adresów narzędzi, czyli „zielony / przekazujący”, odzwierciedla oczekiwany wynik - nie to, że kod działa:

  • Fitness ma pojęcie oczekiwanej porażki.
  • JUnit ma @Ignored / @Test (expect =)
  • Ogórek ma status „jeszcze nie zaimplementowany” (lub jakkolwiek to się nazywa)

Pojawiają się one z własnymi problemami (jak odróżnić „tak, wiemy, że jest zepsute, praca nad nim” i „prawidłowe zachowanie jest wyjątkiem”) - ale pomagają.

ptyx
źródło
0

Używam pominiętych testów.

W konkretnym środowisku testów jednostkowych, którego używam, mogę zgłosić wyjątek SkipTest. Test nie jest właściwie uruchamiany, a jego niepowodzenie nie zepsuje kompilacji. Widzę jednak liczbę pominiętych testów i sprawdzam, czy w tym obszarze jest coś do zrobienia.

Winston Ewert
źródło