Mockowanie a wydajność

0

U mojego klienta mamy trochę ponad 3000 testów jednostkowych, których odpalenie zajmuje ok. 7-8 minut. Średnio daje to ok. 0,13s per test. Ponieważ chcemy uruchamiać wszystkie testy przy każdym deploymencie (także każdej instancji testowej), zależy nam na skróceniu tego czasu. Zauważyłem, że testy, w których nie są mockowane żadne obiekty, wykonują się w granicach 1-3ms, w pozostałych czas znacznie rośnie (w zależności do ilości mockowanych obiektów). Korzystamy z Rhino Mocks. Zastanawiam się, czy waszym zdaniem realne jest znaczne skrócenie średniego czasu - być może da się zastosować jakieś triki z globalnym cacheowaniem mocków; niczego w necie nie udało mi się znaleźć. I generalnie, czy taki rząd średniego czasu jest mocno zawyżony, jak to u Was wygląda?

0

Dlaczego uruchamiacie testy jednostkowe przy deploymencie, a nie po buildzie?

0

Sorry, oczywiście puszczamy po buildzie, przed deploymentem. W każdym razie cały proces długo trwa przez konieczność odpalenia testów.

0

Testy odpalane lokalnie też tyle trwają? Próbowałeś je jakoś profilować?

0

Lokalnie czas jest podobny (nawet trochę dłuższy ze względu na wydajność maszyny). Trochę wybadałem temat i niestety wydaje mi się, że żadnej magicznej sztuczki tutaj nie zastosuję. Mockowania jest bardzo dużo, mockowane klasy są często bardzo ciężkie (pewnie to wydłuża czas mockowania, więcej refleksji pod spodem). Trzeba sporo bindować (wiele klas używa NinjectLocatora niestety). Poza tym sama logika jest dość złożona, więc nie wierzę, że da się tu uzyskać średni czas rzędu milisekundy. Znalazłem taki wątek na stackoverflow:

http://stackoverflow.com/ques[...]ow-is-too-slow-for-unit-tests

Gość ma podobne czasy jak ja (najdłuższe ze względu właśnie na mocki), a najlepsza rada, jaką dostał, to podzielić testy na grupę krytycznych (wykonywanych szybko i zawsze po buildzie) i pozostałych (które mogą się wykonywać kilka minut, kiedy są wolne zasoby).

1
Hrypa napisał(a):

Gość ma podobne czasy jak ja (najdłuższe ze względu właśnie na mocki), a najlepsza rada, jaką dostał, to podzielić testy na grupę krytycznych (wykonywanych szybko i zawsze po buildzie) i pozostałych (które mogą się wykonywać kilka minut, kiedy są wolne zasoby).

To jakby zaburza trochę ideę CI. No, ale jeśli część testów jest, że tak powiem, bardziej integracyjna od innych, to może się udać.
Chociaż ja bym i tak spróbował profilować, bo może się okazać, że przez jakiś prosty błąd (typu Thread.Sleep w pętli) coś wykonuje się w absurdalnym czasie.

0

U nas testy są podzielone na dwa kawałki, część testującą najczęściej modyfikowane elementy systemu i część testującą wszystko. Są to stare zależności, bo kiedyś testy całości zajmowały pół godziny, po znalezieniu i zlikwidowaniu dziury jedno i drugie wykonuje się na agencie Team City poniżej 10 minut (z tego powodu te dwie grupy testów kiedyś zostaną złączone). 10-15 minut (czasem trochę więcej, bo TC może być zajęte innymi projektami) jest to całkowicie akceptowalnym czasem. Dlaczego? Bo:

  • część testów, które bezpośrednio dotykają modyfikowanego kodu, uruchamiasz lokalnie u siebie (sam wybierasz które) i trwa to kilkanaście-kilkadziesiąt sekund,
  • testy na TC odbywają się automatycznie po każdym commicie i całkowicie w tle, jeśli coś spieprzysz i kod się nie skompiluje albo któryś test się wywali dostajesz maila (bo to po Twoim commicie coś nie działa) i wiesz, że to Ty coś spiertentego,
  • nie jest problemem, że musisz poczekać te 10-15 minut na TC, bo nie musisz czekać z dalszym pisaniem kodu, przecież nie zapomnisz po kwadransie co miałeś na myśli w wywalającym się miejscu.
    Testy powinny wykonywać się po każdym commicie (lub grupami, jeśli commity są bardzo częste), zanim zrobi się jakakolwiek paczka z deploy'em. Jeśli uruchamiacie testy jednostkowe u klienta (mocki!!! po co sprawdzać mocki u klienta?!), to coś wam się pomyliło.
0

Dzięki za pomoc. Z tym "klientem" to też niefortunne określenie. Nie chodziło mi o odbiorcę softu, tylko o firmę dla której pracuję. Puszczanie testów po każdym pushu nie wchodzi w grę, bo zarżnęlibyśmy maszynę. Cały czas mówię tu nie o finalnym deploymencie, czy nawet jakichś UATach, a o deweloperskich środowiskach testowych, których mamy setki. Nie po każdym pushu chcemy publikować zmiany na deweloperskie środowisko testowe, często kod nie jest jeszcze gotowy i z góry wiadomo, że testy nie przejdą (znowu podkreślam, chodzi o pushowanie do poszczególnych deweloperskich branchy).
@somekind dzięki za sugestię. Sprawdziłem dotTracem i faktycznie, spory fragment czasu zabiera rhino mocks. Ale znaczna większość idzie na Ninject:/ Mała część na faktyczną logikę biznesową. Będę jeszcze kombinował, co z tym fantem zrobić.

1

7-8 minut to aż taki problem? 2 godziny lub więcej to rozumiem, jest wtedy o co walczyć.
Jeśli jest dużo developerów (dużo branchy równocześnie), to maszyna integracyjna powinna robić testy jedynie dla comitów do master lub na ręczne żądanie.
Jakoś nie chce mi się wierzyć, że merge do master macie częściej niż co 30 minut.

0

@Hrypa, setki środowisk testowych? To co Wy za soft piszecie?

Zawsze można robić build + testy nie po każym commicie, tylko np. co jakiś czas, albo zgodnie z wolnymi zasobami, TeamCity takie coś potrafi. Zysk taki, że maszyna się nie męczy, minus taki, że nie wiadomo dokładnie kto zepsuł testy.
No, a inna rzecz, że może po prostu trzeba więcej build agentów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0