forked from qt-creator/qt-creator
Use QC's TreeModel for TestResultModel
This changes the model to be a real tree instead of a list. Additionally the results pane now displays the results as tree as well. Change-Id: I69ba7bbfcd75ce17c3a0d4052498d9c1c7382d43 Reviewed-by: Niels Weber <niels.weber@theqtcompany.com>
This commit is contained in:
@@ -91,6 +91,16 @@ Result::Type TestResult::toResultType(int rt)
|
||||
return Result::MESSAGE_FATAL;
|
||||
case Result::MESSAGE_INTERNAL:
|
||||
return Result::MESSAGE_INTERNAL;
|
||||
case Result::MESSAGE_TEST_CASE_START:
|
||||
return Result::MESSAGE_TEST_CASE_START;
|
||||
case Result::MESSAGE_TEST_CASE_SUCCESS:
|
||||
return Result::MESSAGE_TEST_CASE_SUCCESS;
|
||||
case Result::MESSAGE_TEST_CASE_WARN:
|
||||
return Result::MESSAGE_TEST_CASE_WARN;
|
||||
case Result::MESSAGE_TEST_CASE_FAIL:
|
||||
return Result::MESSAGE_TEST_CASE_FAIL;
|
||||
case Result::MESSAGE_TEST_CASE_END:
|
||||
return Result::MESSAGE_TEST_CASE_END;
|
||||
case Result::MESSAGE_CURRENT_TEST:
|
||||
return Result::MESSAGE_CURRENT_TEST;
|
||||
default:
|
||||
@@ -120,6 +130,11 @@ QString TestResult::resultToString(const Result::Type type)
|
||||
case Result::MESSAGE_FATAL:
|
||||
return QLatin1String("FATAL");
|
||||
case Result::MESSAGE_INTERNAL:
|
||||
case Result::MESSAGE_TEST_CASE_START:
|
||||
case Result::MESSAGE_TEST_CASE_SUCCESS:
|
||||
case Result::MESSAGE_TEST_CASE_WARN:
|
||||
case Result::MESSAGE_TEST_CASE_FAIL:
|
||||
case Result::MESSAGE_TEST_CASE_END:
|
||||
case Result::MESSAGE_CURRENT_TEST:
|
||||
return QString();
|
||||
case Result::BLACKLISTED_PASS:
|
||||
@@ -155,6 +170,11 @@ QColor TestResult::colorForType(const Result::Type type)
|
||||
case Result::MESSAGE_FATAL:
|
||||
return QColor("#640000");
|
||||
case Result::MESSAGE_INTERNAL:
|
||||
case Result::MESSAGE_TEST_CASE_START:
|
||||
case Result::MESSAGE_TEST_CASE_SUCCESS:
|
||||
case Result::MESSAGE_TEST_CASE_WARN:
|
||||
case Result::MESSAGE_TEST_CASE_FAIL:
|
||||
case Result::MESSAGE_TEST_CASE_END:
|
||||
case Result::MESSAGE_CURRENT_TEST:
|
||||
return QColor("transparent");
|
||||
default:
|
||||
|
||||
@@ -41,6 +41,11 @@ enum Type {
|
||||
MESSAGE_WARN,
|
||||
MESSAGE_FATAL,
|
||||
MESSAGE_INTERNAL,
|
||||
MESSAGE_TEST_CASE_START,
|
||||
MESSAGE_TEST_CASE_SUCCESS,
|
||||
MESSAGE_TEST_CASE_WARN,
|
||||
MESSAGE_TEST_CASE_FAIL,
|
||||
MESSAGE_TEST_CASE_END,
|
||||
MESSAGE_CURRENT_TEST,
|
||||
UNKNOWN // ???
|
||||
};
|
||||
@@ -65,6 +70,7 @@ public:
|
||||
void setDescription(const QString &description) { m_description = description; }
|
||||
void setFileName(const QString &fileName) { m_file = fileName; }
|
||||
void setLine(int line) { m_line = line; }
|
||||
void setResult(Result::Type type) { m_result = type; }
|
||||
|
||||
static Result::Type resultFromString(const QString &resultString);
|
||||
static Result::Type toResultType(int rt);
|
||||
|
||||
@@ -37,11 +37,6 @@ TestResultDelegate::TestResultDelegate(QObject *parent)
|
||||
{
|
||||
}
|
||||
|
||||
TestResultDelegate::~TestResultDelegate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString TestResultDelegate::outputString(const TestResult &testResult, bool selected)
|
||||
{
|
||||
const QString desc = testResult.description();
|
||||
@@ -88,7 +83,6 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
||||
painter->save();
|
||||
|
||||
QFontMetrics fm(opt.font);
|
||||
QColor background;
|
||||
QColor foreground;
|
||||
|
||||
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(opt.widget);
|
||||
@@ -96,22 +90,23 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
||||
|
||||
if (selected) {
|
||||
painter->setBrush(opt.palette.highlight().color());
|
||||
background = opt.palette.highlight().color();
|
||||
foreground = opt.palette.highlightedText().color();
|
||||
} else {
|
||||
painter->setBrush(opt.palette.background().color());
|
||||
background = opt.palette.background().color();
|
||||
foreground = opt.palette.text().color();
|
||||
}
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRect(opt.rect);
|
||||
|
||||
painter->setPen(foreground);
|
||||
|
||||
TestResultFilterModel *resultFilterModel = static_cast<TestResultFilterModel *>(view->model());
|
||||
TestResultModel *resultModel = static_cast<TestResultModel *>(resultFilterModel->sourceModel());
|
||||
LayoutPositions positions(opt, resultModel);
|
||||
TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index));
|
||||
LayoutPositions positions(opt, resultFilterModel);
|
||||
const TestResult &testResult = resultFilterModel->testResult(index);
|
||||
|
||||
// draw the indicator by ourself as we paint across it with the delegate
|
||||
QStyleOptionViewItemV4 indicatorOpt = option;
|
||||
indicatorOpt.rect = QRect(0, opt.rect.y(), positions.indentation(), opt.rect.height());
|
||||
opt.widget->style()->drawPrimitive(QStyle::PE_IndicatorBranch, &indicatorOpt, painter);
|
||||
|
||||
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>();
|
||||
if (!icon.isNull())
|
||||
@@ -163,7 +158,7 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
||||
}
|
||||
|
||||
painter->setClipRect(opt.rect);
|
||||
painter->setPen(QColor::fromRgb(150, 150, 150));
|
||||
painter->setPen(opt.palette.midlight().color());
|
||||
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
|
||||
painter->restore();
|
||||
}
|
||||
@@ -181,13 +176,12 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
|
||||
QFontMetrics fm(opt.font);
|
||||
int fontHeight = fm.height();
|
||||
TestResultFilterModel *resultFilterModel = static_cast<TestResultFilterModel *>(view->model());
|
||||
TestResultModel *resultModel = static_cast<TestResultModel *>(resultFilterModel->sourceModel());
|
||||
LayoutPositions positions(opt, resultModel);
|
||||
LayoutPositions positions(opt, resultFilterModel);
|
||||
QSize s;
|
||||
s.setWidth(opt.rect.width());
|
||||
|
||||
if (selected) {
|
||||
TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index));
|
||||
const TestResult &testResult = resultFilterModel->testResult(index);
|
||||
|
||||
QString output = outputString(testResult, selected);
|
||||
output.replace(QLatin1Char('\n'), QChar::LineSeparator);
|
||||
|
||||
@@ -33,7 +33,6 @@ class TestResultDelegate : public QStyledItemDelegate
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestResultDelegate(QObject *parent = 0);
|
||||
~TestResultDelegate();
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
@@ -55,15 +54,19 @@ private:
|
||||
class LayoutPositions
|
||||
{
|
||||
public:
|
||||
LayoutPositions(QStyleOptionViewItemV4 &options, TestResultModel *model)
|
||||
LayoutPositions(QStyleOptionViewItemV4 &options, TestResultFilterModel *filterModel)
|
||||
: m_totalWidth(options.rect.width()),
|
||||
m_maxFileLength(model->maxWidthOfFileName(options.font)),
|
||||
m_maxLineLength(model->maxWidthOfLineNumber(options.font)),
|
||||
m_realFileLength(m_maxFileLength),
|
||||
m_top(options.rect.top()),
|
||||
m_bottom(options.rect.bottom())
|
||||
{
|
||||
TestResultModel *srcModel = static_cast<TestResultModel *>(filterModel->sourceModel());
|
||||
m_maxFileLength = srcModel->maxWidthOfFileName(options.font);
|
||||
m_maxLineLength = srcModel->maxWidthOfLineNumber(options.font);
|
||||
m_realFileLength = m_maxFileLength;
|
||||
m_typeAreaWidth = QFontMetrics(options.font).width(QLatin1String("XXXXXXXX"));
|
||||
m_indentation = options.widget ? options.widget->style()->pixelMetric(
|
||||
QStyle::PM_TreeViewIndentation, &options) : 0;
|
||||
m_level = srcModel->hasChildren(filterModel->mapToSource(options.index)) ? 1 : 2;
|
||||
int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING;
|
||||
if (m_maxFileLength > flexibleArea / 2)
|
||||
m_realFileLength = flexibleArea / 2;
|
||||
@@ -71,7 +74,7 @@ private:
|
||||
}
|
||||
|
||||
int top() const { return m_top + ITEM_MARGIN; }
|
||||
int left() const { return ITEM_MARGIN; }
|
||||
int left() const { return ITEM_MARGIN + m_indentation * m_level; }
|
||||
int right() const { return m_totalWidth - ITEM_MARGIN; }
|
||||
int bottom() const { return m_bottom; }
|
||||
int minimumHeight() const { return ICON_SIZE + 2 * ITEM_MARGIN; }
|
||||
@@ -80,17 +83,19 @@ private:
|
||||
int fontHeight() const { return m_fontHeight; }
|
||||
int typeAreaLeft() const { return left() + ICON_SIZE + ITEM_SPACING; }
|
||||
int typeAreaWidth() const { return m_typeAreaWidth; }
|
||||
int textAreaLeft() const { return typeAreaLeft() + m_typeAreaWidth + ITEM_SPACING; }
|
||||
int textAreaLeft() const { return typeAreaLeft() + m_typeAreaWidth + ITEM_SPACING
|
||||
+ (1 - m_level) * m_indentation; }
|
||||
int textAreaWidth() const { return fileAreaLeft() - ITEM_SPACING - textAreaLeft(); }
|
||||
int fileAreaLeft() const { return lineAreaLeft() - ITEM_SPACING - m_realFileLength; }
|
||||
int lineAreaLeft() const { return right() - m_maxLineLength; }
|
||||
int indentation() const { return m_indentation; }
|
||||
|
||||
QRect typeArea() const { return QRect(typeAreaLeft(), top(),
|
||||
typeAreaWidth(), m_fontHeight); }
|
||||
QRect textArea() const { return QRect(textAreaLeft(), top(),
|
||||
fileAreaLeft() - ITEM_SPACING, m_fontHeight); }
|
||||
textAreaWidth(), m_fontHeight); }
|
||||
QRect fileArea() const { return QRect(fileAreaLeft(), top(),
|
||||
lineAreaLeft() - ITEM_SPACING, m_fontHeight); }
|
||||
m_realFileLength + ITEM_SPACING, m_fontHeight); }
|
||||
|
||||
QRect lineArea() const { return QRect(lineAreaLeft(), top(),
|
||||
m_maxLineLength, m_fontHeight); }
|
||||
@@ -104,6 +109,8 @@ private:
|
||||
int m_bottom;
|
||||
int m_fontHeight;
|
||||
int m_typeAreaWidth;
|
||||
int m_level;
|
||||
int m_indentation;
|
||||
|
||||
static const int ICON_SIZE = 16;
|
||||
static const int ITEM_MARGIN = 2;
|
||||
|
||||
@@ -19,47 +19,22 @@
|
||||
|
||||
#include "testresultmodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFontMetrics>
|
||||
#include <QIcon>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
namespace Autotest {
|
||||
namespace Internal {
|
||||
|
||||
TestResultModel::TestResultModel(QObject *parent) :
|
||||
QAbstractItemModel(parent),
|
||||
m_widthOfLineNumber(0),
|
||||
m_maxWidthOfFileName(0),
|
||||
m_lastMaxWidthIndex(0)
|
||||
/********************************* TestResultItem ******************************************/
|
||||
|
||||
TestResultItem::TestResultItem(TestResult *testResult)
|
||||
: m_testResult(testResult)
|
||||
{
|
||||
}
|
||||
|
||||
TestResultModel::~TestResultModel()
|
||||
TestResultItem::~TestResultItem()
|
||||
{
|
||||
m_testResults.clear();
|
||||
}
|
||||
|
||||
QModelIndex TestResultModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return QModelIndex();
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
QModelIndex TestResultModel::parent(const QModelIndex &) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int TestResultModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_testResults.size();
|
||||
}
|
||||
|
||||
int TestResultModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 1;
|
||||
delete m_testResult;
|
||||
}
|
||||
|
||||
static QIcon testResultIcon(Result::Type result) {
|
||||
@@ -77,116 +52,201 @@ static QIcon testResultIcon(Result::Type result) {
|
||||
QIcon(QLatin1String(":/images/fatal.png")),
|
||||
}; // provide an icon for unknown??
|
||||
|
||||
if (result < 0 || result >= Result::MESSAGE_INTERNAL)
|
||||
if (result < 0 || result >= Result::MESSAGE_INTERNAL) {
|
||||
switch (result) {
|
||||
case Result::MESSAGE_TEST_CASE_SUCCESS:
|
||||
return icons[Result::PASS];
|
||||
case Result::MESSAGE_TEST_CASE_FAIL:
|
||||
return icons[Result::FAIL];
|
||||
case Result::MESSAGE_TEST_CASE_WARN:
|
||||
return icons[Result::MESSAGE_WARN];
|
||||
default:
|
||||
return QIcon();
|
||||
}
|
||||
}
|
||||
return icons[result];
|
||||
}
|
||||
|
||||
QVariant TestResultModel::data(const QModelIndex &index, int role) const
|
||||
QVariant TestResultItem::data(int column, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0)
|
||||
return QVariant();
|
||||
if (role == Qt::DisplayRole) {
|
||||
const TestResult &tr = m_testResults.at(index.row());
|
||||
switch (tr.result()) {
|
||||
case Result::PASS:
|
||||
if (role == Qt::DecorationRole)
|
||||
return m_testResult ? testResultIcon(m_testResult->result()) : QVariant();
|
||||
|
||||
return Utils::TreeItem::data(column, role);
|
||||
}
|
||||
|
||||
void TestResultItem::updateDescription(const QString &description)
|
||||
{
|
||||
QTC_ASSERT(m_testResult, return);
|
||||
|
||||
m_testResult->setDescription(description);
|
||||
}
|
||||
|
||||
void TestResultItem::updateResult()
|
||||
{
|
||||
if (m_testResult->result() != Result::MESSAGE_TEST_CASE_START)
|
||||
return;
|
||||
|
||||
Result::Type newResult = Result::MESSAGE_TEST_CASE_SUCCESS;
|
||||
foreach (Utils::TreeItem *child, children()) {
|
||||
const TestResult *current = static_cast<TestResultItem *>(child)->testResult();
|
||||
if (current) {
|
||||
switch (current->result()) {
|
||||
case Result::FAIL:
|
||||
case Result::EXPECTED_FAIL:
|
||||
case Result::MESSAGE_FATAL:
|
||||
case Result::UNEXPECTED_PASS:
|
||||
m_testResult->setResult(Result::MESSAGE_TEST_CASE_FAIL);
|
||||
return;
|
||||
case Result::EXPECTED_FAIL:
|
||||
case Result::MESSAGE_WARN:
|
||||
case Result::SKIP:
|
||||
case Result::BLACKLISTED_PASS:
|
||||
case Result::BLACKLISTED_FAIL:
|
||||
case Result::BENCHMARK:
|
||||
return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(),
|
||||
tr.dataTag(), tr.fileName());
|
||||
default:
|
||||
return tr.description();
|
||||
case Result::BLACKLISTED_PASS:
|
||||
newResult = Result::MESSAGE_TEST_CASE_WARN;
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
if (role == Qt::DecorationRole) {
|
||||
const TestResult &tr = m_testResults.at(index.row());
|
||||
return testResultIcon(tr.result());
|
||||
}
|
||||
m_testResult->setResult(newResult);
|
||||
}
|
||||
|
||||
/********************************* TestResultModel *****************************************/
|
||||
|
||||
TestResultModel::TestResultModel(QObject *parent)
|
||||
: Utils::TreeModel(parent),
|
||||
m_widthOfLineNumber(0),
|
||||
m_maxWidthOfFileName(0)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant TestResultModel::data(const QModelIndex &idx, int role) const
|
||||
{
|
||||
if (!idx.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
return itemForIndex(idx)->data(0, Qt::DecorationRole);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void TestResultModel::addTestResult(const TestResult &testResult)
|
||||
void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand)
|
||||
{
|
||||
const bool isCurrentTestMssg = testResult.result() == Result::MESSAGE_CURRENT_TEST;
|
||||
TestResult lastMssg = m_testResults.empty() ? TestResult() : m_testResults.last();
|
||||
|
||||
int position = m_testResults.size();
|
||||
|
||||
if (isCurrentTestMssg && lastMssg.result() == Result::MESSAGE_CURRENT_TEST) {
|
||||
lastMssg.setDescription(testResult.description());
|
||||
m_testResults.replace(m_testResults.size() - 1, lastMssg);
|
||||
const QModelIndex changed = index(m_testResults.size() - 1, 0, QModelIndex());
|
||||
emit dataChanged(changed, changed);
|
||||
} else {
|
||||
if (!isCurrentTestMssg && position) // decrement only if at least one other item
|
||||
--position;
|
||||
beginInsertRows(QModelIndex(), position, position);
|
||||
m_testResults.insert(position, testResult);
|
||||
endInsertRows();
|
||||
}
|
||||
const bool isCurrentTestMssg = testResult->result() == Result::MESSAGE_CURRENT_TEST;
|
||||
|
||||
QVector<Utils::TreeItem *> topLevelItems = rootItem()->children();
|
||||
int lastRow = topLevelItems.size() - 1;
|
||||
TestResultItem *newItem = new TestResultItem(testResult);
|
||||
// we'll add the new item, so raising it's counter
|
||||
if (!isCurrentTestMssg) {
|
||||
int count = m_testResultCount.value(testResult.result(), 0);
|
||||
m_testResultCount.insert(testResult.result(), ++count);
|
||||
int count = m_testResultCount.value(testResult->result(), 0);
|
||||
m_testResultCount.insert(testResult->result(), ++count);
|
||||
} else {
|
||||
// MESSAGE_CURRENT_TEST should always be the last top level item
|
||||
if (lastRow >= 0) {
|
||||
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(lastRow));
|
||||
const TestResult *result = current->testResult();
|
||||
if (result && result->result() == Result::MESSAGE_CURRENT_TEST) {
|
||||
current->updateDescription(testResult->description());
|
||||
emit dataChanged(current->index(), current->index());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rootItem()->appendChild(newItem);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME this might be totally wrong... we need some more unique information!
|
||||
for (int row = lastRow; row >= 0; --row) {
|
||||
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(row));
|
||||
const TestResult *result = current->testResult();
|
||||
if (result && result->className() == testResult->className()) {
|
||||
current->appendChild(newItem);
|
||||
if (autoExpand)
|
||||
current->expand();
|
||||
if (testResult->result() == Result::MESSAGE_TEST_CASE_END) {
|
||||
current->updateResult();
|
||||
emit dataChanged(current->index(), current->index());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if we have a MESSAGE_CURRENT_TEST present, add the new top level item before it
|
||||
if (lastRow >= 0) {
|
||||
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(lastRow));
|
||||
const TestResult *result = current->testResult();
|
||||
if (result && result->result() == Result::MESSAGE_CURRENT_TEST) {
|
||||
rootItem()->insertChild(current->index().row(), newItem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rootItem()->appendChild(newItem);
|
||||
}
|
||||
|
||||
void TestResultModel::removeCurrentTestMessage()
|
||||
{
|
||||
TestResult lastMssg = m_testResults.empty() ? TestResult() : m_testResults.last();
|
||||
if (lastMssg.result() == Result::MESSAGE_CURRENT_TEST) {
|
||||
beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1);
|
||||
m_testResults.removeLast();
|
||||
endRemoveRows();
|
||||
QVector<Utils::TreeItem *> topLevelItems = rootItem()->children();
|
||||
for (int row = topLevelItems.size() - 1; row >= 0; --row) {
|
||||
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(row));
|
||||
if (current->testResult()->result() == Result::MESSAGE_CURRENT_TEST) {
|
||||
delete takeItem(current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestResultModel::clearTestResults()
|
||||
{
|
||||
if (m_testResults.size() == 0)
|
||||
return;
|
||||
beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1);
|
||||
m_testResults.clear();
|
||||
clear();
|
||||
m_testResultCount.clear();
|
||||
m_lastMaxWidthIndex = 0;
|
||||
m_processedIndices.clear();
|
||||
m_maxWidthOfFileName = 0;
|
||||
m_widthOfLineNumber = 0;
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
TestResult TestResultModel::testResult(const QModelIndex &index) const
|
||||
TestResult TestResultModel::testResult(const QModelIndex &idx)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return TestResult(QString(), QString());
|
||||
return m_testResults.at(index.row());
|
||||
if (idx.isValid())
|
||||
return *(static_cast<TestResultItem *>(itemForIndex(idx))->testResult());
|
||||
|
||||
return TestResult();
|
||||
}
|
||||
|
||||
int TestResultModel::maxWidthOfFileName(const QFont &font)
|
||||
{
|
||||
int count = m_testResults.size();
|
||||
if (count == 0)
|
||||
return 0;
|
||||
if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1)
|
||||
return m_maxWidthOfFileName;
|
||||
|
||||
QFontMetrics fm(font);
|
||||
if (font != m_measurementFont) {
|
||||
m_processedIndices.clear();
|
||||
m_maxWidthOfFileName = 0;
|
||||
m_measurementFont = font;
|
||||
|
||||
for (int i = m_lastMaxWidthIndex; i < count; ++i) {
|
||||
QString filename = m_testResults.at(i).fileName();
|
||||
const int pos = filename.lastIndexOf(QLatin1Char('/'));
|
||||
if (pos != -1)
|
||||
filename = filename.mid(pos +1);
|
||||
|
||||
m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(filename));
|
||||
}
|
||||
m_lastMaxWidthIndex = count - 1;
|
||||
|
||||
const QFontMetrics fm(font);
|
||||
const QVector<Utils::TreeItem *> &topLevelItems = rootItem()->children();
|
||||
const int count = topLevelItems.size();
|
||||
for (int row = 0; row < count; ++row) {
|
||||
int processed = row < m_processedIndices.size() ? m_processedIndices.at(row) : 0;
|
||||
const QVector<Utils::TreeItem *> &children = topLevelItems.at(row)->children();
|
||||
const int itemCount = children.size();
|
||||
if (processed < itemCount) {
|
||||
for (int childRow = processed; childRow < itemCount; ++childRow) {
|
||||
const TestResultItem *item = static_cast<TestResultItem *>(children.at(childRow));
|
||||
if (const TestResult *result = item->testResult()) {
|
||||
QString fileName = result->fileName();
|
||||
const int pos = fileName.lastIndexOf(QLatin1Char('/'));
|
||||
if (pos != -1)
|
||||
fileName = fileName.mid(pos + 1);
|
||||
m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(fileName));
|
||||
}
|
||||
}
|
||||
if (row < m_processedIndices.size())
|
||||
m_processedIndices.replace(row, itemCount);
|
||||
else
|
||||
m_processedIndices.insert(row, itemCount);
|
||||
}
|
||||
}
|
||||
return m_maxWidthOfFileName;
|
||||
}
|
||||
|
||||
@@ -200,11 +260,6 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font)
|
||||
return m_widthOfLineNumber;
|
||||
}
|
||||
|
||||
int TestResultModel::resultTypeCount(Result::Type type)
|
||||
{
|
||||
return m_testResultCount.value(type, 0);
|
||||
}
|
||||
|
||||
/********************************** Filter Model **********************************/
|
||||
|
||||
TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObject *parent)
|
||||
@@ -222,7 +277,9 @@ void TestResultFilterModel::enableAllResultTypes()
|
||||
<< Result::MESSAGE_WARN << Result::MESSAGE_INTERNAL
|
||||
<< Result::MESSAGE_FATAL << Result::UNKNOWN << Result::BLACKLISTED_PASS
|
||||
<< Result::BLACKLISTED_FAIL << Result::BENCHMARK
|
||||
<< Result::MESSAGE_CURRENT_TEST;
|
||||
<< Result::MESSAGE_CURRENT_TEST << Result::MESSAGE_TEST_CASE_START
|
||||
<< Result::MESSAGE_TEST_CASE_SUCCESS << Result::MESSAGE_TEST_CASE_WARN
|
||||
<< Result::MESSAGE_TEST_CASE_FAIL << Result::MESSAGE_TEST_CASE_END;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
@@ -230,8 +287,12 @@ void TestResultFilterModel::toggleTestResultType(Result::Type type)
|
||||
{
|
||||
if (m_enabled.contains(type)) {
|
||||
m_enabled.remove(type);
|
||||
if (type == Result::MESSAGE_INTERNAL)
|
||||
m_enabled.remove(Result::MESSAGE_TEST_CASE_END);
|
||||
} else {
|
||||
m_enabled.insert(type);
|
||||
if (type == Result::MESSAGE_INTERNAL)
|
||||
m_enabled.insert(Result::MESSAGE_TEST_CASE_END);
|
||||
}
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
@@ -27,43 +27,47 @@
|
||||
#include <QFont>
|
||||
#include <QSet>
|
||||
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
namespace Autotest {
|
||||
namespace Internal {
|
||||
|
||||
class TestResultModel : public QAbstractItemModel
|
||||
class TestResultItem : public Utils::TreeItem
|
||||
{
|
||||
public:
|
||||
explicit TestResultItem(TestResult *testResult);
|
||||
~TestResultItem();
|
||||
QVariant data(int column, int role) const;
|
||||
const TestResult *testResult() const { return m_testResult; }
|
||||
void updateDescription(const QString &description);
|
||||
void updateResult();
|
||||
|
||||
private:
|
||||
TestResult *m_testResult;
|
||||
};
|
||||
|
||||
class TestResultModel : public Utils::TreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestResultModel(QObject *parent = 0);
|
||||
~TestResultModel();
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||
QModelIndex parent(const QModelIndex &) const;
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
QVariant data(const QModelIndex &idx, int role) const;
|
||||
|
||||
void addTestResult(const TestResult &testResult);
|
||||
void addTestResult(TestResult *testResult, bool autoExpand = false);
|
||||
void removeCurrentTestMessage();
|
||||
void clearTestResults();
|
||||
|
||||
bool hasResults() const { return m_testResults.size() > 0; }
|
||||
TestResult testResult(const QModelIndex &index) const;
|
||||
TestResult testResult(const QModelIndex &idx);
|
||||
|
||||
int maxWidthOfFileName(const QFont &font);
|
||||
int maxWidthOfLineNumber(const QFont &font);
|
||||
|
||||
int resultTypeCount(Result::Type type);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
int resultTypeCount(Result::Type type) const { return m_testResultCount.value(type, 0); }
|
||||
|
||||
private:
|
||||
QList<TestResult> m_testResults;
|
||||
QMap<Result::Type, int> m_testResultCount;
|
||||
int m_widthOfLineNumber;
|
||||
int m_maxWidthOfFileName;
|
||||
int m_lastMaxWidthIndex;
|
||||
QList<int> m_processedIndices;
|
||||
QFont m_measurementFont;
|
||||
};
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ TestResultsPane::TestResultsPane(QObject *parent) :
|
||||
connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () {
|
||||
onCopyItemTriggered(m_treeView->currentIndex());
|
||||
});
|
||||
connect(m_model, &TestResultModel::requestExpansion, [this] (QModelIndex idx) {
|
||||
m_treeView->expand(m_filterModel->mapFromSource(idx));
|
||||
});
|
||||
connect(TestRunner::instance(), &TestRunner::testRunStarted,
|
||||
this, &TestResultsPane::onTestRunStarted);
|
||||
connect(TestRunner::instance(), &TestRunner::testRunFinished,
|
||||
@@ -122,6 +125,18 @@ TestResultsPane::TestResultsPane(QObject *parent) :
|
||||
|
||||
void TestResultsPane::createToolButtons()
|
||||
{
|
||||
m_expandCollapse = new QToolButton(m_treeView);
|
||||
m_expandCollapse->setIcon(QIcon(QLatin1String(":/find/images/expand.png")));
|
||||
m_expandCollapse->setToolTip(tr("Expand All"));
|
||||
m_expandCollapse->setCheckable(true);
|
||||
m_expandCollapse->setChecked(false);
|
||||
connect(m_expandCollapse, &QToolButton::clicked, [this] (bool checked) {
|
||||
if (checked)
|
||||
m_treeView->expandAll();
|
||||
else
|
||||
m_treeView->collapseAll();
|
||||
});
|
||||
|
||||
m_runAll = new QToolButton(m_treeView);
|
||||
m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png")));
|
||||
m_runAll->setToolTip(tr("Run All Tests"));
|
||||
@@ -167,12 +182,12 @@ TestResultsPane::~TestResultsPane()
|
||||
m_instance = 0;
|
||||
}
|
||||
|
||||
void TestResultsPane::addTestResult(const TestResult &result)
|
||||
void TestResultsPane::addTestResult(TestResult *result)
|
||||
{
|
||||
const QScrollBar *scrollBar = m_treeView->verticalScrollBar();
|
||||
m_atEnd = scrollBar ? scrollBar->value() == scrollBar->maximum() : true;
|
||||
|
||||
m_model->addTestResult(result);
|
||||
m_model->addTestResult(result, m_expandCollapse->isChecked());
|
||||
if (!m_treeView->isVisible())
|
||||
popup(Core::IOutputPane::NoModeSwitch);
|
||||
flash();
|
||||
@@ -191,7 +206,8 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent)
|
||||
|
||||
QList<QWidget *> TestResultsPane::toolBarWidgets() const
|
||||
{
|
||||
return QList<QWidget *>() << m_runAll << m_runSelected << m_stopTestRun << m_filterButton;
|
||||
return QList<QWidget *>() << m_expandCollapse << m_runAll << m_runSelected << m_stopTestRun
|
||||
<< m_filterButton;
|
||||
}
|
||||
|
||||
QString TestResultsPane::displayName() const
|
||||
@@ -266,17 +282,41 @@ void TestResultsPane::goToNext()
|
||||
if (!canNext())
|
||||
return;
|
||||
|
||||
QModelIndex currentIndex = m_treeView->currentIndex();
|
||||
const QModelIndex currentIndex = m_treeView->currentIndex();
|
||||
QModelIndex nextCurrentIndex;
|
||||
|
||||
if (currentIndex.isValid()) {
|
||||
int row = currentIndex.row() + 1;
|
||||
if (row == m_filterModel->rowCount(QModelIndex()))
|
||||
row = 0;
|
||||
currentIndex = m_filterModel->index(row, 0, QModelIndex());
|
||||
// try to set next to first child or next sibling
|
||||
if (m_filterModel->rowCount(currentIndex)) {
|
||||
nextCurrentIndex = currentIndex.child(0, 0);
|
||||
} else {
|
||||
currentIndex = m_filterModel->index(0, 0, QModelIndex());
|
||||
nextCurrentIndex = currentIndex.sibling(currentIndex.row() + 1, 0);
|
||||
// if it had no sibling check siblings of parent (and grandparents if necessary)
|
||||
if (!nextCurrentIndex.isValid()) {
|
||||
|
||||
QModelIndex parent = currentIndex.parent();
|
||||
do {
|
||||
if (!parent.isValid())
|
||||
break;
|
||||
nextCurrentIndex = parent.sibling(parent.row() + 1, 0);
|
||||
parent = parent.parent();
|
||||
} while (!nextCurrentIndex.isValid());
|
||||
}
|
||||
m_treeView->setCurrentIndex(currentIndex);
|
||||
onItemActivated(currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// if we have no current or could not find a next one, use the first item of the whole tree
|
||||
if (!nextCurrentIndex.isValid()) {
|
||||
Utils::TreeItem *rootItem = m_model->itemForIndex(QModelIndex());
|
||||
// if the tree does not contain any item - don't do anything
|
||||
if (!rootItem || !rootItem->childCount())
|
||||
return;
|
||||
|
||||
nextCurrentIndex = m_filterModel->mapFromSource(m_model->indexForItem(rootItem->child(0)));
|
||||
}
|
||||
|
||||
m_treeView->setCurrentIndex(nextCurrentIndex);
|
||||
onItemActivated(nextCurrentIndex);
|
||||
}
|
||||
|
||||
void TestResultsPane::goToPrev()
|
||||
@@ -284,17 +324,37 @@ void TestResultsPane::goToPrev()
|
||||
if (!canPrevious())
|
||||
return;
|
||||
|
||||
QModelIndex currentIndex = m_treeView->currentIndex();
|
||||
const QModelIndex currentIndex = m_treeView->currentIndex();
|
||||
QModelIndex nextCurrentIndex;
|
||||
|
||||
if (currentIndex.isValid()) {
|
||||
int row = currentIndex.row() - 1;
|
||||
if (row < 0)
|
||||
row = m_filterModel->rowCount(QModelIndex()) - 1;
|
||||
currentIndex = m_filterModel->index(row, 0, QModelIndex());
|
||||
// try to set next to prior sibling or parent
|
||||
if (currentIndex.row() > 0) {
|
||||
nextCurrentIndex = currentIndex.sibling(currentIndex.row() - 1, 0);
|
||||
// if the sibling has children, use the last one
|
||||
while (int rowCount = m_filterModel->rowCount(nextCurrentIndex))
|
||||
nextCurrentIndex = nextCurrentIndex.child(rowCount - 1, 0);
|
||||
} else {
|
||||
currentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0, QModelIndex());
|
||||
nextCurrentIndex = currentIndex.parent();
|
||||
}
|
||||
m_treeView->setCurrentIndex(currentIndex);
|
||||
onItemActivated(currentIndex);
|
||||
}
|
||||
|
||||
// if we have no current or didn't find a sibling/parent use the last item of the whole tree
|
||||
if (!nextCurrentIndex.isValid()) {
|
||||
const QModelIndex rootIdx = m_filterModel->index(0, 0);
|
||||
// if the tree does not contain any item - don't do anything
|
||||
if (!rootIdx.isValid())
|
||||
return;
|
||||
|
||||
// get the last (visible) top level index
|
||||
nextCurrentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0);
|
||||
// step through until end
|
||||
while (int rowCount = m_filterModel->rowCount(nextCurrentIndex))
|
||||
nextCurrentIndex = nextCurrentIndex.child(rowCount - 1, 0);
|
||||
}
|
||||
|
||||
m_treeView->setCurrentIndex(nextCurrentIndex);
|
||||
onItemActivated(nextCurrentIndex);
|
||||
}
|
||||
|
||||
void TestResultsPane::onItemActivated(const QModelIndex &index)
|
||||
@@ -482,14 +542,15 @@ void TestResultsPane::onSaveWholeTriggered()
|
||||
}
|
||||
|
||||
// helper for onCopyWholeTriggered() and onSaveWholeTriggered()
|
||||
QString TestResultsPane::getWholeOutput()
|
||||
QString TestResultsPane::getWholeOutput(const QModelIndex &parent)
|
||||
{
|
||||
QString output;
|
||||
const QModelIndex invalid; // practically the invisible root item
|
||||
for (int row = 0, count = m_model->rowCount(invalid); row < count; ++row) {
|
||||
const TestResult result = m_model->testResult(m_model->index(row, 0, invalid));
|
||||
for (int row = 0, count = m_model->rowCount(parent); row < count; ++row) {
|
||||
QModelIndex current = m_model->index(row, 0, parent);
|
||||
const TestResult result = m_model->testResult(current);
|
||||
output.append(TestResult::resultToString(result.result())).append(QLatin1Char('\t'));
|
||||
output.append(TestResultDelegate::outputString(result, true)).append(QLatin1Char('\n'));
|
||||
output.append(getWholeOutput(current));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void addTestResult(const TestResult &result);
|
||||
void addTestResult(TestResult *result);
|
||||
|
||||
private slots:
|
||||
void onItemActivated(const QModelIndex &index);
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
void onCopyItemTriggered(const QModelIndex &idx);
|
||||
void onCopyWholeTriggered();
|
||||
void onSaveWholeTriggered();
|
||||
QString getWholeOutput();
|
||||
QString getWholeOutput(const QModelIndex &parent = QModelIndex());
|
||||
|
||||
QWidget *m_outputWidget;
|
||||
QFrame *m_summaryWidget;
|
||||
@@ -115,6 +115,7 @@ private:
|
||||
TestResultModel *m_model;
|
||||
TestResultFilterModel *m_filterModel;
|
||||
Core::IContext *m_context;
|
||||
QToolButton *m_expandCollapse;
|
||||
QToolButton *m_runAll;
|
||||
QToolButton *m_runSelected;
|
||||
QToolButton *m_stopTestRun;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Internal {
|
||||
|
||||
static TestRunner *m_instance = 0;
|
||||
|
||||
void emitTestResultCreated(const TestResult &testResult)
|
||||
void emitTestResultCreated(TestResult *testResult)
|
||||
{
|
||||
emit m_instance->testResultCreated(testResult);
|
||||
}
|
||||
@@ -114,7 +114,7 @@ void performTestRun(QFutureInterface<void> &futureInterface,
|
||||
if (config->project()) {
|
||||
testCaseCount += config->testCaseCount();
|
||||
} else {
|
||||
emitTestResultCreated(FaultyTestResult(Result::MESSAGE_WARN,
|
||||
emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_WARN,
|
||||
QObject::tr("Project is null for \"%1\". Removing from test run.\n"
|
||||
"Check the test environment.").arg(config->displayName())));
|
||||
}
|
||||
@@ -148,7 +148,7 @@ void performTestRun(QFutureInterface<void> &futureInterface,
|
||||
QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment();
|
||||
QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment);
|
||||
if (commandFilePath.isEmpty()) {
|
||||
emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
QObject::tr("Could not find command \"%1\". (%2)")
|
||||
.arg(testConfiguration->targetFile())
|
||||
.arg(testConfiguration->displayName())));
|
||||
@@ -177,7 +177,7 @@ void performTestRun(QFutureInterface<void> &futureInterface,
|
||||
if (futureInterface.isCanceled()) {
|
||||
testProcess.kill();
|
||||
testProcess.waitForFinished();
|
||||
emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
QObject::tr("Test run canceled by user.")));
|
||||
}
|
||||
qApp->processEvents();
|
||||
@@ -188,7 +188,7 @@ void performTestRun(QFutureInterface<void> &futureInterface,
|
||||
if (testProcess.state() != QProcess::NotRunning) {
|
||||
testProcess.kill();
|
||||
testProcess.waitForFinished();
|
||||
emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr(
|
||||
emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr(
|
||||
"Test case canceled due to timeout. \nMaybe raise the timeout?")));
|
||||
}
|
||||
}
|
||||
@@ -208,14 +208,14 @@ void TestRunner::prepareToRunTests()
|
||||
|
||||
foreach (TestConfiguration *config, m_selectedTests) {
|
||||
if (!omitRunConfigWarnings && config->guessedConfiguration()) {
|
||||
TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN,
|
||||
TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN,
|
||||
tr("Project's run configuration was guessed for \"%1\".\n"
|
||||
"This might cause trouble during execution.").arg(config->displayName())));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_selectedTests.empty()) {
|
||||
TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN,
|
||||
TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN,
|
||||
tr("No tests selected. Canceling test run.")));
|
||||
onFinished();
|
||||
return;
|
||||
@@ -223,7 +223,7 @@ void TestRunner::prepareToRunTests()
|
||||
|
||||
ProjectExplorer::Project *project = m_selectedTests.at(0)->project();
|
||||
if (!project) {
|
||||
TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN,
|
||||
TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN,
|
||||
tr("Project is null. Canceling test run.\n"
|
||||
"Only desktop kits are supported. Make sure the "
|
||||
"currently active kit is a desktop kit.")));
|
||||
@@ -239,7 +239,7 @@ void TestRunner::prepareToRunTests()
|
||||
if (project->hasActiveBuildSettings()) {
|
||||
buildProject(project);
|
||||
} else {
|
||||
TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
tr("Project is not configured. Canceling test run.")));
|
||||
onFinished();
|
||||
return;
|
||||
@@ -284,7 +284,7 @@ void TestRunner::buildFinished(bool success)
|
||||
if (success) {
|
||||
runTests();
|
||||
} else {
|
||||
TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_FATAL,
|
||||
tr("Build failed. Canceling test run.")));
|
||||
onFinished();
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
signals:
|
||||
void testRunStarted();
|
||||
void testRunFinished();
|
||||
void testResultCreated(const TestResult &testResult);
|
||||
void testResultCreated(TestResult *testResult);
|
||||
void requestStopTestRun();
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -208,8 +208,12 @@ void TestXmlOutputReader::processOutput()
|
||||
while (m_testApplication->canReadLine()) {
|
||||
// TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem?
|
||||
const QString line = QString::fromUtf8(m_testApplication->readLine()).trimmed();
|
||||
if (line.isEmpty() || xmlStartsWith(line, QLatin1String("<TestCase name=\""), className))
|
||||
if (line.isEmpty() || xmlStartsWith(line, QLatin1String("<TestCase name=\""), className)) {
|
||||
testResultCreated(new TestResult(className, QString(), QString(),
|
||||
Result::MESSAGE_TEST_CASE_START,
|
||||
QObject::tr("Executing test case %1").arg(className)));
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(QLatin1String("<?xml version"))) {
|
||||
className = QString();
|
||||
continue;
|
||||
@@ -222,7 +226,7 @@ void TestXmlOutputReader::processOutput()
|
||||
result = Result::UNKNOWN;
|
||||
lineNumber = 0;
|
||||
readingDescription = false;
|
||||
testResultCreated(TestResult(QString(), QString(), QString(), Result::MESSAGE_CURRENT_TEST,
|
||||
testResultCreated(new TestResult(QString(), QString(), QString(), Result::MESSAGE_CURRENT_TEST,
|
||||
QObject::tr("Entering test function %1::%2").arg(className).arg(testCase)));
|
||||
continue;
|
||||
}
|
||||
@@ -240,39 +244,37 @@ void TestXmlOutputReader::processOutput()
|
||||
}
|
||||
if (xmlExtractTypeFileLine(line, QLatin1String("<Incident"), result, file, lineNumber)) {
|
||||
if (line.endsWith(QLatin1String("/>"))) {
|
||||
TestResult testResult(className, testCase, dataTag, result, description);
|
||||
TestResult *testResult = new TestResult(className, testCase, dataTag, result, description);
|
||||
if (!file.isEmpty())
|
||||
file = constructSourceFilePath(m_testApplication->workingDirectory(), file,
|
||||
m_testApplication->program());
|
||||
testResult.setFileName(file);
|
||||
testResult.setLine(lineNumber);
|
||||
testResult->setFileName(file);
|
||||
testResult->setLine(lineNumber);
|
||||
testResultCreated(testResult);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (xmlExtractBenchmarkInformation(line, QLatin1String("<BenchmarkResult"), benchmarkDescription)) {
|
||||
TestResult testResult(className, testCase, dataTag, Result::BENCHMARK, benchmarkDescription);
|
||||
testResultCreated(testResult);
|
||||
testResultCreated(new TestResult(className, testCase, dataTag, Result::BENCHMARK,
|
||||
benchmarkDescription));
|
||||
continue;
|
||||
}
|
||||
if (line == QLatin1String("</Message>") || line == QLatin1String("</Incident>")) {
|
||||
TestResult testResult(className, testCase, dataTag, result, description);
|
||||
TestResult *testResult = new TestResult(className, testCase, dataTag, result, description);
|
||||
if (!file.isEmpty())
|
||||
file = constructSourceFilePath(m_testApplication->workingDirectory(), file,
|
||||
m_testApplication->program());
|
||||
testResult.setFileName(file);
|
||||
testResult.setLine(lineNumber);
|
||||
testResult->setFileName(file);
|
||||
testResult->setLine(lineNumber);
|
||||
testResultCreated(testResult);
|
||||
description = QString();
|
||||
} else if (line == QLatin1String("</TestFunction>") && !duration.isEmpty()) {
|
||||
TestResult testResult(className, testCase, QString(), Result::MESSAGE_INTERNAL,
|
||||
QObject::tr("Execution took %1 ms.").arg(duration));
|
||||
testResultCreated(testResult);
|
||||
testResultCreated(new TestResult(className, testCase, QString(), Result::MESSAGE_INTERNAL,
|
||||
QObject::tr("Execution took %1 ms.").arg(duration)));
|
||||
emit increaseProgress();
|
||||
} else if (line == QLatin1String("</TestCase>") && !duration.isEmpty()) {
|
||||
TestResult testResult(className, QString(), QString(), Result::MESSAGE_INTERNAL,
|
||||
QObject::tr("Test execution took %1 ms.").arg(duration));
|
||||
testResultCreated(testResult);
|
||||
testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_TEST_CASE_END,
|
||||
QObject::tr("Test execution took %1 ms.").arg(duration)));
|
||||
} else if (readingDescription) {
|
||||
if (line.endsWith(QLatin1String("]]></Description>"))) {
|
||||
description.append(QLatin1Char('\n'));
|
||||
@@ -283,10 +285,10 @@ void TestXmlOutputReader::processOutput()
|
||||
description.append(line);
|
||||
}
|
||||
} else if (xmlStartsWith(line, QLatin1String("<QtVersion>"), qtVersion)) {
|
||||
testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL,
|
||||
testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_INTERNAL,
|
||||
QObject::tr("Qt version: %1").arg(qtVersion)));
|
||||
} else if (xmlStartsWith(line, QLatin1String("<QTestVersion>"), qtestVersion)) {
|
||||
testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL,
|
||||
testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_INTERNAL,
|
||||
QObject::tr("QTest version: %1").arg(qtestVersion)));
|
||||
} else {
|
||||
// qDebug() << "Unhandled line:" << line; // TODO remove
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
public slots:
|
||||
void processOutput();
|
||||
signals:
|
||||
void testResultCreated(const TestResult &testResult);
|
||||
void testResultCreated(TestResult *testResult);
|
||||
void increaseProgress();
|
||||
private:
|
||||
QProcess *m_testApplication;
|
||||
|
||||
Reference in New Issue
Block a user