Czy dobrym pomysłem jest zmierzenie wydajności metody przy użyciu limitu czasu testu jednostkowego?

14

W projekcie, w którym istnieją niefunkcjonalne wymagania, które określają maksymalny czas wykonania dla określonego działania, QA musi sprawdzić wydajność tego działania na dedykowanej maszynie przy użyciu precyzyjnego sprzętu pod precyzyjnym obciążeniem, przy czym zarówno sprzęt, jak i obciążenie są określone w wymaganiach.

Z drugiej strony niektóre błędne zmiany w kodzie źródłowym mogą poważnie wpłynąć na wydajność. Zauważenie tego negatywnego wpływu wcześnie , zanim kod źródłowy przejdzie do kontroli źródła i zostanie zweryfikowany przez dział kontroli jakości, może być korzystny pod względem czasu straconego przez dział kontroli jakości zgłaszający problem, a deweloper naprawiający go kilka później.

Aby to zrobić, czy to dobry pomysł:

  • Aby użyć testów jednostkowych, aby zorientować się, ile czasu zajmuje wykonanie tej samej akcji² n razy,

  • Aby użyć limitu czasu dla testu za pomocą [TestMethod, Timeout(200)]atrybutu w języku C #?

Oczekuję kilku problemów z tym podejściem:

  • Pod względem koncepcyjnym testy jednostkowe tak naprawdę nie są do tego przeznaczone: oczekuje się, że przetestują małą część kodu, nic więcej: ani sprawdzenie wymagań funkcjonalnych, ani test integracji, ani test wydajności.

  • Czy limit czasu testu jednostkowego w programie Visual Studio naprawdę mierzy to, co należy zmierzyć, biorąc pod uwagę, że inicjalizacja i czyszczenie nie istnieją dla tych testów lub są zbyt krótkie, aby wpłynąć na wyniki?

  • Pomiar wydajności w ten sposób jest brzydki. Uruchomienie testu porównawczego na dowolnej maszynie¹ niezależnie od sprzętu, obciążenia itp. Jest jak wykonanie testu porównawczego, który pokazuje, że jeden produkt bazodanowy jest zawsze szybszy od drugiego. Z drugiej strony nie oczekuję, że te testy jednostkowe będą ostatecznym wynikiem, ani też czymś, co będzie wykorzystywane przez dział kontroli jakości . Te testy jednostkowe zostaną wykorzystane jedynie w celu przedstawienia ogólnego wyobrażenia o oczekiwanej wydajności i zasadniczo do ostrzeżenia dewelopera, że ​​jego ostatnia modyfikacja coś zepsuła, poważnie wpływając na wydajność .

  • Test Driven Development (TDD) jest niemożliwy dla tych testów. Jak by to się nie powiodło, zanim zacznie wdrażać kod?

  • Zbyt wiele testów wydajności wpłynie na czas wymagany do uruchomienia testów, więc to podejście ogranicza się tylko do krótkich akcji.

Biorąc pod uwagę te problemy, nadal uważam za interesujące stosowanie takich testów jednostkowych, jeśli są one połączone z rzeczywistymi wskaźnikami wydajności działem kontroli jakości.

Czy się mylę? Czy istnieją inne problemy, które sprawiają, że całkowicie niedopuszczalne jest stosowanie do tego testów jednostkowych?

Jeśli się mylę, jaki jest właściwy sposób ostrzeżenia programisty, że zmiana kodu źródłowego poważnie wpłynęła na wydajność, zanim kod źródłowy przejdzie pod kontrolę źródła i zostanie zweryfikowany przez dział kontroli jakości?


¹ W rzeczywistości oczekuje się, że testy jednostkowe będą przeprowadzane tylko na komputerach programistów o porównywalnej wydajności sprzętowej, co zmniejsza różnicę między najszybszymi komputerami, które nigdy nie będą w stanie zawieść testu wydajności, a najwolniejszymi komputerami, które nigdy nie zdadzą go pomyślnie.

² Przez działanie mam na myśli raczej krótki fragment kodu, którego uruchomienie zajmuje kilka milisekund.

Arseni Mourzenko
źródło

Odpowiedzi:

3

Stosujemy również to podejście, tzn. Mamy testy, które mierzą czas działania w określonym scenariuszu obciążenia na danym komputerze. Ważne może być wskazanie, że nie uwzględniamy ich w normalnych testach jednostkowych. Testy jednostkowe są w zasadzie wykonywane przez każdego programistę na komputerze programisty przed zatwierdzeniem zmian. Zobacz poniżej, dlaczego nie ma to sensu dla testów wydajności (przynajmniej w naszym przypadku). Zamiast tego przeprowadzamy testy wydajności w ramach testów integracyjnych.

Prawidłowo wskazałeś, że nie powinno to wykluczać weryfikacji. Nie zakładamy, że nasz test jest testem wymagań niefunkcjonalnych. Zamiast tego uważamy to za zwykły wskaźnik potencjalnego problemu.

Nie jestem pewien co do twojego produktu, ale w naszym przypadku, jeśli wydajność jest niewystarczająca, oznacza to, że potrzeba dużo pracy, aby to naprawić. Tak więc czas zawracania, kiedy pozostawiamy to całkowicie kontroli jakości, jest okropny. Ponadto poprawki wydajności będą miały poważny wpływ na dużą część podstawy kodu, co powoduje, że poprzednie prace związane z kontrolą jakości są nieważne. Podsumowując, bardzo nieefektywny i niezadowalający przepływ pracy.

Biorąc to pod uwagę, oto kilka punktów dotyczących twoich problemów:

  • koncepcyjnie: to prawda, że ​​nie o to chodzi w testach jednostkowych. Ale tak długo, jak wszyscy są świadomi, że test nie powinien weryfikować niczego, co powinna zrobić QA, jest w porządku.

  • Visual Studio: nie możemy nic na ten temat powiedzieć, ponieważ nie używamy frameworku testów jednostkowych VS.

  • Maszyna: zależy od produktu. Jeśli Twój produkt jest przeznaczony dla użytkowników końcowych z niestandardowymi indywidualnymi komputerami stacjonarnymi, przeprowadzanie testów na komputerach różnych programistów jest bardziej realistyczne. W naszym przypadku dostarczamy produkt do maszyny o określonej specyfikacji i testy wydajności przeprowadzamy tylko na takiej maszynie. Rzeczywiście, nie ma większego sensu mierzenie wydajności na dwurdzeniowej maszynie deweloperskiej, kiedy klient ostatecznie uruchomi 16 lub więcej rdzeni.

  • TDD: Chociaż początkowa awaria jest typowa, nie jest to konieczne. W rzeczywistości wczesne napisanie tych testów sprawia, że ​​służy raczej jako test regresji niż tradycyjny test jednostkowy. To, że test się powiedzie wcześnie, nie stanowi problemu. Ale masz tę zaletę, że za każdym razem, gdy programista dodaje funkcjonalność, która spowalnia rzeczy, ponieważ nie był świadomy niefunkcjonalnego wymogu wydajności, ten test TDD go wykryje. Zdarza się dużo i jest to niesamowita informacja zwrotna. Wyobraź sobie, że w codziennej pracy: piszesz kod, zatwierdzasz go, idziesz na lunch, a gdy wrócisz, system kompilacji mówi ci, że ten kod, gdy jest wykonywany w środowisku dużego obciążenia, jest zbyt wolny. Miło mi to zaakceptować, że test TDD początkowo nie zawiódł.

  • Czas wykonywania: jak wspomniano, nie uruchamiamy tych testów na komputerach programistów, ale raczej jako część systemu kompilacji w ramach testu integracji.

Szczery
źródło
3

Jestem w dużej mierze zgodny z twoim myśleniem. Po prostu opierając moje rozumowanie na niezależnym przepływie.

1. Spraw, by działał, zanim stał się lepszy / szybszy
Zanim kod zapewni jakikolwiek pomiar wydajności (nie mówiąc już o zagwarantowaniu), należy go najpierw poprawić, tzn. Sprawić, by działał. Optymalizacja kodu, który jest funkcjonalnie niepoprawny, to nie tylko strata czasu, ale także utrudnia rozwój.

2. Wydajność systemu ma sens tylko w pełnym systemie
Zazwyczaj każda znacząca wydajność zawsze zależy od danej infrastruktury i powinna być postrzegana tylko w pełnym systemie. Na przykład podczas próbnego testu, jeśli moduł odbiera odpowiedzi z lokalnych plików tekstowych, ale w środowisku produkcyjnym pobiera dane z bazy danych, wcześniej

3. Skalowanie wydajności powinno odbywać się według celu
Po uzyskaniu funkcjonalnego systemu należy przeanalizować wydajność systemu i znaleźć wąskie gardła, aby zrozumieć, gdzie należy zwiększyć wydajność. Ślepe próby zoptymalizowania każdej metody, nawet zanim poznasz wydajność pełnego systemu, może pociągać za sobą niepotrzebną pracę (optymalizacja metod, które nie mają znaczenia) i może stworzyć niepotrzebnie rozdęty kod.

Nie jestem całkowicie świadomy funkcjonalności Visual Studio, ale ogólnie potrzebujesz szerszego narzędzia do profilowania.

Dipan Mehta
źródło
2

Jakiś czas temu miałem podobne zadanie, a ostateczne rozwiązanie było gdzieś pośrodku między testowaniem jednostkowym a w pełni automatycznym testowaniem wydajności.

Niektóre uwagi w określonej kolejności, które mogą być przydatne:

  • Testy wydajności przeprowadzane przez kontrolę jakości były pracochłonne i miały własny harmonogram (powiedzmy raz w iteracji), więc uzyskanie kontroli źródła nie stanowiło problemu.
  • Nasz system był duży i modułowy, testy jednostkowe były zbyt szczegółowe dla naszych potrzeb, a my stworzyliśmy specjalne „jednostkowe” testy jednostkowe starannie opracowane, aby wywołać problemy z wydajnością w określonych obszarach zainteresowania (zostały również podzielone na kategorie, ale to jest szczegół implementacji).
  • Nadal obowiązują typowe ograniczenia dla testów jednostkowych: powinny być małe, szybkie i na temat.
  • Aby wykluczyć wpływ środowiska testowego, działały one w specjalnym opakowaniu, więc wiedzieliśmy dokładnie, ile czasu zajmuje dana operacja.
  • Można je napisać przed zakończeniem faktycznej implementacji (wyniki mogą być nieistotne lub przydatne, w zależności od procesu, być może programiści nadal eksperymentują z implementacją i chcieliby zobaczyć, jak idzie ogólnie).
  • Były uruchamiane przez serwer CI po każdej kompilacji, więc całkowity czas działania powinien być stosunkowo krótki (jeśli tak nie jest, znacznie trudniej jest wskazać dokładną zmianę, która spowodowała problem).
  • Serwer CI był potężny i miał naprawiony sprzęt, dlatego policzyliśmy to jako maszynę dedykowaną (możliwe jest użycie naprawdę dedykowanego serwera za pomocą zdalnego agenta kompilacji).
  • Opakowanie testowe zebrało wszystkie istotne informacje (specyfikacje sprzętu, nazwy / kategorie testów, obciążenie systemu, upływ czasu itp.) I wyeksportowało je jako raporty lub do bazy danych.
  • Mieliśmy gadżet dla JIRA, który pobiera te raporty i rysuje ładne wykresy według nazwy / kategorii / numeru kompilacji z pewnymi kontrolkami (nakładka poprzedniej wersji na bieżącą itp.), Więc programiści mogą szybko zobaczyć ich wpływ, a menedżerowie mogą uzyskać przegląd (niektóre czerwone, wszystkie zielone, wiesz, to dla nich ważne).
  • Za pomocą zebranych statystyk można było przeanalizować przebieg projektu w czasie.

Tak więc ostatecznie mieliśmy skalowalny, elastyczny i przewidywalny system, który możemy szybko dostosować do naszych specjalnych wymagań. Wymagało to jednak pewnego wysiłku.

Wracając do pytań. Koncepcyjnie testy jednostkowe nie są do tego przeznaczone, ale można wykorzystać funkcje środowiska testowego. Nigdy nie uważałem limitów czasu testu za środek do pomiaru, to tylko siatka bezpieczeństwa dla zawieszeń i takich rzeczy. Ale jeśli twoje obecne podejście działa dla Ciebie, kontynuuj jego stosowanie, bądź praktyczny. W razie potrzeby zawsze możesz zrobić coś wyjątkowego.

Oleg Kolosov
źródło
0

Myślę, że masz się dobrze. Właśnie w tym momencie mają limity czasu testów jednostkowych: aby sprawdzić, czy coś się dzieje , znacznie dłużej niż powinno. Istnieją ograniczenia w tym podejściu, ale wydaje się, że już je znasz, więc dopóki pamiętasz o tych ograniczeniach, nie widzę problemu.

Mike Baranczak
źródło