AutoTest: Create tree item for each failure

Introduce special location item for this purpose.

Task-number: QTCREATORBUG-20967
Change-Id: Icb6c6ec8ff9d2e4e8e3d13834427bae50d74bd2a
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Sergey Morozov
2018-08-18 21:48:34 +03:00
parent fa4693fd29
commit db85693690
6 changed files with 40 additions and 17 deletions

View File

@@ -144,7 +144,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
TestResultPtr testResult = createDefaultResult(); TestResultPtr testResult = createDefaultResult();
testResult->setResult(Result::Fail); testResult->setResult(Result::Fail);
m_description.chop(1); m_description.chop(1);
testResult->setDescription(m_description); QStringList resultDescription;
for (const QString &output : m_description.split('\n')) { for (const QString &output : m_description.split('\n')) {
QRegExp *match = nullptr; QRegExp *match = nullptr;
@@ -152,17 +152,23 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
match = &failureLocation; match = &failureLocation;
else if (errorLocation.exactMatch(output)) else if (errorLocation.exactMatch(output))
match = &errorLocation; match = &errorLocation;
if (!match) {
resultDescription << output;
continue;
}
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult);
resultDescription.clear();
if (match) { testResult = createDefaultResult();
testResult->setResult(Result::MessageLocation);
testResult->setLine(match->cap(2).toInt()); testResult->setLine(match->cap(2).toInt());
QString file = constructSourceFilePath(m_buildDir, match->cap(1)); QString file = constructSourceFilePath(m_buildDir, match->cap(1));
if (!file.isEmpty()) if (!file.isEmpty())
testResult->setFileName(file); testResult->setFileName(file);
resultDescription << output;
break;
}
} }
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult); reportResult(testResult);
m_description.clear(); m_description.clear();
testResult = createDefaultResult(); testResult = createDefaultResult();

View File

@@ -69,8 +69,11 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
return false; return false;
const GTestResult *gtOther = static_cast<const GTestResult *>(other); const GTestResult *gtOther = static_cast<const GTestResult *>(other);
if (m_testSetName == gtOther->m_testSetName && other->result() == Result::MessageInternal) if (m_testSetName == gtOther->m_testSetName) {
return true; const Result::Type otherResult = other->result();
if (otherResult == Result::MessageInternal || otherResult == Result::MessageLocation)
return result() != Result::MessageLocation;
}
if (m_iteration != gtOther->m_iteration) if (m_iteration != gtOther->m_iteration)
return false; return false;
return isTest() && gtOther->isTestSet(); return isTest() && gtOther->isTestSet();

View File

@@ -136,6 +136,8 @@ QString TestResult::resultToString(const Result::Type type)
return QString("BPASS"); return QString("BPASS");
case Result::BlacklistedFail: case Result::BlacklistedFail:
return QString("BFAIL"); return QString("BFAIL");
case Result::MessageLocation:
return QString();
default: default:
if (type >= Result::INTERNAL_MESSAGES_BEGIN && type <= Result::INTERNAL_MESSAGES_END) if (type >= Result::INTERNAL_MESSAGES_BEGIN && type <= Result::INTERNAL_MESSAGES_END)
return QString(); return QString();

View File

@@ -52,6 +52,7 @@ enum Type {
MessageWarn, MessageWarn,
MessageFatal, MessageFatal,
MessageSystem, MessageSystem,
MessageLocation,
MessageInternal, INTERNAL_MESSAGES_BEGIN = MessageInternal, MessageInternal, INTERNAL_MESSAGES_BEGIN = MessageInternal,
MessageDisabledTests, MessageDisabledTests,

View File

@@ -57,6 +57,7 @@ static QIcon testResultIcon(Result::Type result) {
Icons::RESULT_MESSAGEWARN.icon(), Icons::RESULT_MESSAGEWARN.icon(),
Icons::RESULT_MESSAGEFATAL.icon(), Icons::RESULT_MESSAGEFATAL.icon(),
Icons::RESULT_MESSAGEFATAL.icon(), // System gets same handling as Fatal for now Icons::RESULT_MESSAGEFATAL.icon(), // System gets same handling as Fatal for now
QIcon(),
Icons::RESULT_MESSAGEPASSWARN.icon(), Icons::RESULT_MESSAGEPASSWARN.icon(),
Icons::RESULT_MESSAGEFAILWARN.icon(), Icons::RESULT_MESSAGEFAILWARN.icon(),
}; // provide an icon for unknown?? }; // provide an icon for unknown??
@@ -81,8 +82,14 @@ static QIcon testResultIcon(Result::Type result) {
QVariant TestResultItem::data(int column, int role) const QVariant TestResultItem::data(int column, int role) const
{ {
switch (role) { switch (role) {
case Qt::DecorationRole: case Qt::DecorationRole: {
return m_testResult ? testResultIcon(m_testResult->result()) : QVariant(); if (!m_testResult)
return QVariant();
const Result::Type result = m_testResult->result();
if (result == Result::MessageLocation && parent())
return parent()->data(column, role);
return testResultIcon(result);
}
case Qt::DisplayRole: case Qt::DisplayRole:
return m_testResult ? m_testResult->outputString(true) : QVariant(); return m_testResult ? m_testResult->outputString(true) : QVariant();
default: default:
@@ -354,7 +361,7 @@ void TestResultFilterModel::enableAllResultTypes()
{ {
m_enabled << Result::Pass << Result::Fail << Result::ExpectedFail m_enabled << Result::Pass << Result::Fail << Result::ExpectedFail
<< Result::UnexpectedPass << Result::Skip << Result::MessageDebug << Result::UnexpectedPass << Result::Skip << Result::MessageDebug
<< Result::MessageWarn << Result::MessageInternal << Result::MessageWarn << Result::MessageInternal << Result::MessageLocation
<< Result::MessageFatal << Result::Invalid << Result::BlacklistedPass << Result::MessageFatal << Result::Invalid << Result::BlacklistedPass
<< Result::BlacklistedFail << Result::Benchmark << Result::MessageIntermediate << Result::BlacklistedFail << Result::Benchmark << Result::MessageIntermediate
<< Result::MessageCurrentTest << Result::MessageTestCaseStart << Result::MessageCurrentTest << Result::MessageTestCaseStart

View File

@@ -637,6 +637,9 @@ QString TestResultsPane::getWholeOutput(const QModelIndex &parent)
void TestResultsPane::createMarks(const QModelIndex &parent) void TestResultsPane::createMarks(const QModelIndex &parent)
{ {
const TestResult *parentResult = m_model->testResult(parent);
Result::Type parentType = parentResult ? parentResult->result() : Result::Invalid;
const QVector<Result::Type> interested{Result::Fail, Result::UnexpectedPass};
for (int row = 0, count = m_model->rowCount(parent); row < count; ++row) { for (int row = 0, count = m_model->rowCount(parent); row < count; ++row) {
const QModelIndex index = m_model->index(row, 0, parent); const QModelIndex index = m_model->index(row, 0, parent);
const TestResult *result = m_model->testResult(index); const TestResult *result = m_model->testResult(index);
@@ -645,8 +648,9 @@ void TestResultsPane::createMarks(const QModelIndex &parent)
if (m_model->hasChildren(index)) if (m_model->hasChildren(index))
createMarks(index); createMarks(index);
const QVector<Result::Type> interested{Result::Fail, Result::UnexpectedPass}; bool isLocationItem = result->result() == Result::MessageLocation;
if (interested.contains(result->result())) { if (interested.contains(result->result())
|| (isLocationItem && interested.contains(parentType))) {
const Utils::FileName fileName = Utils::FileName::fromString(result->fileName()); const Utils::FileName fileName = Utils::FileName::fromString(result->fileName());
TestEditorMark *mark = new TestEditorMark(index, fileName, result->line()); TestEditorMark *mark = new TestEditorMark(index, fileName, result->line());
mark->setIcon(index.data(Qt::DecorationRole).value<QIcon>()); mark->setIcon(index.data(Qt::DecorationRole).value<QIcon>());