CTest: Add colored output on tests summary where supported

- Number of passed/failed tests is colored according to the whole outcome
- Individual listed tested are colored according to their completion status:
  * Disabled: blue
  * Failed: red
  * Not Run: yellow
This commit is contained in:
Sylvain Joubert
2018-11-07 16:33:28 +01:00
parent 48bc74710d
commit ffdec37a19
4 changed files with 92 additions and 16 deletions

View File

@@ -535,11 +535,21 @@ int cmCTestTestHandler::ProcessHandler()
percent = 99; percent = 99;
} }
std::string passColorCode;
std::string failedColorCode;
if (failed.empty()) {
passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN);
} else {
failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED);
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, cmCTestLog(this->CTest, HANDLER_OUTPUT,
std::endl std::endl
<< static_cast<int>(percent + .5f) << "% tests passed, " << passColorCode << static_cast<int>(percent + .5f)
<< failed.size() << " tests failed out of " << total << "% tests passed"
<< std::endl); << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
<< ", " << failedColorCode << failed.size() << " tests failed"
<< this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
<< " out of " << total << std::endl);
if ((!this->CTest->GetLabelsForSubprojects().empty() && if ((!this->CTest->GetLabelsForSubprojects().empty() &&
this->CTest->GetSubprojectSummary())) { this->CTest->GetSubprojectSummary())) {
this->PrintLabelOrSubprojectSummary(true); this->PrintLabelOrSubprojectSummary(true);
@@ -562,6 +572,8 @@ int cmCTestTestHandler::ProcessHandler()
this->StartLogFile("TestsDisabled", ofs); this->StartLogFile("TestsDisabled", ofs);
const char* disabled_reason; const char* disabled_reason;
cmCTestLog(this->CTest, HANDLER_OUTPUT,
this->CTest->GetColorCode(cmCTest::Color::BLUE));
for (cmCTestTestResult const& dt : disabledTests) { for (cmCTestTestResult const& dt : disabledTests) {
ofs << dt.TestCount << ":" << dt.Name << std::endl; ofs << dt.TestCount << ":" << dt.Name << std::endl;
if (dt.CompletionStatus == "Disabled") { if (dt.CompletionStatus == "Disabled") {
@@ -573,6 +585,8 @@ int cmCTestTestHandler::ProcessHandler()
"\t" << std::setw(3) << dt.TestCount << " - " << dt.Name "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name
<< " (" << disabled_reason << ")" << std::endl); << " (" << disabled_reason << ")" << std::endl);
} }
cmCTestLog(this->CTest, HANDLER_OUTPUT,
this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR));
} }
if (!failed.empty()) { if (!failed.empty()) {
@@ -587,10 +601,17 @@ int cmCTestTestHandler::ProcessHandler()
!cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") && !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") &&
ft.CompletionStatus != "Disabled") { ft.CompletionStatus != "Disabled") {
ofs << ft.TestCount << ":" << ft.Name << std::endl; ofs << ft.TestCount << ":" << ft.Name << std::endl;
cmCTestLog(this->CTest, HANDLER_OUTPUT, auto testColor = cmCTest::Color::RED;
"\t" << std::setw(3) << ft.TestCount << " - " << ft.Name if (this->GetTestStatus(ft) == "Not Run") {
<< " (" << this->GetTestStatus(ft) << ")" testColor = cmCTest::Color::YELLOW;
<< std::endl); }
cmCTestLog(
this->CTest, HANDLER_OUTPUT,
"\t" << this->CTest->GetColorCode(testColor) << std::setw(3)
<< ft.TestCount << " - " << ft.Name << " ("
<< this->GetTestStatus(ft) << ")"
<< this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
<< std::endl);
} }
} }
} }
@@ -1725,7 +1746,7 @@ void cmCTestTestHandler::UseExcludeRegExp()
this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag; this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag;
} }
const char* cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result) std::string cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result)
{ {
static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT", static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT",
"ILLEGAL", "INTERRUPT", "NUMERICAL", "ILLEGAL", "INTERRUPT", "NUMERICAL",
@@ -1737,7 +1758,7 @@ const char* cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result)
return "No Status"; return "No Status";
} }
if (status == cmCTestTestHandler::OTHER_FAULT) { if (status == cmCTestTestHandler::OTHER_FAULT) {
return result.ExceptionStatus.c_str(); return result.ExceptionStatus;
} }
return statuses[status]; return statuses[status];
} }

View File

@@ -274,7 +274,7 @@ private:
*/ */
std::string FindTheExecutable(const char* exe); std::string FindTheExecutable(const char* exe);
const char* GetTestStatus(cmCTestTestResult const&); std::string GetTestStatus(cmCTestTestResult const&);
void ExpandTestsToRunInformation(size_t numPossibleTests); void ExpandTestsToRunInformation(size_t numPossibleTests);
void ExpandTestsToRunInformationForRerunFailed(); void ExpandTestsToRunInformationForRerunFailed();

View File

@@ -296,6 +296,7 @@ cmCTest::cmCTest()
this->DropSiteCDash = false; this->DropSiteCDash = false;
this->BuildID = ""; this->BuildID = "";
this->OutputTestOutputOnTestFailure = false; this->OutputTestOutputOnTestFailure = false;
this->OutputColorCode = this->ColoredOutputSupportedByConsole();
this->RepeatTests = 1; // default to run each test once this->RepeatTests = 1; // default to run each test once
this->RepeatUntilFail = false; this->RepeatUntilFail = false;
@@ -2075,7 +2076,18 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
return true; return true;
} }
bool cmCTest::ProgressOutputSupportedByConsole() const #if !defined(_WIN32)
bool cmCTest::ConsoleIsNotDumb()
{
std::string term_env_variable;
if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
return isatty(1) && term_env_variable != "dumb";
}
return false;
}
#endif
bool cmCTest::ProgressOutputSupportedByConsole()
{ {
#if defined(_WIN32) #if defined(_WIN32)
// On Windows we need a console buffer. // On Windows we need a console buffer.
@@ -2084,12 +2096,19 @@ bool cmCTest::ProgressOutputSupportedByConsole() const
return GetConsoleScreenBufferInfo(console, &csbi); return GetConsoleScreenBufferInfo(console, &csbi);
#else #else
// On UNIX we need a non-dumb tty. // On UNIX we need a non-dumb tty.
std::string term_env_variable; return ConsoleIsNotDumb();
if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
return isatty(1) && term_env_variable != "dumb";
}
#endif #endif
}
bool cmCTest::ColoredOutputSupportedByConsole()
{
#if defined(_WIN32)
// Not supported on Windows
return false; return false;
#else
// On UNIX we need a non-dumb tty.
return ConsoleIsNotDumb();
#endif
} }
// handle the -S -SR and -SP arguments // handle the -S -SR and -SP arguments
@@ -2958,6 +2977,20 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
} }
} }
std::string cmCTest::GetColorCode(Color color) const
{
if (this->OutputColorCode) {
#if defined(_WIN32)
// Not supported on Windows
static_cast<void>(color);
#else
return "\033[0;" + std::to_string(static_cast<int>(color)) + "m";
#endif
}
return "";
}
cmDuration cmCTest::GetRemainingTimeAllowed() cmDuration cmCTest::GetRemainingTimeAllowed()
{ {
if (!this->GetHandler("script")) { if (!this->GetHandler("script")) {

View File

@@ -405,6 +405,19 @@ public:
void Log(int logType, const char* file, int line, const char* msg, void Log(int logType, const char* file, int line, const char* msg,
bool suppress = false); bool suppress = false);
/** Color values */
enum class Color
{
CLEAR_COLOR = 0,
RED = 31,
GREEN = 32,
YELLOW = 33,
BLUE = 34
};
/** Get color code characters for a specific color */
std::string GetColorCode(Color color) const;
/** Get the version of dart server */ /** Get the version of dart server */
int GetDartVersion() { return this->DartVersion; } int GetDartVersion() { return this->DartVersion; }
int GetDropSiteCDash() { return this->DropSiteCDash; } int GetDropSiteCDash() { return this->DropSiteCDash; }
@@ -575,8 +588,16 @@ private:
bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args, bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
std::string& errormsg); std::string& errormsg);
#if !defined(_WIN32)
/** returns true iff the console supports progress output */ /** returns true iff the console supports progress output */
bool ProgressOutputSupportedByConsole() const; static bool ConsoleIsNotDumb();
#endif
/** returns true iff the console supports progress output */
static bool ProgressOutputSupportedByConsole();
/** returns true iff the console supports colored output */
static bool ColoredOutputSupportedByConsole();
/** handle the -S -SP and -SR arguments */ /** handle the -S -SP and -SR arguments */
void HandleScriptArguments(size_t& i, std::vector<std::string>& args, void HandleScriptArguments(size_t& i, std::vector<std::string>& args,
@@ -625,6 +646,7 @@ private:
int OutputLogFileLastTag; int OutputLogFileLastTag;
bool OutputTestOutputOnTestFailure; bool OutputTestOutputOnTestFailure;
bool OutputColorCode;
std::map<std::string, std::string> Definitions; std::map<std::string, std::string> Definitions;
}; };