Obecnie w mojej pracy mamy duży pakiet testów jednostkowych dla naszej aplikacji C ++. Nie używamy jednak ram testów jednostkowych. Po prostu używają makra C, które w zasadzie otacza aser i cout. Coś jak:
VERIFY(cond) if (!(cond)) {std::cout << "unit test failed at " << __FILE__ << "," << __LINE__; asserst(false)}
Następnie po prostu tworzymy funkcje dla każdego z naszych testów, takie jak
void CheckBehaviorYWhenXHappens()
{
// a bunch of code to run the test
//
VERIFY(blah != blah2);
// more VERIFY's as needed
}
Nasz serwer CI odbiera komunikat „test jednostkowy nie powiódł się” i kompilacja kończy się niepowodzeniem, wysyłając wiadomość e-mail do programistów.
A jeśli mamy zduplikowany kod instalacyjny, po prostu refaktoryzujemy go tak, jak każdy inny zduplikowany kod, który mielibyśmy w produkcji. Opakowujemy go za funkcje pomocnicze, niektóre klasy testowe zawijają konfigurację często używanych scenariuszy.
Wiem, że istnieją frameworki, takie jak CppUnit i test jednostek podwyższających. Zastanawiam się, jaką wartość to dodają? Czy tęsknię za tym, co przynoszą na stół? Czy jest coś przydatnego, co mogę na nich zyskać? Waham się przed dodaniem zależności, chyba że wnosi ona prawdziwą wartość, zwłaszcza że wydaje się, że to, co mamy, jest bardzo proste i działa dobrze.
źródło
Wygląda na to, że już używasz frameworka, domowej roboty.
Jaka jest wartość dodana bardziej popularnych ram? Powiedziałbym, że wartość, którą dodają, polega na tym, że kiedy trzeba wymieniać kod z osobami spoza firmy, można to zrobić, ponieważ jest on oparty na znanym i powszechnie używanym frameworku .
Z drugiej strony, domowe frameworki zmuszają cię do tego, abyś nigdy nie dzielił się swoim kodem, lub do dostarczenia samego frameworka, co może stać się kłopotliwe z powodu rozwoju samego frameworka.
Jeśli podasz swój kod takiemu koledze, jak jest, bez wyjaśnień i bez ram testów jednostkowych, nie będzie w stanie go skompilować.
Drugą wadą domowych frameworków jest kompatybilność . Popularne frameworki testów jednostkowych zapewniają zgodność z różnymi IDE, systemami kontroli wersji itp. W tej chwili może to nie być dla Ciebie bardzo ważne, ale co się stanie, jeśli pewnego dnia będziesz musiał coś zmienić na serwerze CI lub przeprowadzić migrację do nowego IDE lub nowego VCS? Czy na nowo wymyślisz koło?
Wreszcie, większe frameworki zapewniają więcej funkcji, które mogą być potrzebne do zaimplementowania we własnym frameworku jednego dnia.
Assert.AreEqual(expected, actual)
nie zawsze wystarcza. Co jeśli potrzebujesz:zmierzyć precyzję?
anulować test, jeśli działa zbyt długo? Ponowne wprowadzenie limitu czasu może nie być proste, nawet w językach, które ułatwiają programowanie asynchroniczne.
przetestować metodę, która oczekuje na zgłoszenie wyjątku?
masz bardziej elegancki kod?
jest w porządku, ale czy nie jest bardziej wyrazisty zamiar napisania następnego wiersza?
źródło
Jak już powiedzieli inni, masz już własne, domowe ramy.
Jedyny powód, dla którego widzę użycie innego frameworka testowego, byłby z „powszechnej wiedzy” branży. Nowi programiści nie musieliby uczyć się twojego domu (choć wygląda to bardzo prosto).
Ponadto inne ramy testowe mogą mieć więcej funkcji, z których możesz skorzystać.
źródło
Masz już framework, nawet jeśli jest prosty.
Głównymi zaletami większego frameworka, jaki widzę, jest możliwość posiadania wielu różnych twierdzeń (takich jak twierdzenie podwyżek), logiczna kolejność testów jednostkowych oraz możliwość uruchamiania tylko podzbioru testów jednostkowych w czas. Wzorzec testów xUnit jest całkiem przyjemny do naśladowania, jeśli możesz - na przykład jeden setUP () i tearDown (). Oczywiście, to blokuje cię we wspomnianym frameworku. Pamiętaj, że niektóre frameworki mają lepszą integrację próbną niż inne - na przykład próbną wersję Google i test.
Jak długo zajmie Ci refaktoryzacja wszystkich testów jednostkowych do nowej struktury? Dni lub kilka tygodni może warto, ale więcej może nie tyle.
źródło
Z mojego punktu widzenia oboje macie przewagę i znajdujecie się w „niekorzystnej sytuacji” (sic).
Zaletą jest to, że masz system, w którym czujesz się komfortowo i który działa dla Ciebie. Cieszysz się, że potwierdza to ważność twojego produktu i prawdopodobnie nie znajdziesz wartości biznesowej, próbując zmienić wszystkie swoje testy na coś, co korzysta z innego frameworka. Jeśli możesz przefakturować kod, a testy wykryją zmiany - lub jeszcze lepiej, jeśli możesz zmodyfikować testy, a istniejący kod nie przejdzie testów do czasu, aż zostanie zrefaktoryzowany, oznacza to, że masz wszystkie podstawy. Jednak...
Jedną z zalet posiadania dobrze zaprojektowanego API do testowania jednostek jest to, że w większości współczesnych IDE jest dużo natywnego wsparcia. Nie wpłynie to na hard-core VI i emacs użytkowników, którzy szydzą z użytkowników Visual Studio tam, ale dla tych, którzy używają dobrego IDE, masz możliwość debugowania testów i wykonania ich w obrębie samo IDE. Jest to dobre, jednak istnieje jeszcze większa zaleta w zależności od używanego frameworka, czyli w języku używanym do testowania kodu.
Kiedy mówię język , nie mówię o języku programowania, ale mówię o bogatym zestawie słów owiniętych płynną składnią, dzięki której kod testowy jest czytany jak historia. W szczególności stałem się zwolennikiem korzystania z ram BDD . Moim ulubionym API DotNet BDD jest StoryQ, ale istnieje kilka innych o tym samym podstawowym celu, którym jest wyciągnięcie pojęcia z dokumentu wymagań i zapisanie go w kodzie w podobny sposób, jak jest napisany w specyfikacji. Naprawdę dobre interfejsy API idą jednak jeszcze dalej, przechwytując każdą pojedynczą instrukcję w teście i wskazując, czy instrukcja wykonała się pomyślnie, czy nie. Jest to niezwykle przydatne, ponieważ możesz zobaczyć cały test wykonany bez powrotu wcześniej, co oznacza, że twoje wysiłki debugowania stają się niezwykle wydajne, ponieważ musisz tylko skupić uwagę na częściach testu, które zakończyły się niepowodzeniem, bez konieczności dekodowania całego połączenia sekwencja. Inną miłą rzeczą jest to, że wynik testu pokazuje wszystkie te informacje,
Jako przykład tego, o czym mówię, porównaj następujące:
Korzystanie z zapewnień:
Korzystając z płynnego interfejsu API BDD: (Wyobraź sobie, że kursywa to w zasadzie wskaźniki metod)
Teraz przyznano, że składnia BDD jest dłuższa i bardziej sformułowana, a te przykłady są strasznie wymyślone, jednak w bardzo złożonych sytuacjach testowych, w których wiele rzeczy zmienia się w systemie w wyniku danego zachowania systemu, składnia BDD oferuje jasne opis tego, co testujesz i jak zdefiniowano konfigurację testu. Możesz pokazać ten kod programistom, a oni natychmiast zrozumieją, co się dzieje. Ponadto, jeśli „zmienna_A” nie przejdzie testu w obu przypadkach, przykład Asserts nie wykona się po pierwszym stwierdzeniu, dopóki problem nie zostanie rozwiązany, podczas gdy interfejs BDD API wykona kolejno każdą metodę wywoływaną w łańcuchu i wskaże, która z nich poszczególne części oświadczenia były błędne.
Osobiście uważam, że to podejście działa znacznie lepiej niż bardziej tradycyjne frameworki xUnit w tym sensie, że językiem testowania jest ten sam język, w którym klienci będą mówić o swoich logicznych wymaganiach. Mimo to udało mi się wykorzystać frameworki xUnit w podobnym stylu, bez potrzeby wymyślania pełnego testowego interfejsu API, aby wesprzeć moje wysiłki, a podczas gdy twierdzenia nadal skutecznie same się zwieją, czytają bardziej czysto. Na przykład:
Korzystanie z Nunit :
Jeśli zdecydujesz się na skorzystanie z interfejsu API do testowania jednostkowego, radzę eksperymentować z dużą liczbą różnych interfejsów API przez chwilę, a także zachować ostrożność i podejście do swojego podejścia. Chociaż ja osobiście opowiadam się za BDD, twoje potrzeby biznesowe mogą wymagać czegoś innego w zależności od okoliczności twojego zespołu. Kluczem jest jednak uniknięcie wtórnego zgadywania istniejącego systemu. Zawsze możesz wesprzeć swoje istniejące testy kilkoma testami wykorzystującymi inny interfejs API, jeśli to konieczne, ale z pewnością nie poleciłbym ogromnego przepisywania testów, aby wszystko było takie samo. Ponieważ przestarzały kod przestaje być używany, możesz łatwo zastąpić go i jego testy nowym kodem, a także przetestować przy użyciu alternatywnego interfejsu API, i to bez konieczności inwestowania w duży wysiłek, który niekoniecznie przyniesie rzeczywistą wartość biznesową. Jeśli chodzi o używanie interfejsu API do testowania jednostkowego,
źródło
To, co masz, jest proste i wykonuje pracę. Jeśli to działa, świetnie. Nie potrzebujesz głównego szkieletu testów jednostkowych, a ja wahałbym się zająć przeniesieniem istniejącej biblioteki testów jednostkowych do nowego szkieletu. Myślę, że największą wartością platform testowania jednostkowego jest zmniejszenie bariery wejścia; dopiero zaczynasz pisać testy, ponieważ framework jest już na miejscu. Przekroczyłeś już ten punkt, więc nie dostaniesz tej korzyści.
Inną zaletą korzystania z głównego nurtu - i jest to niewielka korzyść, IMO - jest to, że nowi programiści mogą już być na bieżąco z dowolnym używanym frameworkiem, a zatem będą wymagali mniej szkolenia. W praktyce przy prostym podejściu, takim jak to, co opisałeś, nie powinno to być wielkim problemem.
Ponadto większość platform głównego nurtu ma pewne funkcje, które może posiadać lub nie. Te funkcje zmniejszają kod hydrauliczny i przyspieszają i ułatwiają pisanie przypadków testowych:
źródło