AutoTest: Add location info to all GTest results

Currently location information are only set for failed gtest results.
One can't jump to the location of a successful test by doing a double
click on the corresponding entry in the test result pane.

Use the TestTreeModel to obtain the location information for successful
tests in the GTestOutputReader.

Change-Id: I3fad2d0540edb653ff186011cb92db220748b4f5
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Claus Steuer
2017-08-04 18:33:50 +02:00
committed by Christian Stenger
parent 285f054d74
commit 4e4118dd26
4 changed files with 99 additions and 5 deletions

View File

@@ -35,7 +35,7 @@ namespace Internal {
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi, TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
QProcess *app) const QProcess *app) const
{ {
return new GTestOutputReader(fi, app, buildDirectory()); return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
} }
QStringList GTestConfiguration::argumentsForTestRunner() const QStringList GTestConfiguration::argumentsForTestRunner() const

View File

@@ -25,6 +25,8 @@
#include "gtestoutputreader.h" #include "gtestoutputreader.h"
#include "gtestresult.h" #include "gtestresult.h"
#include "../testtreemodel.h"
#include "../testtreeitem.h"
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@@ -39,9 +41,11 @@ static QString constructSourceFilePath(const QString &path, const QString &fileP
} }
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface, GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory) QProcess *testApplication, const QString &buildDirectory,
const QString &projectFile)
: TestOutputReader(futureInterface, testApplication, buildDirectory) : TestOutputReader(futureInterface, testApplication, buildDirectory)
, m_executable(testApplication ? testApplication->program() : QString()) , m_executable(testApplication ? testApplication->program() : QString())
, m_projectFile(projectFile)
{ {
} }
@@ -94,8 +98,9 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
m_futureInterface.reportResult(TestResultPtr(testResult)); m_futureInterface.reportResult(TestResultPtr(testResult));
m_currentTestName.clear(); m_currentTestName.clear();
m_currentTestSet.clear(); m_currentTestSet.clear();
m_normalizedCurrentTestSet.clear();
} else if (newTestStarts.exactMatch(line)) { } else if (newTestStarts.exactMatch(line)) {
m_currentTestName = newTestStarts.cap(1); setCurrentTestName(newTestStarts.cap(1));
TestResultPtr testResult = TestResultPtr(createDefaultResult()); TestResultPtr testResult = TestResultPtr(createDefaultResult());
testResult->setResult(Result::MessageTestCaseStart); testResult->setResult(Result::MessageTestCaseStart);
if (m_iteration > 1) { if (m_iteration > 1) {
@@ -106,7 +111,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
} }
m_futureInterface.reportResult(testResult); m_futureInterface.reportResult(testResult);
} else if (newTestSetStarts.exactMatch(line)) { } else if (newTestSetStarts.exactMatch(line)) {
m_currentTestSet = newTestSetStarts.cap(1); setCurrentTestSet(newTestSetStarts.cap(1));
TestResultPtr testResult = TestResultPtr(new GTestResult); TestResultPtr testResult = TestResultPtr(new GTestResult);
testResult->setResult(Result::MessageCurrentTest); testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet)); testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet));
@@ -155,13 +160,87 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
} }
} }
void GTestOutputReader::setCurrentTestSet(const QString &testSet)
{
m_currentTestSet = testSet;
m_normalizedCurrentTestSet = normalizeName(testSet);
}
void GTestOutputReader::setCurrentTestName(const QString &testName)
{
m_currentTestName = testName;
m_normalizedTestName = normalizeTestName(testName);
}
QString GTestOutputReader::normalizeName(const QString &name) const
{
static QRegExp parameterIndex("/\\d+");
QString nameWithoutParameterIndices = name;
nameWithoutParameterIndices.remove(parameterIndex);
return nameWithoutParameterIndices.split('/').last();
}
QString GTestOutputReader::normalizeTestName(const QString &testname) const
{
QString nameWithoutTypeParam = testname.split(',').first();
return normalizeName(nameWithoutTypeParam);
}
GTestResult *GTestOutputReader::createDefaultResult() const GTestResult *GTestOutputReader::createDefaultResult() const
{ {
GTestResult *result = new GTestResult(m_executable, m_currentTestName); GTestResult *result = new GTestResult(m_executable, m_currentTestName);
result->setTestSetName(m_currentTestSet); result->setTestSetName(m_currentTestSet);
result->setIteration(m_iteration); result->setIteration(m_iteration);
const TestTreeItem *testItem = findTestTreeItemForCurrentLine();
if (testItem && testItem->line()) {
result->setFileName(testItem->filePath());
result->setLine(static_cast<int>(testItem->line()));
}
return result; return result;
} }
const TestTreeItem *GTestOutputReader::findTestTreeItemForCurrentLine() const
{
const auto item = TestTreeModel::instance()->findNonRooItem([&](const Utils::TreeItem *item) {
const TestTreeItem &treeItem = static_cast<const TestTreeItem &>(*item);
return matches(treeItem);
});
return static_cast<const TestTreeItem *>(item);
}
bool GTestOutputReader::matches(const TestTreeItem &treeItem) const
{
if (treeItem.proFile() != m_projectFile)
return false;
if (m_currentTestSet.isEmpty())
return matchesTestCase(treeItem);
return matchesTestFunctionOrSet(treeItem);
}
bool GTestOutputReader::matchesTestFunctionOrSet(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestFunctionOrSet)
return false;
const QString testItemTestSet = treeItem.parentItem()->name() + '.' + treeItem.name();
return testItemTestSet == m_normalizedCurrentTestSet;
}
bool GTestOutputReader::matchesTestCase(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestCase)
return false;
return treeItem.name() == m_normalizedTestName;
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -33,6 +33,7 @@ namespace Autotest {
namespace Internal { namespace Internal {
class GTestResult; class GTestResult;
class TestTreeItem;
class GTestOutputReader : public TestOutputReader class GTestOutputReader : public TestOutputReader
{ {
@@ -40,16 +41,29 @@ class GTestOutputReader : public TestOutputReader
public: public:
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface, GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory); QProcess *testApplication, const QString &buildDirectory,
const QString &projectFile);
protected: protected:
void processOutput(const QByteArray &outputLine) override; void processOutput(const QByteArray &outputLine) override;
private: private:
void setCurrentTestSet(const QString &testSet);
void setCurrentTestName(const QString &testName);
QString normalizeName(const QString &name) const;
QString normalizeTestName(const QString &testname) const;
GTestResult *createDefaultResult() const; GTestResult *createDefaultResult() const;
const TestTreeItem *findTestTreeItemForCurrentLine() const;
bool matches(const TestTreeItem &treeItem) const;
bool matchesTestFunctionOrSet(const TestTreeItem &treeItem) const;
bool matchesTestCase(const TestTreeItem &treeItem) const;
QString m_executable; QString m_executable;
QString m_projectFile;
QString m_currentTestName; QString m_currentTestName;
QString m_normalizedTestName;
QString m_currentTestSet; QString m_currentTestSet;
QString m_normalizedCurrentTestSet;
QString m_description; QString m_description;
int m_iteration = 1; int m_iteration = 1;
}; };

View File

@@ -73,6 +73,7 @@ public:
QString executableFilePath() const; QString executableFilePath() const;
QString workingDirectory() const; QString workingDirectory() const;
QString buildDirectory() const { return m_buildDir; } QString buildDirectory() const { return m_buildDir; }
QString projectFile() const { return m_projectFile; }
QString displayName() const { return m_displayName; } QString displayName() const { return m_displayName; }
Utils::Environment environment() const { return m_environment; } Utils::Environment environment() const { return m_environment; }
ProjectExplorer::Project *project() const { return m_project.data(); } ProjectExplorer::Project *project() const { return m_project.data(); }