Do tej pory używałem prowizorycznej procedury testowania jednostkowego - w zasadzie cały ładunek programów testów jednostkowych jest uruchamiany automatycznie przez plik wsadowy. Chociaż wiele z nich wyraźnie sprawdza ich wyniki, o wiele więcej oszustów - zrzucają wyniki do plików tekstowych, które są wersjonowane. Każda zmiana w wynikach testu zostanie oznaczona przez subversion i mogę łatwo określić, jaka była zmiana. Wiele testów wyprowadza pliki kropek lub inną formę, która pozwala uzyskać wizualną reprezentację wyników.Jak dostosować testy jednostek do cmake i ctest?
Problem polega na tym, że przełączam się na używanie cmake. Idąc z przepływem cmake, korzystamy z kompilacji out-of-source, co oznacza, że wygoda zrzucania wyników kończy się we współdzielonym folderze source/build, a ich wersjonowanie wraz ze źródłem nie działa.
Jako zamiennik, chciałbym zrobić to, aby , jak, było powiedzenie narzędziu do testowania urządzenia, gdzie znaleźć pliki oczekiwanych wyników (w drzewie źródłowym) i poprosić o wykonanie porównania. W przypadku niepowodzenia powinien dostarczyć rzeczywiste wyniki i listy różnic.
Czy to możliwe, czy też powinienem przyjąć zupełnie inne podejście?
Oczywiście, mogę może zignorować ctest i po prostu dostosować to, co zawsze robiłem do kompilacji poza źródłem. Mógłbym, na przykład, wyposażyć mój folder-where-all-the-builds-live (z liberalnym użyciem "ignore" oczywiście). Czy to jest przy zdrowych zmysłach? Prawdopodobnie nie, ponieważ każda kompilacja kończy się oddzielną kopią oczekiwanych wyników.
Przedstawiono również porady dotyczące zalecanego sposobu przeprowadzania testów jednostkowych za pomocą cmake/ctest wdzięczności. Zminake zmarnowałem sporo czasu, nie dlatego, że jest źle, ale dlatego, że nie rozumiałem, jak najlepiej z nim pracować.
EDIT
W końcu postanowiłem zachować cmake/ctest bok testów jednostkowych jak najprostsze. Aby przetestować rzeczywisty przeciwko oczekiwanych rezultatów, znalazłem dom dla następujących funkcji w mojej bibliotece ...
bool Check_Results (std::ostream &p_Stream ,
const char *p_Title ,
const char **p_Expected,
const std::ostringstream &p_Actual )
{
std::ostringstream l_Expected_Stream;
while (*p_Expected != 0)
{
l_Expected_Stream << (*p_Expected) << std::endl;
p_Expected++;
}
std::string l_Expected (l_Expected_Stream.str());
std::string l_Actual (p_Actual.str());
bool l_Pass = (l_Actual == l_Expected);
p_Stream << "Test: " << p_Title << " : ";
if (l_Pass)
{
p_Stream << "Pass" << std::endl;
}
else
{
p_Stream << "*** FAIL ***" << std::endl;
p_Stream << "===============================================================================" << std::endl;
p_Stream << "Expected Results For: " << p_Title << std::endl;
p_Stream << "-------------------------------------------------------------------------------" << std::endl;
p_Stream << l_Expected;
p_Stream << "===============================================================================" << std::endl;
p_Stream << "Actual Results For: " << p_Title << std::endl;
p_Stream << "-------------------------------------------------------------------------------" << std::endl;
p_Stream << l_Actual;
p_Stream << "===============================================================================" << std::endl;
}
return l_Pass;
}
Typowy test jednostka teraz wygląda mniej więcej tak ...
bool Test0001()
{
std::ostringstream l_Actual;
const char* l_Expected [] =
{
"Some",
"Expected",
"Results",
0
};
l_Actual << "Some" << std::endl
<< "Actual" << std::endl
<< "Results" << std::endl;
return Check_Results (std::cout, "0001 - not a sane test", l_Expected, l_Actual);
}
Gdzie muszę wielokrotnego użytku funkcja przesypywania danych, przyjmuje parametr typu std::ostream&
, dzięki czemu może zrzucić do strumienia rzeczywistych wyników.
Powinieneś dodać swoją edycję jako odpowiedź, ponieważ odpowiada ona na twoje własne pytanie – Joakim