Adding test support plugin to Creator.

The plugin adds a navigator pane which shows a tree of all tests
'found' in the project, as well as Test Result output panes.
Tests can be edited in an editor and executed from within the IDE.
This is the first in a series of commits, ending with documentation.

Change-Id: Iee91cf991810347cb2f3a428f7457ea75e0c5b57
Reviewed-on: http://codereview.qt.nokia.com/2020
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@nokia.com>
Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
This commit is contained in:
Shane Bradley
2011-07-22 17:32:08 +10:00
committed by Eike Ziller
parent 9c72215147
commit 82427fe4fd
54 changed files with 12540 additions and 0 deletions

View File

@@ -44,6 +44,7 @@ SUBDIRS = plugin_coreplugin \
debugger/dumper.pro \ debugger/dumper.pro \
plugin_qmlprofiler \ plugin_qmlprofiler \
plugin_remotelinux \ plugin_remotelinux \
plugin_qttest \
plugin_valgrind plugin_valgrind
linux-* { linux-* {
@@ -181,6 +182,14 @@ plugin_qtestlib.subdir = qtestlib
plugin_qtestlib.depends = plugin_projectexplorer plugin_qtestlib.depends = plugin_projectexplorer
plugin_qtestlib.depends += plugin_coreplugin plugin_qtestlib.depends += plugin_coreplugin
plugin_qttest.subdir = qttest
plugin_qttest.depends = plugin_projectexplorer
plugin_qttest.depends += plugin_coreplugin
plugin_qttest.depends += plugin_debugger
plugin_qttest.depends += plugin_qt4projectmanager
plugin_qttest.depends += plugin_qtsupport
plugin_qttest.depends += plugin_remotelinux
plugin_helloworld.subdir = helloworld plugin_helloworld.subdir = helloworld
plugin_helloworld.depends = plugin_coreplugin plugin_helloworld.depends = plugin_coreplugin

View File

@@ -0,0 +1,24 @@
<plugin name=\"QtTest\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
<vendor>Nokia Corporation</vendor>
<copyright>(C) 2011 Nokia Corporation</copyright>
<license>
Commercial Usage
Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Nokia.
GNU Lesser General Public License Usage
Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. Please review the following information to ensure the GNU Lesser General Public License version 2.1 requirements will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
</license>
<category>Automated Testing</category>
<description>Automated Testing Plugin</description>
<url>http://qt.nokia.com</url>
<dependencyList>
<dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"Debugger\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"Qt4ProjectManager\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"QtSupport\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"RemoteLinux\" version=\"$$QTCREATOR_VERSION\"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,46 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "addmanualtestdlg.h"
#include "ui_addmanualtestdlg.h"
AddManualTestDlg::AddManualTestDlg(QWidget *parent) :
QDialog(parent),
ui(new Ui::AddManualTestDlg)
{
ui->setupUi(this);
}
AddManualTestDlg::~AddManualTestDlg()
{
delete ui;
}

View File

@@ -0,0 +1,54 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef ADDMANUALTESTDLG_H
#define ADDMANUALTESTDLG_H
#include <QDialog>
namespace Ui {
class AddManualTestDlg;
}
class AddManualTestDlg : public QDialog
{
Q_OBJECT
public:
explicit AddManualTestDlg(QWidget *parent = 0);
~AddManualTestDlg();
private:
Ui::AddManualTestDlg *ui;
};
#endif // ADDMANUALTESTDLG_H

View File

@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddManualTestDlg</class>
<widget class="QDialog" name="AddManualTestDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>625</width>
<height>605</height>
</rect>
</property>
<property name="windowTitle">
<string>Add Manual Test</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Test function name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Test goal:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>75</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Prerequisites:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>75</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Test steps:</string>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="tableWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>lineEdit</tabstop>
<tabstop>plainTextEdit</tabstop>
<tabstop>plainTextEdit_2</tabstop>
<tabstop>tableWidget</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AddManualTestDlg</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>AddManualTestDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,217 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "dialogs.h"
#include "qsystem.h"
#include <QTimer>
#include <QMessageBox>
#include <QFileDialog>
#include <QAbstractItemView>
#include <QHeaderView>
#include <QTableWidgetItem>
#include <QResizeEvent>
#include <QScrollBar>
#include <QPushButton>
SelectDlg::SelectDlg(const QString &title, const QString &helpText,
QAbstractItemView::SelectionMode mode, int width, int height,
const QStringList &columns, const QByteArray &colWidths, QWidget *parent) : QDialog(parent)
{
m_colWidths = colWidths;
setupUi(this);
setModal(true);
setWindowTitle(title);
instructLabel->setText(helpText);
groupsList->setSelectionMode(mode);
resize(width, height);
groupsList->setEditTriggers(QAbstractItemView::NoEditTriggers);
groupsList->setColumnCount(columns.count());
groupsList->setHorizontalHeaderLabels(columns);
groupsList->setSelectionBehavior(QAbstractItemView::SelectRows);
groupsList->setSortingEnabled(true);
groupsList->sortByColumn(0, Qt::AscendingOrder);
groupsList->setAlternatingRowColors(true);
groupsList->verticalHeader()->hide();
groupsList->horizontalHeader()->show();
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
groupsList->setWordWrap(true);
connect(groupsList, SIGNAL(itemSelectionChanged()),
this, SLOT(onItemSelectionChanged()), Qt::DirectConnection);
QTimer::singleShot(0, this, SLOT(resizeEvent()));
}
void SelectDlg::resizeEvent()
{
resizeEvent(0);
}
void SelectDlg::addSelectableItems(const QStringList &items)
{
foreach (const QString &item, items)
addSelectableItem(item);
}
void SelectDlg::addSelectableItem(const QString &item)
{
groupsList->setSortingEnabled(false);
if (groupsList->columnCount() > 1) {
int row = groupsList->rowCount();
groupsList->insertRow(row);
QStringList tmp = item.split("|");
if (tmp.count() > groupsList->columnCount()) {
for (int i = 0; i < (groupsList->columnCount() - 1); ++i)
groupsList->setItem(row, i, new QTableWidgetItem(tmp[i]));
QString s;
for (int i = groupsList->columnCount(); i < tmp.count(); ++i) {
if (!s.isEmpty()) s+= "|";
s += tmp[i];
}
groupsList->setItem(row, (groupsList->columnCount() - 1), new QTableWidgetItem(s));
} else if (tmp.count() < groupsList->columnCount()) {
for (int i = 0; i < tmp.count(); ++i)
groupsList->setItem(row, i, new QTableWidgetItem(tmp[i]));
for (int i = tmp.count(); i < groupsList->columnCount(); ++i)
groupsList->setItem(row, i, new QTableWidgetItem(""));
} else {
for (int i = 0; i < tmp.count(); ++i)
groupsList->setItem(row, i, new QTableWidgetItem(tmp[i]));
}
} else {
// In single column mode we accept no duplicates
if (groupsList->findItems(item, Qt::MatchCaseSensitive).count() <= 0) {
int row = groupsList->rowCount();
groupsList->insertRow(row);
groupsList->setItem(row, 0, new QTableWidgetItem(item));
}
}
groupsList->setSortingEnabled(true);
}
QStringList SelectDlg::selectedItems()
{
QStringList ret;
QTableWidgetItem *item;
for (int row = 0; row < groupsList->rowCount(); ++row) {
item = groupsList->item(row, 0);
if (item && item->isSelected()) {
QString S = item->text();
for (int col = 1; col < groupsList->columnCount(); ++col) {
S+= "|";
item = groupsList->item(row, col);
if (item)
S += item->text();
}
ret.append(S);
}
}
return ret;
}
void SelectDlg::setColumnWidth(int col, int width)
{
groupsList->setColumnWidth(col, width);
}
void SelectDlg::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
int fixedSize = 4;
const int extraSize = 80;
int total = 0;
if (groupsList->verticalScrollBar()->isVisible())
fixedSize += groupsList->verticalScrollBar()->width();
for (int i = 0; i < groupsList->columnCount(); ++i) {
if (i < m_colWidths.count()) {
if (static_cast<int>(m_colWidths[i]) > 0) {
setColumnWidth(i, m_colWidths[i]);
total += m_colWidths[i];
}
} else if (i == 0) {
int extra = groupsList->columnCount() - 1;
int colWidth = (groupsList->width() - fixedSize) - (extraSize * extra);
setColumnWidth(0, colWidth);
} else {
setColumnWidth(i, extraSize);
}
}
if (m_colWidths.count() > 0) {
for (int i = 0; i < groupsList->columnCount(); ++i) {
if ((i < m_colWidths.count()) && (static_cast<int>(m_colWidths[i]) == 0)) {
int colWidth = (groupsList->width() - fixedSize) - total;
setColumnWidth(i, colWidth);
}
}
}
groupsList->resizeRowsToContents();
}
void SelectDlg::resizeContents()
{
groupsList->resizeRowsToContents();
}
void SelectDlg::onItemSelectionChanged()
{
QList<QTableWidgetItem *> items = groupsList->selectedItems();
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(items.count() > 0);
}
//***********************************
NewTestFunctionDlg::NewTestFunctionDlg(const QString &testCase, QWidget *parent) :
QDialog(parent)
{
setupUi(this);
setModal(true);
testcaseLabel->setText(testCase);
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
connect(testFunctionName,SIGNAL(textChanged(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
resizeEvent(0);
}
void NewTestFunctionDlg::onChanged()
{
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!testFunctionName->text().isEmpty());
}

View File

@@ -0,0 +1,74 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef DIALOGS_H
#define DIALOGS_H
#include "ui_selectdlg.h"
#include "ui_newtestfunctiondlg.h"
class SelectDlg : public QDialog, public Ui::SelectDlg
{
Q_OBJECT
public:
SelectDlg(const QString &title, const QString &helpText,
QAbstractItemView::SelectionMode mode, int width, int height,
const QStringList &columns, const QByteArray &colWidths, QWidget *parent = 0);
void addSelectableItem(const QString &item);
void addSelectableItems(const QStringList &items);
QStringList selectedItems();
void resizeContents();
private slots:
void onItemSelectionChanged();
void resizeEvent();
private:
void setColumnWidth(int col, int width);
void resizeEvent(QResizeEvent *event);
QByteArray m_colWidths;
};
class NewTestFunctionDlg : public QDialog, public Ui::NewTestFunctionDlg
{
Q_OBJECT
public:
NewTestFunctionDlg(const QString &testCase, QWidget *parent = 0);
private slots:
void onChanged();
};
#endif // DIALOGS_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,202 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "newtestcasedlg.h"
#include "ui_newtestcasedlg.h"
#include "testgenerator.h"
#include <QPushButton>
#include <QFileDialog>
#include <QRegExpValidator>
#include <QRegExp>
#include <QDir>
#include <QDebug>
NewTestCaseDlg::NewTestCaseDlg(const QString &path, QWidget *parent) :
QDialog(parent),
ui(new Ui::NewTestCaseDlg)
{
ui->setupUi(this);
m_pathIsEdited = false;
ui->location->setText(path + "/tests");
connect(ui->rbUnit, SIGNAL(clicked(bool)), this, SLOT(onChanged()));
connect(ui->rbIntegration, SIGNAL(clicked(bool)), this, SLOT(onChanged()));
connect(ui->rbPerformance, SIGNAL(clicked(bool)), this, SLOT(onChanged()));
connect(ui->rbSystem, SIGNAL(clicked(bool)), this, SLOT(onChanged()));
connect(ui->testName, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
connect(ui->componentName, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
connect(ui->location, SIGNAL(textChanged(QString)), this, SLOT(onLocationChanged(QString)));
connect(ui->locationBtn, SIGNAL(clicked()), this, SLOT(onLocationBtnClicked()));
connect(ui->prependComponentName, SIGNAL(stateChanged(int)),
this, SLOT(onComponentChkBoxChanged(int)));
m_originalPalette = palette();
ui->rbUnit->setChecked(true);
// set a validator for test case name
QRegExp testCaseRegExp(QLatin1String("([a-z]{3,3})_([a-z]|[A-Z])([a-z]|[A-Z]|\\d|_|-)+"),
Qt::CaseSensitive);
QRegExpValidator *testCaseValidator = new QRegExpValidator(testCaseRegExp, this);
ui->testName->setValidator(testCaseValidator);
onTextChanged("");
}
NewTestCaseDlg::~NewTestCaseDlg()
{
delete ui;
}
void NewTestCaseDlg::onTextChanged(const QString &txt)
{
Q_UNUSED(txt);
onChanged();
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ui->testName->text().length() > 4);
}
void NewTestCaseDlg::onLocationChanged(const QString &txt)
{
Q_UNUSED(txt);
m_pathIsEdited = true;
onChanged();
}
void NewTestCaseDlg::onChanged()
{
QString txt = ui->testName->text();
QString prefix;
QString subdir;
switch (mode()) {
case TestGenerator::UnitTest:
prefix = "tst_";
subdir = "auto";
break;
case TestGenerator::PerformanceTest:
prefix = "prf_";
subdir = "benchmarks";
break;
case TestGenerator::IntegrationTest:
prefix = "int_";
subdir = "auto";
break;
case TestGenerator::SystemTest:
prefix = "sys_";
subdir = "systemtests";
break;
}
if (!txt.startsWith(prefix)) {
QString rest = txt.mid(4);
ui->testName->setText(prefix + rest);
}
if (QFile::exists(ui->location->text())) {
ui->location->setPalette(m_originalPalette);
} else {
// use a highlighted text color if directory does not exist
QPalette pal = ui->location->palette();
pal.setColor(QPalette::Text, Qt::red); // TODO make use of a theme friendly color
ui->location->setPalette(pal);
}
// show the user the files that would be created
ui->filesList->clear();
m_testCaseGenerator.setTestCase(mode(), location(), "", testCaseName(),
testedComponent(), testedClassName(), "");
ui->filesList->addItem(m_testCaseGenerator.generatedProName());
ui->filesList->addItem(m_testCaseGenerator.generatedFileName());
}
QString NewTestCaseDlg::actualPath()
{
return m_testCaseGenerator.testCaseDirectory();
}
TestGenerator::GenMode NewTestCaseDlg::mode()
{
if (ui->rbUnit->isChecked())
return TestGenerator::UnitTest;
else if (ui->rbIntegration->isChecked())
return TestGenerator::IntegrationTest;
else if (ui->rbPerformance->isChecked())
return TestGenerator::PerformanceTest;
else
return TestGenerator::SystemTest;
}
QString NewTestCaseDlg::testCaseName()
{
return ui->testName->text();
}
QString NewTestCaseDlg::location()
{
return ui->location->text();
}
QString NewTestCaseDlg::testedClassName()
{
return ui->testedClass->text();
}
QString NewTestCaseDlg::testedComponent()
{
return ui->componentName->text();
}
void NewTestCaseDlg::onLocationBtnClicked()
{
QString absoluteTestPath =
QFileDialog::getExistingDirectory(this, tr("Select Absolute Test Case Directory"),
ui->location->text());
if (!absoluteTestPath.isEmpty()) {
ui->location->setText(absoluteTestPath);
onChanged();
}
}
void NewTestCaseDlg::onComponentChkBoxChanged(int state)
{
m_testCaseGenerator.enableComponentInTestName(state == Qt::Checked);
onChanged();
}
bool NewTestCaseDlg::componentInName()
{
return (ui->prependComponentName->checkState() == Qt::Checked);
}

View File

@@ -0,0 +1,73 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef NEWTESTCASEDLG_H
#define NEWTESTCASEDLG_H
#include "testgenerator.h"
#include <QDialog>
namespace Ui {
class NewTestCaseDlg;
}
class NewTestCaseDlg : public QDialog
{
Q_OBJECT
public:
explicit NewTestCaseDlg(const QString &path, QWidget *parent = 0);
~NewTestCaseDlg();
TestGenerator::GenMode mode();
QString testCaseName();
QString location();
QString testedClassName();
QString testedComponent();
QString actualPath();
bool componentInName();
private slots:
void onTextChanged(const QString &txt);
void onLocationChanged(const QString &txt);
void onChanged();
void onLocationBtnClicked();
void onComponentChkBoxChanged(int state);
private:
Ui::NewTestCaseDlg *ui;
bool m_pathIsEdited;
QPalette m_originalPalette;
TestGenerator m_testCaseGenerator;
};
#endif // NEWTESTCASEDLG_H

View File

@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewTestCaseDlg</class>
<widget class="QDialog" name="NewTestCaseDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>548</width>
<height>461</height>
</rect>
</property>
<property name="windowTitle">
<string>New Test</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Test Type</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="rbUnit">
<property name="text">
<string>Unit test</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbIntegration">
<property name="text">
<string>Integration test</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbPerformance">
<property name="text">
<string>Performance test</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbSystem">
<property name="text">
<string>System test</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Base path:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="location"/>
</item>
<item>
<widget class="QPushButton" name="locationBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Test name:</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="testName">
<property name="toolTip">
<string>Example of test name: tst_MyAppTest1</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="prependComponentName">
<property name="text">
<string>Use component name in test case path</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Tested component:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLineEdit" name="componentName"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Tested class:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLineEdit" name="testedClass">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_filename">
<property name="text">
<string>Test files:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="m_filename">
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QListWidget" name="filesList"/>
</item>
<item row="8" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>rbUnit</tabstop>
<tabstop>rbIntegration</tabstop>
<tabstop>rbPerformance</tabstop>
<tabstop>rbSystem</tabstop>
<tabstop>location</tabstop>
<tabstop>testName</tabstop>
<tabstop>componentName</tabstop>
<tabstop>testedClass</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>NewTestCaseDlg</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>NewTestCaseDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewTestFunctionDlg</class>
<widget class="QDialog" name="NewTestFunctionDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>540</width>
<height>140</height>
</rect>
</property>
<property name="windowTitle">
<string>New Test Function</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="testcaseLabel">
<property name="text">
<string>Text case</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Test function name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="testFunctionName"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="insertAtCursor">
<property name="text">
<string>Insert at cursor</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>NewTestFunctionDlg</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>NewTestFunctionDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,547 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "qsystem.h"
#include <QApplication>
#include <QProcess>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QtNetwork/QUdpSocket>
#include <QTimer>
#include <QHostInfo>
#include <stdlib.h>
#if defined Q_OS_UNIX
# include <sys/utsname.h>
# include <sys/stat.h>
# include <utime.h>
#endif
// WinCE doesn't have time.h
#ifndef Q_OS_TEMP
# include <time.h>
#endif
#ifdef Q_OS_WIN32
# include <windows.h>
# include <stdlib.h>
#endif
#ifdef Q_OS_UNIX
# if defined(Q_OS_MAC)
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
# else
# include <unistd.h>
extern char **environ;
# endif
#endif
//workaround for Qt 4
#if !defined(QT_THREAD_SUPPORT) && !defined(QT_NO_THREAD)
# define QT_THREAD_SUPPORT
#endif
/*!
\class QSystem qsystem.h
\mainclass
\brief The QSystem class is a wrapper class that provides a platform independent
API for some frequently used platform dependent functions.
*/
/*!
Returns the lowercase username as known to the system.
*/
QString QSystem::userName()
{
QString userName;
#if defined Q_OS_TEMP
userName = "WinCE";
#elif defined Q_OS_WIN32
userName = getenv("USERNAME");
#elif defined Q_OS_UNIX
userName = getenv("USER");
if (userName == "")
userName = getenv("LOGNAME");
#elif defined Q_OS_MAC
userName = getenv();
#endif
return userName.toLower();
}
/*!
Returns the lowercase hostname (computername) as known to the system.
Only the first part of a hostname is returned, e.g. foo.troll.no will return foo
as the hostname.
*/
QString QSystem::hostName()
{
static QString hostName;
if (!hostName.isEmpty())
return hostName;
hostName = QHostInfo::localHostName();
// convert anarki.troll.no to anarki
int pos = hostName.indexOf(".");
if (pos > 0)
hostName = hostName.left(pos);
return hostName;
}
/*!
Returns the operating system on which the app is running.
*/
QString QSystem::OSName()
{
#if defined(Q_OS_MAC)
return "Mac-OSX";
#elif defined(Q_OS_MSDOS)
return "MSDOS";
#elif defined(Q_OS_OS2EMX)
return "OS2EMX";
#elif defined(Q_OS_OS2)
return "OS2";
#elif defined(Q_OS_WIN32) || defined (Q_OS_WIN64)
return "Windows";
#elif defined(Q_OS_SOLARIS)
return "Solaris";
#elif defined(Q_OS_SUN) && defined(Q_OS_BSD4)
return "Sun";
#elif defined(Q_OS_HPUX)
return "HPUX";
#elif defined(Q_OS_ULTRIX)
return "ULTRIX";
#elif defined(Q_OS_RELIANT)
return "RELIANT";
#elif defined(Q_OS_LINUX)
return "Linux";
#elif defined(Q_OS_FREEBSD) && defined(Q_OS_BSD4)
return "FREEBSD";
#elif defined(Q_OS_NETBSD) && defined(Q_OS_BSD4)
return "NETBSD";
#elif defined(Q_OS_OPENBSD) && defined(Q_OS_BSD4)
return "OPENBSD";
#elif defined(Q_OS_BSDI) && defined(Q_OS_BSD4)
return "BSDI";
#elif defined(Q_OS_IRIX)
return "IRIX";
#elif defined(Q_OS_OSF)
return "OSF";
#elif defined(Q_OS_AIX)
return "AIX";
#elif defined(Q_OS_LYNX)
return "LYNX";
#elif defined(Q_OS_UNIXWARE)
return "UNIXWARE";
#elif defined(Q_OS_HURD)
return "HURD";
#elif defined(Q_OS_DGUX)
return "DGUX";
#elif defined(Q_OS_QNX6)
return "QNX6";
#elif defined(Q_OS_QNX)
return "QNX";
#elif defined(Q_OS_SCO)
return "SCO";
#elif defined(Q_OS_UNIXWARE7)
return "UNIXWARE7";
#elif defined(Q_OS_DYNIX)
return "DYNIX";
#elif defined(Q_OS_SVR4)
return "SVR4";
#else
return "UNKNOWN";
#endif
}
QString which_p(const QString &path, const QString &applicationName)
{
QStringList paths;
#if defined Q_OS_WIN32
paths = path.split(";");
#else
paths = path.split(":");
#endif
foreach (const QString &p, paths) {
QString fname = p + QDir::separator() + applicationName;
if (QFile::exists(fname))
return fname;
#if defined Q_OS_WIN32
if (QFile::exists(fname + ".exe"))
return fname + ".exe";
if (QFile::exists(fname + ".bat"))
return fname + ".bat";
#endif
}
return "";
}
/*!
Traverses through the PATH setting as specified in \a path and returns the full
path + appname if found. On Windows the application name may be appended with .exe or .bat
(if either exists).
*/
QString QSystem::which(const QString &path, const QString &applicationName)
{
QString ret = which_p(path, applicationName);
if (ret.contains(" "))
return '"' + ret + '"';
return ret;
}
/*!
Processes a string \a envString. If the envString contains a set (export)
command then the information in the envString is used to update \a envList.
If the envString does not contain a set command then the string is processed
and all references to environment values are replaced with their actual values
from \a envList.
The function returns true if 'something' is converted.
Example1:
envString == "export PATH=/home/myname/bin:/home/bin"
envList == {
export PATH=foo
export QTDIR=/home/qt
export QTESTDIR=/home/qtest
}
QSystem::processEnvValue(envList, value);
envList == {
export PATH=/home/myname/bin:/home/bin
export QTDIR=/home/qt
export QTESTDIR=/home/qtest
}
Example2:
envString == "cd $(QTDIR)/bin"
envList == {
export PATH=foo
export QTDIR=/home/qt
export QTESTDIR=/home/qtest
}
QSystem::processEnvValue(envList, value);
envString == "cd /home/qt/bin"
\sa getEnvList()
*/
bool QSystem::processEnvValue(QStringList *envList, QString &envString)
{
if (envList == 0)
return false;
QString _envString = envString;
QString prefix;
bool isSetCmd = false;
if (_envString.startsWith("export ")) {
_envString = _envString.mid(7);
prefix = "export ";
isSetCmd = true;
}
if (_envString.startsWith("set ")) {
_envString = _envString.mid(4);
prefix = "set ";
isSetCmd = true;
}
if (isSetCmd) {
int pos = _envString.indexOf("=");
if (pos < 0) {
// nothing to do
return false;
}
QString key = _envString.left(pos);
QString value = _envString.mid(pos + 1);
if (processEnvValue(envList, value)) {
setEnvKey(envList, key, value);
envString = /*prefix +*/ key + "=" + value;
return true;
} else {
return false;
}
} else {
int pos = -1;
int start = -1;
QString key;
QString replacementValue;
while (hasEnvKey(_envString, key, pos, start)) {
// prevent infinite loops! If there is no value we replace the key with an empty string
replacementValue = envKey(envList, key);
int len = key.length()+1;
if (_envString.at(pos) == '%')
len++;
if (_envString.indexOf("("+ key + ")") == (pos + 1))
len += 2;
_envString.remove(pos, len);
_envString.insert(pos, replacementValue);
start = pos + 1;
}
// We really can't be sure we're dealing with a path...
envString = _envString;
return true;
}
}
/*!
Searches the given \a envString for the specified \a key after position
\a start.
If the \a key is found, \a pos returns the position of the key in the string and
the function returns true.
*/
bool QSystem::hasEnvKey(const QString &envString, QString &key, int &pos, int start)
{
pos = -1;
key = "";
int end = -1;
bool winKey = false;
// we actually want to start after the position we specify
++start;
int pos1, pos2, pos3;
pos1 = envString.indexOf("$", start);
pos2 = envString.indexOf("%", start);
pos3 = envString.indexOf("%", pos2 + 1);
if (pos1 < 0 && pos2 < 0)
return false;
if (pos1 < 0) {
if (pos3 < 0)
return false;
pos = pos2;
winKey = true; // must search for a terminating % char...
} else if (pos2 < 0) {
pos = pos1;
} else {
if (pos1 < pos2) {
pos = pos1;
} else {
if ((pos3 < 0) || (pos3 > pos1)) {
pos = pos1;
} else {
pos = pos2;
winKey = true; // must search for a terminating % char...
}
}
}
if (pos >= start) {
end = -1;
if (winKey) {
// if we found a % we only look for a closing one
end = envString.indexOf("%", pos+1);
} else {
// else look for some other characters that close a KEY
const uint maxSrch = 8;
int term[maxSrch];
term[0] = envString.indexOf("/", pos+1);
term[1] = envString.indexOf(":", pos+1);
term[2] = envString.indexOf("\\", pos+1);
term[3] = envString.indexOf(";", pos+1);
term[4] = envString.indexOf(" ", pos+1);
term[5] = envString.indexOf("-", pos+1);
term[6] = envString.indexOf(".", pos+1);
term[7] = envString.length();
// now lets see which char comes first after pos: Thats the one we are looking for.
for (uint i = 0; i < maxSrch; ++i) {
if (end < 0)
end = term[i];
else if ((term[i] >= 0) && (term[i] < end))
end = term[i];
}
}
if (end > pos) {
int extraKey = 0;
if (winKey)
extraKey = 1;
QString tmpKey = envString.mid(pos + 1, end - (pos+1));
// see if we have a string that looks like $(QTDIR) and convert it to QTDIR
if (tmpKey.startsWith("(") && tmpKey.endsWith(")"))
tmpKey = tmpKey.mid(1, tmpKey.length()-2);
if (!tmpKey.isEmpty()) {
key = tmpKey;
return true;
}
}
}
return false;
}
/*!
Removes any occurance of environment \a key from the environment \a list.
The function returns true if the list was valid and no more instances of \a key
exist in the list.
*/
bool QSystem::unsetEnvKey(QStringList *list, const QString &key)
{
if (list == 0)
return false;
if (list->size() == 0)
return true;
QString envKey = key.toUpper();
QStringList::Iterator it;
for (int i = list->size() - 1; i > 0; --i) {
QString s = list->at(i);
int pos = s.indexOf("=");
if (pos > 0) {
QString keyName = (s.left(pos)).toUpper();
if (keyName == envKey) {
list->removeAt(i);
}
}
}
return true;
}
/*!
Replaces or appends an environment \a key with \a value in the environment \a list.
The key/value will be appended to the list if it is not found.
*/
bool QSystem::setEnvKey(QStringList *list, const QString &key, const QString &value)
{
if (list == 0)
return false;
QString envKey = key.toUpper();
QString envValue = value;
QString replacementValue;
int pos;
int start = -1;
bool found;
do {
found = false;
QString tmpKey;
if (hasEnvKey(envValue, tmpKey, pos, start)) {
replacementValue = QSystem::envKey(list, tmpKey.toUpper());
if (!replacementValue.isEmpty()) {
int len = tmpKey.length() + 1;
if (envValue.at(pos) == '%')
++len;
envValue.remove(pos, len);
envValue.insert(pos, replacementValue);
}
found = true;
start = pos + 1;
}
} while ((pos >= 0) && found);
QStringList::Iterator end = list->end();
for (QStringList::Iterator it = list->begin(); it != end; ++it) {
QString s = *it;
pos = s.indexOf("=");
if (pos > 0) {
QString keyName = (s.left(pos)).toUpper();
if (keyName == envKey) {
*it = envKey + "=" + envValue;
list->sort();
return true;
}
}
}
list->append(envKey + "=" + envValue);
list->sort();
return true;
}
void QSystem::addEnvPath(QStringList *environment, const QString &key, const QString &addedPath)
{
QString dyldPath = QSystem::envKey(environment, key);
if (!dyldPath.contains(addedPath)) {
#ifdef Q_OS_WIN
dyldPath = addedPath + ";" + dyldPath;
#else
dyldPath = addedPath + ":" + dyldPath;
#endif
QSystem::setEnvKey(environment, key, dyldPath);
}
}
/*!
Searches the environment \a list for a \a key.
If the key is found the function retuns true and \a value returns the value found in the
list.
*/
QString QSystem::envKey(QStringList *list, const QString &key)
{
QString value;
if (list == 0)
return "";
QString srchKey = key.toUpper();
int pos;
QStringList::Iterator end = list->end();
for (QStringList::Iterator it = list->begin(); it != end; ++it) {
QString s = *it;
pos = s.indexOf("=");
if (pos > 0) {
QString keyName = (s.left(pos)).toUpper();
if (keyName == srchKey) {
value = s.mid(pos+1);
if (value.endsWith(";%" + keyName + "%")) {
value = value.left(value.length() - (3 + keyName.length()));
} else if (value.endsWith(":$" + keyName)) {
value = value.left(value.length() - (2 + keyName.length()));
}
return value;
}
}
}
return "";
}

View File

@@ -0,0 +1,54 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef QSYSTEM_H
#define QSYSTEM_H
#include <QString>
class QSystem
{
public:
static QString which(const QString &path, const QString &applicationName);
static bool hasEnvKey(const QString &envString, QString &key, int &pos, int start = 0);
static bool unsetEnvKey(QStringList *list, const QString &key);
static bool setEnvKey(QStringList *list, const QString &key, const QString &value);
static QString envKey(QStringList *list, const QString &key);
static bool processEnvValue(QStringList *list, QString &envString);
static void addEnvPath(QStringList *environment, const QString &key, const QString &addedPath);
static QString userName();
static QString hostName();
static QString OSName();
};
#endif

View File

@@ -0,0 +1,62 @@
TARGET = QtTest
TEMPLATE = lib
DEFINES += QTCREATOR_QTEST
DEFINES += QTTEST_PLUGIN_LEAN
include(../../qtcreatorplugin.pri)
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/texteditor/texteditor.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/debugger/debugger.pri)
include(../../plugins/qtsupport/qtsupport.pri)
include(../../plugins/remotelinux/remotelinux.pri)
include(../../plugins/qt4projectmanager/qt4projectmanager.pri)
include(../../libs/utils/utils.pri)
include(../../libs/qmljs/qmljs.pri)
include(../../libs/cplusplus/cplusplus.pri)
QT += network
FORMS += newtestfunctiondlg.ui \
selectdlg.ui \
recorddlg.ui \
testsettingspropertiespage.ui \
newtestcasedlg.ui \
addmanualtestdlg.ui
HEADERS += qttestplugin.h \
dialogs.h \
newtestcasedlg.h \
qsystem.h \
resultsview.h \
testselector.h \
testcode.h \
testconfigurations.h \
testexecuter.h \
testgenerator.h \
testsettings.h \
testsuite.h \
testoutputwindow.h \
testcontextmenu.h \
testsettingspropertiespage.h \
addmanualtestdlg.h \
testresultuploader.h
SOURCES += qttestplugin.cpp \
dialogs.cpp \
newtestcasedlg.cpp \
qsystem.cpp \
resultsview.cpp \
testselector.cpp \
testcode.cpp \
testconfigurations.cpp \
testexecuter.cpp \
testgenerator.cpp \
testsettings.cpp \
testoutputwindow.cpp \
testcontextmenu.cpp \
testsettingspropertiespage.cpp \
addmanualtestdlg.cpp \
testresultuploader.cpp
RESOURCES += qttest.qrc

View File

@@ -0,0 +1,14 @@
<RCC>
<qresource prefix="/">
<file alias="testrecord.png">images/testrecord.png</file>
<file alias="testrun.png">images/testrun.png</file>
<file alias="testlearn.png">images/testlearn.png</file>
<file alias="teststop.png">images/teststop.png</file>
<file alias="breakpoint.png">images/breakpoint.png</file>
<file alias="breakstep.png">images/breakstep.png</file>
<file alias="breakcontinue.png">images/breakcontinue.png</file>
<file alias="nextfail.png">images/next_fail.png</file>
<file alias="reload.png">images/reload.png</file>
<file alias="error.png">images/error.png</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,316 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "qttestplugin.h"
#include "testselector.h"
#include "dialogs.h"
#include "qsystem.h"
#include "testsettingspropertiespage.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <qmljseditor/qmljseditorconstants.h>
#include <cppeditor/cppeditorconstants.h>
#include <cpptools/cpptoolsconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <find/ifindsupport.h>
#include <utils/linecolumnlabel.h>
#include <projectexplorer/session.h>
#include <projectexplorer/project.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
#include <debugger/debuggerengine.h>
#include <debugger/debuggerruncontrolfactory.h>
#include <debugger/debuggerstartparameters.h>
#ifdef QTTEST_DEBUGGER_SUPPORT
# include <debugger/qtuitest/qtuitestengine.h>
#endif
#include <QtCore/QDebug>
#include <QtCore/QtPlugin>
#include <QtGui/QAction>
#include <QtGui/QMenu>
#include <QtGui/QMessageBox>
#include <QtGui/QPushButton>
#include <QMenuBar>
#include <QDebug>
#include <QToolButton>
using namespace QtTest::Internal;
Core::NavigationView TestNavigationWidgetFactory::createWidget()
{
Core::NavigationView view;
TestSelector *ptw = new TestSelector();
ptw->rescan();
view.widget = ptw;
QToolButton *filter = new QToolButton;
filter->setIcon(QIcon(Core::Constants::ICON_FILTER));
filter->setToolTip(tr("Filter tree"));
filter->setPopupMode(QToolButton::InstantPopup);
QMenu *filterMenu = new QMenu(filter);
filterMenu->addAction(ptw->m_componentViewMode);
filterMenu->addAction(ptw->m_showUnitTests);
filterMenu->addAction(ptw->m_showIntegrationTests);
filterMenu->addAction(ptw->m_showPerformanceTests);
filterMenu->addAction(ptw->m_showSystemTests);
filter->setMenu(filterMenu);
QToolButton *newTest = new QToolButton;
newTest->setIcon(QIcon(":/core/images/filenew.png"));
newTest->setToolTip(tr("New test"));
newTest->setPopupMode(QToolButton::InstantPopup);
QObject::connect(newTest, SIGNAL(clicked()), ptw,
SLOT(testInsertUnitOrSystemTest()), Qt::DirectConnection);
view.dockToolBarWidgets << filter << newTest;
return view;
}
QString TestNavigationWidgetFactory::displayName() const
{
return "Tests";
}
//******************************************
QtTestPlugin::QtTestPlugin()
{
m_messageOutputWindow = 0;
m_testResultsWindow = 0;
m_contextMenu = new TestContextMenu(this);
}
QtTestPlugin::~QtTestPlugin()
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
pm->removeObject(m_messageOutputWindow);
delete m_messageOutputWindow;
pm->removeObject(m_testResultsWindow);
delete m_testResultsWindow;
delete TestExecuter::instance();
delete m_contextMenu;
}
bool QtTestPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
Q_UNUSED(arguments)
Q_UNUSED(errorMessage)
addAutoReleasedObject(new TestNavigationWidgetFactory);
addAutoReleasedObject(new TestSettingsPanelFactory);
addAutoReleasedObject(new TestConfigurations);
return true;
}
void QtTestPlugin::extensionsInitialized()
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
Core::ICore *core = Core::ICore::instance();
Core::ActionManager *am = core->actionManager();
m_messageOutputWindow = new TestOutputWindow();
pm->addObject(m_messageOutputWindow);
m_testResultsWindow = TestResultsWindow::instance();
connect(m_testResultsWindow, SIGNAL(stopTest()), this, SLOT(stopTesting()));
connect(m_testResultsWindow, SIGNAL(retryFailedTests(QStringList)),
this, SLOT(retryTests(QStringList)));
connect(TestExecuter::instance(), SIGNAL(testStarted()),
m_testResultsWindow, SLOT(onTestStarted()));
connect(TestExecuter::instance(), SIGNAL(testStop()),
m_testResultsWindow, SLOT(onTestStopped()));
connect(TestExecuter::instance(), SIGNAL(testFinished()),
m_testResultsWindow, SLOT(onTestFinished()));
pm->addObject(m_testResultsWindow);
connect(testResultsPane(), SIGNAL(defectSelected(TestCaseRec)),
this, SLOT(onDefectSelected(TestCaseRec)));
// Add context menu to CPP editor
Core::ActionContainer *mcontext = am->actionContainer(CppEditor::Constants::M_CONTEXT);
m_contextMenu->init(mcontext->menu(), 2, this);
// Add context menu to JS editor
mcontext = am->actionContainer(QmlJSEditor::Constants::M_CONTEXT);
m_contextMenu->init(mcontext->menu(), 2, this);
// Add a Test menu to the menu bar
Core::ActionContainer* ac = am->createMenu("QtTestPlugin.TestMenu");
ac->menu()->setTitle(tr("&Test"));
m_contextMenu->init(ac->menu(), 0, 0);
// Insert the "Test" menu between "Window" and "Help".
QMenu *windowMenu = am->actionContainer(Core::Constants::M_TOOLS)->menu();
QMenuBar *menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(windowMenu->menuAction(), ac->menu());
ProjectExplorer::ProjectExplorerPlugin *explorer =
ProjectExplorer::ProjectExplorerPlugin::instance();
connect(core->progressManager(), SIGNAL(allTasksFinished(QString)),
this, SLOT(onAllTasksFinished(QString)));
connect(explorer->session(), SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)),
this, SLOT(onProjectRemoved(ProjectExplorer::Project *)));
m_contextMenu->init(0, 3, this);
}
void QtTestPlugin::onDefectSelected(TestCaseRec rec)
{
if (rec.m_code) {
int line = (rec.m_line > 0 ? rec.m_line : 0);
TextEditor::BaseTextEditorWidget::openEditorAt(rec.m_code->actualFileName(), line);
}
}
void QtTestPlugin::onProjectRemoved(ProjectExplorer::Project *project)
{
if (project == startupProject())
TestConfigurations::instance().setActiveConfiguration(0);
}
void QtTestPlugin::onAllTasksFinished(const QString &t)
{
if ((t == CppTools::Constants::TASK_INDEX) && startupProject())
TestConfigurations::instance().setActiveConfiguration(startupProject());
}
void QtTestPlugin::testRun()
{
runSelectedTests(false, false);
}
void QtTestPlugin::testRunAsManual()
{
runSelectedTests(false, true);
}
void QtTestPlugin::testDebug()
{
Debugger::DebuggerRunControl *runControl = 0;
Debugger::DebuggerStartParameters params;
params.startMode = Debugger::NoStartMode; // we'll start the test runner here
params.executable = ".qtt";
runControl = Debugger::DebuggerPlugin::createDebugger(params);
qDebug() << "Debugger run control" << runControl;
runControl->start();
#ifdef QTTEST_DEBUGGER_SUPPORT
Debugger::Internal::QtUiTestEngine *engine =
qobject_cast<Debugger::Internal::QtUiTestEngine*>(runControl->engine());
TestExecuter::instance()->setDebugEngine(engine);
#endif
runSelectedTests(false, false);
#ifdef QTTEST_DEBUGGER_SUPPORT
TestExecuter::instance()->setDebugEngine(0);
runControl->debuggingFinished();
#endif
}
void QtTestPlugin::testRunSingle()
{
runSelectedTests(true, false);
}
void QtTestPlugin::runSelectedTests(bool singleTest, bool forceManual)
{
m_forceManual = forceManual;
TestExecuter::instance()->runTests(singleTest, forceManual);
}
void QtTestPlugin::stopTesting()
{
TestExecuter::instance()->manualStop();
}
void QtTestPlugin::retryTests(const QStringList &tests)
{
QStringList currentSelection(TestConfigurations::instance().selectedTests());
QStringList newSelection;
foreach (const QString &test, currentSelection) {
QString testName = test.mid(test.lastIndexOf("/") + 1);
if (tests.contains(testName))
newSelection.append(test);
}
TestExecuter::instance()->setSelectedTests(newSelection);
TestExecuter::instance()->runSelectedTests(m_forceManual);
}
void QtTestPlugin::insertTestFunction()
{
TestCode *currentTest = m_testCollection.currentEditedTest();
if (currentTest) {
QString prompt = "<b>" + currentTest->testTypeString()
+ " Test: </b>" + currentTest->testCase();
NewTestFunctionDlg dlg(prompt);
dlg.exec();
if (dlg.result() == QDialog::Accepted) {
QString testFunc = dlg.testFunctionName->text();
// check for duplicate
if (TestFunctionInfo *functionInfo = currentTest->findFunction(testFunc)) {
QMessageBox::critical(0, tr("Error"),
tr("Test function \"%1\" already exists.").arg(testFunc));
currentTest->gotoLine(functionInfo->testStartLine());
return;
}
currentTest->addTestFunction(testFunc, QString(), dlg.insertAtCursor->isChecked());
}
}
}
ProjectExplorer::Project *QtTestPlugin::startupProject()
{
return ProjectExplorer::ProjectExplorerPlugin::instance()->session()->startupProject();
}
Q_EXPORT_PLUGIN(QtTestPlugin)

View File

@@ -0,0 +1,101 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef QTTESTPLUGIN_H
#define QTTESTPLUGIN_H
#include "testoutputwindow.h"
#include "testselector.h"
#include "resultsview.h"
#include "testexecuter.h"
#include "testcontextmenu.h"
#include "testsuite.h"
#include <coreplugin/inavigationwidgetfactory.h>
#include <extensionsystem/iplugin.h>
#include <QtCore/QObject>
namespace QtTest {
namespace Internal {
class TestNavigationWidgetFactory : public Core::INavigationWidgetFactory
{
public:
TestNavigationWidgetFactory() {}
~TestNavigationWidgetFactory() {}
Core::NavigationView createWidget();
QString displayName() const;
QString id() const { return "QtTestNavigationWidget"; }
int priority() const { return 750; }
};
class QtTestPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
QtTestPlugin();
~QtTestPlugin();
bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized();
public slots:
void onDefectSelected(TestCaseRec rec);
void onProjectRemoved(ProjectExplorer::Project *project);
void onAllTasksFinished(const QString &);
void testRun();
void testRunAsManual();
void testDebug();
void testRunSingle();
void stopTesting();
void retryTests(const QStringList &tests);
void insertTestFunction();
protected:
void runSelectedTests(bool singleTest, bool forceManual);
ProjectExplorer::Project *startupProject();
private:
TestOutputWindow *m_messageOutputWindow;
TestResultsWindow *m_testResultsWindow;
TestCollection m_testCollection;
TestContextMenu *m_contextMenu;
bool m_forceManual;
};
} // namespace Internal
} // namespace QtTest
#endif //QTTESTPLUGIN_H

View File

@@ -0,0 +1,108 @@
<ui version="4.0" >
<class>RecordDialog</class>
<widget class="QDialog" name="RecordDialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>562</width>
<height>314</height>
</rect>
</property>
<property name="windowTitle" >
<string>System Test</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QLabel" name="steps_label" >
<property name="text" >
<string>Manual steps to record</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="steps_view" >
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>Events are now being recorded and scripting code will be added to the field below. When you have finished recording events, copy the text from the field and click 'Stop'.</string>
</property>
<property name="wordWrap" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="codeEdit" >
<property name="font" >
<font>
<family>Courier New</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="readOnly" >
<bool>true</bool>
</property>
<property name="acceptRichText" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QPushButton" name="abort_button" >
<property name="text" >
<string>Abort</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>371</width>
<height>26</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="stopButton" >
<property name="text" >
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>stopButton</sender>
<signal>clicked()</signal>
<receiver>RecordDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>504</x>
<y>291</y>
</hint>
<hint type="destinationlabel" >
<x>419</x>
<y>295</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,697 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "resultsview.h"
#include <projectexplorer/projectexplorerconstants.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/uniqueidmanager.h>
#include <QHeaderView>
#include <QResizeEvent>
#include <QSize>
#include <QTimer>
#include <QFileInfo>
#include <QDesktopServices>
#include <QUrl>
#include <QToolButton>
#include <QAction>
#include <QMenu>
#include <QClipboard>
#include <QApplication>
#include <QDebug>
enum {
RES_SIZE = 100,
RESULT_POS = 0,
DETAILS_POS = 1,
REASON_POS = 2,
SCREEN_POS = 3
};
// Role for data which holds the identifier for use with m_pendingScreenshots
static const int ScreenshotIdRole = Qt::UserRole + 10;
// Role for the link to the .png file of a failure screenshot
static const int ScreenshotLinkRole = Qt::UserRole + 100;
static QBrush passBrush(QColor("lightgreen"));
static QBrush failBrush(QColor("orangered"));
static QBrush unexpectedBrush(QColor("orange"));
/*
Constructs a screenshot ID for the test failure at the given \a file and
\a line.
*/
QString screenshotId(const QString &file, int line)
{
return QString("%1 %2").arg(QFileInfo(file).canonicalFilePath()).arg(line);
}
ResultsView::ResultsView(QWidget *parent, const char *name) :
QTableWidget(parent)
{
setObjectName(name);
setColumnCount(3);
setGridStyle(Qt::NoPen);
m_showPassing = m_testSettings.showPassedResults();
m_showDebug = m_testSettings.showDebugResults();
m_showSkipped = m_testSettings.showSkippedResults();
setHorizontalHeaderLabels(QStringList() << tr("Result")
<< tr("Test Details") << tr("Description"));
resize(width());
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSortingEnabled(false);
setAlternatingRowColors(true);
setEditTriggers(QAbstractItemView::NoEditTriggers);
verticalHeader()->hide();
horizontalHeader()->show();
m_lastRow = -1;
m_ignoreEvent = false;
m_userLock = false;
connect(this, SIGNAL(currentCellChanged(int,int,int,int)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(this, SIGNAL(itemClicked(QTableWidgetItem*)),
this, SLOT(onItemClicked(QTableWidgetItem*)), Qt::DirectConnection);
setWordWrap(true);
}
ResultsView::~ResultsView()
{
}
void ResultsView::resize(int width)
{
resizeColumnToContents(RESULT_POS);
if (columnWidth(RESULT_POS) < RES_SIZE)
setColumnWidth(RESULT_POS, RES_SIZE);
resizeColumnToContents(DETAILS_POS);
if (columnWidth(DETAILS_POS) < RES_SIZE)
setColumnWidth(DETAILS_POS, RES_SIZE);
setColumnWidth(DETAILS_POS, columnWidth(DETAILS_POS) + 20);
setColumnWidth(REASON_POS, width - columnWidth(RESULT_POS) - columnWidth(DETAILS_POS));
}
void ResultsView::resizeEvent(QResizeEvent *event)
{
resize(event->size().width());
}
void ResultsView::clear()
{
setUpdatesEnabled(false);
disconnect(this, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(onChanged()));
clearContents();
setRowCount(0);
connect(this, SIGNAL(currentCellChanged(int,int,int,int)),
this, SLOT(onChanged()), Qt::DirectConnection);
setUpdatesEnabled(true);
m_ignoreEvent = false;
m_userLock = false;
m_failedTests.clear();
}
/*
Called when the test runner tells us it has taken a screenshot due to
failure.
Note that, since we determine test failures by parsing output, this could happen
before or after we see the actual test failure.
*/
void ResultsView::addScreenshot(const QString &screenshot, const QString &testfunction,
const QString& file, int line)
{
Q_UNUSED(testfunction);
QString id = screenshotId(file, line);
// We may have received the screenshot before the test result it matches.
m_pendingScreenshots[id] = screenshot;
updateScreenshots();
}
/*
Iterates through the test results and generates links to screenshots
for any that have a screenshot available.
*/
void ResultsView::updateScreenshots()
{
for (int row = 0; row < rowCount(); ++row) {
QTableWidgetItem *result = item(row, RESULT_POS);
if (!result)
continue;
// If there is a screenshot for this result, put a link to it in the table.
QString id = result->data(ScreenshotIdRole).toString();
if (!m_pendingScreenshots.contains(id))
continue;
QString screenshot = m_pendingScreenshots.take(id);
QTableWidgetItem* shot = new QTableWidgetItem(QIcon(QPixmap(":/testrun.png")), QString());
shot->setData(ScreenshotLinkRole, screenshot);
shot->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
setItem(row, SCREEN_POS, shot);
}
}
/*
Opens any screenshot linked to from \a item.
Called when \a item is clicked.
*/
void ResultsView::onItemClicked(QTableWidgetItem* item)
{
QString shot = item->data(ScreenshotLinkRole).toString();
if (shot.isEmpty())
return;
// Open the screenshot using the preferred image viewer.
QDesktopServices::openUrl(QUrl::fromLocalFile(shot));
}
void ResultsView::append(const QString &res, const QString &test, const QString &reason, const QString &dataTag, const QString &file, const QString &line)
{
int row = rowCount();
insertRow(row);
QTableWidgetItem* result = new QTableWidgetItem(res);
result->setTextAlignment(Qt::AlignCenter);
if (res.startsWith("PASS")) {
result->setBackground(passBrush);
setRowHidden(row, !m_showPassing);
} else if (res.startsWith("FAIL")) {
result->setBackground(failBrush);
} else if (res.startsWith("QDEBUG")) {
setRowHidden(row, !m_showDebug);
} else if (res.startsWith("SKIP")) {
setRowHidden(row, !m_showSkipped);
} else if (res.startsWith("XFAIL") || res.startsWith("XPASS")) {
result->setBackground(unexpectedBrush);
}
if ((res.contains("FAIL") || res.startsWith("XPASS")) && !m_failedTests.contains(test))
m_failedTests.append(test);
// Construct a result id for use in mapping test failures to screenshots.
QString resultId = screenshotId(file, line.toInt());
result->setData(ScreenshotIdRole, resultId);
QTableWidgetItem *testDetails = new QTableWidgetItem(formatTestDetails(test, dataTag));
testDetails->setToolTip(formatLocation(file, line));
setItem(row, RESULT_POS, result);
setItem(row, DETAILS_POS, testDetails);
setItem(row, REASON_POS, new QTableWidgetItem(reason));
resize(width());
resizeRowToContents(row);
if (currentRow() == -1)
scrollToItem(item(row, REASON_POS));
m_resultsWindow->navigateStateChanged();
updateScreenshots();
}
QString ResultsView::xmlDequote(const QString &input)
{
QString result = input;
return result.replace(QLatin1String("&gt;"), QLatin1String(">"))
.replace(QLatin1String("&lt;"), QLatin1String("<"))
.replace(QLatin1String("&apos;"), QLatin1String("'"))
.replace(QLatin1String("&quot;"), QLatin1String("\""))
.replace(QLatin1String("&amp;"), QLatin1String("&"))
.replace(QLatin1String("&#x002D;"), QLatin1String("-"));
}
QString ResultsView::htmlQuote(const QString &input)
{
QString result=input;
return result.replace(QLatin1String("&"), QLatin1String("&amp;"))
.replace(QLatin1String(">"), QLatin1String("&gt;"))
.replace(QLatin1String("<"), QLatin1String("&lt;"))
.replace(QLatin1String("\""), QLatin1String("&quot;"))
.replace(QLatin1String("\n"), QLatin1String("<br />\n"));
}
QString ResultsView::formatTestDetails(const QString &test, const QString &dataTag)
{
QString ret = test;
if (!dataTag.isEmpty() && dataTag != "...")
ret += " (" + dataTag + ")";
return ret;
}
QString ResultsView::formatLocation(const QString &file, const QString &line)
{
QString description;
QString _file = file;
if (_file.startsWith("["))
_file = _file.mid(1);
if (_file != "" || line != "") {
description += xmlDequote(file);
if (line != "-1")
description += ":" + line;
}
return description;
}
QString ResultsView::result(int row)
{
if (row >= rowCount())
return false;
return item(row, RESULT_POS)->text().simplified();
}
QString ResultsView::reason(int row)
{
if (row >= rowCount())
return false;
QString txt = item(row, REASON_POS)->text();
int pos = txt.indexOf("\n");
if (pos > 0)
txt = txt.left(pos);
return txt.simplified();
}
QString ResultsView::location(int row)
{
if (row >= rowCount())
return false;
return item(row, DETAILS_POS)->toolTip();
}
QString ResultsView::file(int row)
{
QString txt = location(row);
if (!txt.isEmpty()) {
int pos = txt.indexOf(":");
if (pos >= 0)
txt = txt.left(pos);
return txt.simplified();
}
return "";
}
QString ResultsView::line(int row)
{
QString txt = location(row);
if (!txt.isEmpty()) {
int pos = txt.indexOf(":");
if (pos >= 0)
txt = txt.mid(pos + 1);
else txt = "";
return txt.simplified();
}
return "";
}
int ResultsView::intLine(int row)
{
if (row >= rowCount())
return false;
return line(row).toInt();
}
void ResultsView::setResult(const QString &result, const QString &test, const QString &reason, const QString &dataTag, const QString &file, int line)
{
int row;
QString lineStr(QString::number(line));
append(result, test, reason, dataTag, file, lineStr);
row = rowCount()-1;
}
void ResultsView::onChanged()
{
if (!m_ignoreEvent) {
if (currentColumn() == 0)
m_userLock = false;
else
m_userLock = true;
}
int row = currentRow();
m_lastRow = row;
if (m_ignoreEvent || row >= rowCount())
return;
m_resultsWindow->navigateStateChanged();
QTimer::singleShot(0, this, SLOT(emitCurSelection()));
}
void ResultsView::emitCurSelection()
{
emitSelection(m_lastRow);
}
void ResultsView::emitSelection(int row)
{
if (row < 0)
return;
TestCaseRec rec;
rec.m_testFunction = "";
rec.m_line = intLine(row);
TestCode *tmp = m_testCollection.findCode(file(row), "", "");
rec.m_code = tmp;
emit defectSelected(rec);
}
void ResultsView::setResultsWindow(TestResultsWindow *window)
{
m_resultsWindow = window;
}
TestResultsWindow* ResultsView::resultsWindow() const
{
return m_resultsWindow;
}
void ResultsView::showPassing(bool show)
{
m_showPassing = show;
updateHidden("PASS", show);
m_testSettings.setShowPassedResults(show);
}
void ResultsView::showDebugMessages(bool show)
{
m_showDebug = show;
updateHidden("QDEBUG", show);
m_testSettings.setShowDebugResults(show);
}
void ResultsView::showSkipped(bool show)
{
m_showSkipped = show;
updateHidden("SKIP", show);
m_testSettings.setShowSkippedResults(show);
}
void ResultsView::updateHidden(const QString &result, bool show)
{
for (int row = 0; row < rowCount(); ++row) {
QTableWidgetItem *resultItem = item(row, RESULT_POS);
if (resultItem && resultItem->text().startsWith(result))
setRowHidden(row, !show);
}
resize(width());
m_resultsWindow->navigateStateChanged();
}
// **********************************************************
ResultsView *testResultsPane()
{
return TestResultsWindow::instance()->resultsView();
}
TestResultsWindow *_testResultsInstance = 0;
TestResultsWindow *TestResultsWindow::instance()
{
if (!_testResultsInstance) {
_testResultsInstance = new TestResultsWindow();
}
return _testResultsInstance;
}
TestResultsWindow::TestResultsWindow() :
m_stopAction(new QAction(QIcon(QLatin1String(ProjectExplorer::Constants::ICON_STOP)),
tr("Stop Testing"), this)),
m_retryAction(new QAction(QIcon(QLatin1String(":/reload.png")),
tr("Retry Failed Tests"), this)),
m_copyAction(new QAction(QIcon(QLatin1String(Core::Constants::ICON_COPY)),
tr("Copy Results"), this)),
m_stopButton(new QToolButton),
m_retryButton(new QToolButton),
m_copyButton(new QToolButton),
m_filterButton(new QToolButton)
{
m_resultsView = new ResultsView;
m_resultsView->setResultsWindow(this);
m_resultsView->setFrameStyle(QFrame::NoFrame);
connect(&m_testSettings, SIGNAL(changed()), this, SLOT(onSettingsChanged()));
m_stopAction->setToolTip(tr("Stop Testing"));
m_stopAction->setEnabled(false);
m_retryAction->setToolTip(tr("Retry Failed Tests"));
m_retryAction->setEnabled(false);
m_copyAction->setToolTip(tr("Copy Results"));
m_copyAction->setEnabled(false);
m_filterButton->setIcon(QIcon(Core::Constants::ICON_FILTER));
m_filterButton->setToolTip(tr("Filter Results"));
m_filterButton->setPopupMode(QToolButton::InstantPopup);
m_showPassingAction = new QAction(tr("Show Passing Tests"), this);
m_showPassingAction->setCheckable(true);
m_showPassingAction->setChecked(m_testSettings.showPassedResults());
connect(m_showPassingAction, SIGNAL(toggled(bool)), m_resultsView, SLOT(showPassing(bool)));
m_showDebugAction = new QAction(tr("Show Debug Messages"), this);
m_showDebugAction->setCheckable(true);
m_showDebugAction->setChecked(m_testSettings.showDebugResults());
connect(m_showDebugAction, SIGNAL(toggled(bool)), m_resultsView, SLOT(showDebugMessages(bool)));
m_showSkipAction = new QAction(tr("Show Skipped Tests"), this);
m_showSkipAction->setCheckable(true);
m_showSkipAction->setChecked(m_testSettings.showSkippedResults());
connect(m_showSkipAction, SIGNAL(toggled(bool)), m_resultsView, SLOT(showSkipped(bool)));
QMenu *filterMenu = new QMenu(m_filterButton);
filterMenu->addAction(m_showPassingAction);
filterMenu->addAction(m_showDebugAction);
filterMenu->addAction(m_showSkipAction);
m_filterButton->setMenu(filterMenu);
Core::ActionManager *am = Core::ICore::instance()->actionManager();
Core::Context globalcontext(Core::Constants::C_GLOBAL);
Core::Command *stopCmd = am->registerAction(m_stopAction,
Core::Id("Qt4Test.StopTest"), globalcontext);
Core::Command *retryCmd = am->registerAction(m_retryAction,
Core::Id("Qt4Test.RetryFailed"), globalcontext);
Core::Command *copyCmd = am->registerAction(m_copyAction,
Core::Id("Qt4Test.CopyResults"), globalcontext);
m_stopButton->setDefaultAction(stopCmd->action());
m_stopButton->setAutoRaise(true);
m_retryButton->setDefaultAction(retryCmd->action());
m_retryButton->setAutoRaise(true);
m_copyButton->setDefaultAction(copyCmd->action());
m_copyButton->setAutoRaise(true);
connect(m_stopAction, SIGNAL(triggered()), this, SIGNAL(stopTest()));
connect(m_retryAction, SIGNAL(triggered()), this, SLOT(retryFailed()));
connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copyResults()));
}
TestResultsWindow::~TestResultsWindow()
{
delete m_resultsView;
_testResultsInstance = 0;
}
bool TestResultsWindow::hasFocus()
{
return m_resultsView->hasFocus();
}
bool TestResultsWindow::canFocus()
{
return true;
}
void TestResultsWindow::setFocus()
{
m_resultsView->setFocus();
}
void TestResultsWindow::clearContents()
{
m_resultsView->clear();
m_retryAction->setEnabled(false);
m_copyAction->setEnabled(false);
navigateStateChanged();
}
QWidget *TestResultsWindow::outputWidget(QWidget *parent)
{
m_resultsView->setParent(parent);
return m_resultsView;
}
QString TestResultsWindow::name() const
{
return tr("Test Results");
}
void TestResultsWindow::visibilityChanged(bool /*b*/)
{
}
int TestResultsWindow::priorityInStatusBar() const
{
return 50;
}
bool TestResultsWindow::canNext()
{
for (int i = m_resultsView->currentRow() + 1; i < m_resultsView->rowCount(); ++i) {
if (!m_resultsView->isRowHidden(i))
return true;
}
return false;
}
bool TestResultsWindow::canPrevious()
{
for (int i = m_resultsView->currentRow() - 1; i >= 0; --i) {
if (!m_resultsView->isRowHidden(i))
return true;
}
return false;
}
void TestResultsWindow::goToNext()
{
for (int i = m_resultsView->currentRow() + 1; i < m_resultsView->rowCount(); ++i) {
if (!m_resultsView->isRowHidden(i)) {
m_resultsView->setCurrentCell(i, 0);
return;
}
}
}
void TestResultsWindow::goToPrev()
{
for (int i = m_resultsView->currentRow() - 1; i >= 0; --i) {
if (!m_resultsView->isRowHidden(i)) {
m_resultsView->setCurrentCell(i, 0);
return;
}
}
}
bool TestResultsWindow::canNavigate()
{
return true;
}
QList<QWidget*> TestResultsWindow::toolBarWidgets() const
{
return QList<QWidget*>() << m_filterButton << m_stopButton << m_retryButton << m_copyButton;
}
void TestResultsWindow::addResult(const QString &result, const QString &test, const QString &reason,
const QString &dataTag, const QString &file, int line)
{
m_resultsView->setResult(result, test, reason, dataTag, file, line);
}
void TestResultsWindow::onTestStarted()
{
m_stopAction->setEnabled(true);
m_retryAction->setEnabled(false);
m_copyAction->setEnabled(false);
}
void TestResultsWindow::onTestStopped()
{
m_stopAction->setEnabled(false);
m_retryAction->setEnabled(false);
m_copyAction->setEnabled(false);
}
void TestResultsWindow::onTestFinished()
{
m_stopAction->setEnabled(false);
m_retryAction->setEnabled(!m_resultsView->failedTests().isEmpty());
m_copyAction->setEnabled(true);
}
void TestResultsWindow::retryFailed()
{
emit retryFailedTests(m_resultsView->failedTests());
}
void TestResultsWindow::copyResults()
{
m_resultsView->copyResults();
}
void ResultsView::copyResults()
{
QMimeData *md = new QMimeData();
QString html("<html><table>");
QString text;
for (int row = 0; row < rowCount(); ++row) {
QString result = item(row, RESULT_POS)->text().trimmed();
QString detail = item(row, DETAILS_POS)->text();
QString location = item(row, DETAILS_POS)->toolTip();
QString reason = item(row, REASON_POS)->text();
html += QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td></tr>")
.arg(result).arg(detail).arg(location).arg(htmlQuote(reason));
text += QString("%1\n%2\n%3\n%4\n").arg(result).arg(detail).arg(location).arg(reason);
}
html += "</table></html>";
md->setHtml(html);
md->setText(text);
QApplication::clipboard()->setMimeData(md);
}
void TestResultsWindow::onSettingsChanged()
{
if (m_showPassingAction->isChecked() != m_testSettings.showPassedResults())
m_showPassingAction->setChecked(m_testSettings.showPassedResults());
if (m_showDebugAction->isChecked() != m_testSettings.showDebugResults())
m_showDebugAction->setChecked(m_testSettings.showDebugResults());
if (m_showSkipAction->isChecked() != m_testSettings.showSkippedResults())
m_showSkipAction->setChecked(m_testSettings.showSkippedResults());
}

View File

@@ -0,0 +1,182 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef RESULTSVIEW_H
#define RESULTSVIEW_H
#include "testsuite.h"
#include "testsettings.h"
#include <coreplugin/ioutputpane.h>
#include <QTableWidget>
class ResultsView;
class TestResultsWindow;
class QToolButton;
ResultsView *testResultsPane();
class ResultsView : public QTableWidget
{
Q_OBJECT
public:
ResultsView(QWidget *parent = 0, const char *name = 0);
virtual ~ResultsView();
QString result(int row);
QString reason(int row);
QString dataTag(int row);
QString file(int row);
QString line(int row);
int intLine(int row);
void reselect();
virtual void clear();
void setResult(const QString &result, const QString &test, const QString &reason,
const QString &dataTag, const QString &file, int line);
void setResultsWindow(TestResultsWindow * = 0);
TestResultsWindow *resultsWindow() const;
QStringList failedTests() const { return m_failedTests; }
void copyResults();
public slots:
void addScreenshot(const QString &screenshot,
const QString &testfunction, const QString &file, int line);
signals:
void defectSelected(TestCaseRec rec);
private:
QString formatTestDetails(const QString &test, const QString &dataTag);
QString formatLocation(const QString &file, const QString &line);
void append(const QString &res, const QString &test, const QString &reason,
const QString &dataTag, const QString &file, const QString &line);
void resize(int width);
void resizeEvent(QResizeEvent *event);
void emitSelection(int row);
QString location(int row);
void updateScreenshots();
static QString xmlDequote(const QString &input);
static QString htmlQuote(const QString &input);
void updateHidden(const QString &result, bool show);
int m_lastRow;
int m_usedRows;
bool m_ignoreEvent;
bool m_userLock;
QMap<QString,QString> m_pendingScreenshots;
TestCollection m_testCollection;
TestResultsWindow *m_resultsWindow;
bool m_showPassing;
bool m_showDebug;
bool m_showSkipped;
QStringList m_failedTests;
TestSettings m_testSettings;
private slots:
void onChanged();
void emitCurSelection();
void onItemClicked(QTableWidgetItem *);
void showPassing(bool);
void showDebugMessages(bool);
void showSkipped(bool);
};
class TestResultsWindow : public Core::IOutputPane
{
Q_OBJECT
public:
TestResultsWindow();
~TestResultsWindow();
static TestResultsWindow *instance();
virtual QString displayName() const { return "Test Results"; }
QWidget *outputWidget(QWidget *parent);
QList<QWidget*> toolBarWidgets() const;
QString name() const;
int priorityInStatusBar() const;
void clearContents();
void visibilityChanged(bool visible);
bool canFocus();
bool hasFocus();
void setFocus();
virtual bool canNext();
virtual bool canPrevious();
virtual void goToNext();
virtual void goToPrev();
bool canNavigate();
ResultsView *resultsView() { return m_resultsView; }
void addResult(const QString &result, const QString &test, const QString &reason,
const QString &dataTag, const QString &file, int line);
signals:
void stopTest();
void retryFailedTests(const QStringList &);
public slots:
void onTestStarted();
void onTestStopped();
void onTestFinished();
void retryFailed();
void copyResults();
void onSettingsChanged();
private:
TestSettings m_testSettings;
ResultsView *m_resultsView;
QAction *m_stopAction;
QAction *m_retryAction;
QAction *m_copyAction;
QAction *m_showPassingAction;
QAction *m_showDebugAction;
QAction *m_showSkipAction;
QToolButton *m_stopButton;
QToolButton *m_retryButton;
QToolButton *m_copyButton;
QToolButton *m_filterButton;
};
#endif

View File

@@ -0,0 +1,86 @@
<ui version="4.0" >
<class>SelectDlg</class>
<widget class="QDialog" name="SelectDlg" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>368</width>
<height>302</height>
</rect>
</property>
<property name="windowTitle" >
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QLabel" name="instructLabel" >
<property name="text" >
<string>Select something</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="groupsList" >
<property name="verticalScrollBarPolicy" >
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="alternatingRowColors" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SelectDlg</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SelectDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTCODE_H
#define TESTCODE_H
#include "testconfigurations.h"
#include <texteditor/basetexteditor.h>
#include <coreplugin/icontext.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <cplusplus/CppDocument.h>
#include <QStringList>
#include <QDate>
#include <QPointer>
#include <QTimer>
class QVConfig;
class TestCollection_p;
namespace Core {
class IEditor;
}
namespace CPlusPlus {
class CppModelManagerInterface;
}
class SystemTestCodeSync;
class TestFunctionInfo : public QObject
{
Q_OBJECT
public:
TestFunctionInfo();
TestFunctionInfo(TestFunctionInfo &other);
virtual ~TestFunctionInfo();
void reset();
static bool validFunctionName(const QString &funcName);
bool needsRevision();
TestFunctionInfo& operator=(const TestFunctionInfo &other);
void setFunctionName(const QString &nm) { m_functionName = nm; }
QString functionName() const { return m_functionName; }
void setManualTest(bool isManual) { m_isManualTest = isManual; }
bool isManualTest() const { return m_isManualTest; }
void setTestStart(int s) { m_testStart = s; }
int testStart() const { return m_testStart; }
void setTestStartLine(int s) { m_testStartLine = s; }
int testStartLine() const { return m_testStartLine; }
void setTestEnd(int e) { m_testEnd = e; }
int testEnd() const { return m_testEnd; }
void setDeclarationStart(int s) { m_declStart = s; }
int declarationStart() const { return m_declStart; }
void setDeclarationStartLine(int s) { m_declStartLine = s; }
int declarationStartLine() const { return m_declStartLine; }
void setDeclarationEnd(int e) { m_declEnd = e; }
int declarationEnd() const { return m_declEnd; }
void setTestGroups(const QString &grps) { m_testGroups = grps; }
QString testGroups() const { return m_testGroups; }
void processDocBlock(const QStringList &docBlock);
private:
QString m_functionName;
bool m_isManualTest;
int m_testStart;
int m_testStartLine;
int m_testEnd;
int m_declStart;
int m_declStartLine;
int m_declEnd;
QString m_testGroups;
};
class TestCode : public QObject
{
Q_OBJECT
public:
enum TestType {
TypeUnknownTest = 0x1,
TypeUnitTest = 0x2,
TypeIntegrationTest = 0x4,
TypePerformanceTest = 0x8,
TypeSystemTest = 0x10
};
Q_DECLARE_FLAGS(TestTypes, TestType)
TestCode(const QString &basePath, const QString &extraPath, const QString &fileName);
virtual ~TestCode();
uint testFunctionCount();
void clearTestFunctions();
TestFunctionInfo *currentTestFunction();
TestFunctionInfo *testFunction(int index);
TestFunctionInfo *findFunction(int line, bool next);
TestFunctionInfo *findFunction(const QString &funcName);
bool testFunctionExists(QString funcName);
bool requirementIsTested(const QString &reqID);
QString visualBasePath();
QString actualBasePath();
QString externalBasePath();
QString fullVisualSuitePath(bool componentViewMode) const;
QString baseFileName() const; // just the file name part
QString targetFileName(const QString &buildPath) const;
QString actualFileName() const;
QString visualFileName(bool componentViewMode) const;
QString projectFileName();
QString execFileName();
QString testedComponent() const;
QString testedClass() const;
QString testedFile() const;
QString testCase() const;
TestType testType() const;
QString testTypeString() const;
void save(bool force = false);
bool openTestInEditor(const QString &testFunction);
Core::IEditor *editor();
bool gotoLine(int lineNumber);
void addTestFunction(const QString &newFuncName, const QString &newFuncHeader,
bool insertAtCursorPosition);
bool hasUnsavedChanges() const;
bool isInitialized() const;
bool isErrored() const;
void setDocument(QmlJS::Document::Ptr doc);
void setDocument(CPlusPlus::Document::Ptr doc);
signals:
void testChanged(TestCode *testCode);
void testRemoved(TestCode *testCode);
void changed();
public slots:
void onContextHelpIdRequested(TextEditor::ITextEditor *editor, int position);
void parseDocument();
private:
friend class SystemTestCodeSync;
friend class UnitTestCodeSync;
bool parseComments(const QString&);
TestFunctionInfo *processFunction(const QString&, int, int, int);
void setManualTest(int);
static bool validFunctionName(const QString &funcName);
QString m_testedComponent;
QString m_testedFile;
QString m_testedClass;
QString m_testCase;
QString m_basePath;
QString m_externalPath;
QString m_fileName;
TestType m_testType;
QList<TestFunctionInfo*> m_testFunctions;
bool m_hasChanged;
QPointer<TextEditor::BaseTextEditor> m_codeEditor;
QTimer m_editTimer;
QDateTime m_lastModified;
QFileInfo *m_fileInfo;
QmlJS::Document::Ptr m_qmlJSDoc;
CPlusPlus::Document::Ptr m_cppDoc;
QTimer m_parseTimer;
bool m_initialized;
bool m_errored;
};
class TestCollection : public QObject
{
Q_OBJECT
public:
TestCollection();
virtual ~TestCollection();
TestCode *currentEditedTest();
void setCurrentEditedTest(TestCode *code);
TestCode *findCode(const QString &fileName, const QString &basePath, const QString &extraPath);
TestCode *findCodeByVisibleName(const QString &fileName, bool componentMode);
TestCode *findCodeByTestCaseName(const QString &testCaseName);
TestCode *testCode(int index);
int count();
void removeAll();
void addPath(const QString &srcPath);
void addExtraPath(const QString &srcPath);
void removePath(const QString &srcPath);
QStringList testFiles();
QStringList manualTests(const QString &startPath, bool componentMode);
signals:
void testChanged(TestCode *testCode);
void testRemoved(TestCode *testCode);
void changed();
private:
static TestCollection_p *d;
static int m_refCount;
};
class TestCollection_p : public QObject
{
Q_OBJECT
public:
TestCollection_p();
virtual ~TestCollection_p();
TestCode *currentEditedTest();
void setCurrentEditedTest(TestCode *code);
TestCode *findCode(const QString &fileName, const QString &basePath, const QString &extraPath);
TestCode *findCodeByVisibleName(const QString &fileName, bool componentMode);
TestCode *findCodeByTestCaseName(const QString &testCaseName);
void removeCode(const QString &fileName);
TestCode *testCode(int index);
int count();
QStringList testFiles();
QStringList manualTests(const QString &startPath, bool componentMode);
public slots:
void addPath(const QString &srcPath);
void addExtraPath(const QString &srcPath);
void removePath(const QString &srcPath);
void removeAll();
void initModelManager();
void onDocumentUpdated(QmlJS::Document::Ptr doc);
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
private:
void scanTests(const QString &suitePath);
bool isUnitTestCase(const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot);
bool isUnitTestCase(const CPlusPlus::Document::Ptr &doc,
const CPlusPlus::Snapshot &snapshot, QStringList &visited);
signals:
void testChanged(TestCode *testCode);
void testRemoved(TestCode *testCode);
void changed();
private:
QString m_currentScanRoot;
QString m_currentExtraBase;
QList<TestCode*> m_codeList;
QPointer<TestCode> m_currentEditedTest;
QmlJS::ModelManagerInterface *m_qmlJSModelManager;
CPlusPlus::CppModelManagerInterface *m_cppModelManager;
QMap<QString, TestCode*> m_qttDocumentMap;
QMap<QString, TestCode*> m_cppDocumentMap;
};
#endif // TESTCODE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,222 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTCONFIGURATIONS_H
#define TESTCONFIGURATIONS_H
#ifndef QTTEST_PLUGIN_LEAN
# include "testcontrol.h"
#endif
#include "projectexplorer/project.h"
#include <../../libs/utils/ssh/sshconnection.h>
#include <QTextStream>
#include <QObject>
#include <QList>
#include <QStringList>
#include <QPointer>
#include <QTimer>
class TestConfigurations_p;
class TestConfig : public QObject
{
Q_OBJECT
public:
TestConfig();
virtual ~TestConfig();
bool load(uint version, QTextStream *s);
bool save(QTextStream *s);
void clear();
bool isActive() { return m_activeProject != 0; }
QPointer<ProjectExplorer::Project> activeProject() { return m_activeProject; }
QString configName();
QString runParams();
QString srcPath();
QString buildPath();
QString currentTestCase();
QString currentTestFunc();
QStringList selectedTests();
QString copyrightHeader();
QString runScript();
QString postProcessScript();
QString makeCommand();
QString qmakeCommand(bool desktopQMakeRequested);
QStringList *buildEnvironment();
QStringList *runEnvironment();
QString uploadChange();
void setUploadChange(const QString &newValue);
QString uploadBranch();
void setUploadBranch(const QString &newValue);
QString uploadBranchSpecialization() const;
void setUploadBranchSpecialization(const QString &newValue);
QString uploadPlatform();
void setUploadPlatform(const QString &newValue);
bool autoDetectPlatformConfiguration() const;
void setAutoDetectPlatformConfiguration(bool doAutoDetect);
QString QMAKESPEC();
void setQMAKESPEC(const QString &newValue);
QString QMAKESPECSpecialization() const;
void setQMAKESPECSpecialization(const QString &newValue);
QString PATH();
QString QTDIR();
bool uploadUsingScp();
bool uploadUsingEMail();
void setUploadMethod(bool useScp);
enum UploadMode { UploadAuto, UploadAskMe, UploadNoThanks };
void setUploadMode(UploadMode mode);
UploadMode uploadMode();
bool uploadResults();
bool isRemoteTarget(QString &deviceName, QString &testDeviceType, Utils::SshConnectionParameters &sshParameters);
QStringList extraTests() const;
void setExtraTests(const QStringList &list);
void setCurrentTest(const QString &testcase, const QString &testFunc);
void setSelectedTests(const QStringList &list);
void setConfigName(const QString &name) { m_configName = name; }
void setRunParams(const QString &params) { m_runParams = params; }
void setRunScript(const QString &script) { m_runScript = script; }
void setPostProcessScript(const QString &script) { m_postprocessScript = script; }
void activate(ProjectExplorer::Project *project);
void deactivate();
protected:
void emitConfigChanged();
private slots:
void onProjectSettingsChanged();
void onBuildDirectoryChanged();
void onEnvironmentChanged();
void onActiveTargetChanged();
private:
QTimer m_configChangedTimer;
QStringList m_buildEnvironment;
QStringList m_runEnvironment;
QString m_configName;
QString m_runParams;
QString m_runScript;
QString m_postprocessScript;
QString m_lastTestcase;
QString m_lastTestfunc;
QStringList m_lastSelectedTests;
QString m_uploadChange;
QString m_uploadBranch;
QString m_uploadPlatform;
QString m_uploadBranchSpecialization;
QString m_qmakeMkspec;
QString m_qmakeMkspecSpecialization;
QStringList m_extraTests;
QPointer<ProjectExplorer::Project> m_activeProject;
bool m_autodetectPlatformConfiguration;
QString m_uploadMethod;
QStringList m_extraTestPaths;
UploadMode m_uploadMode;
QString m_currentLoadedSrcDir;
QStringList m_currentLoadedExtraDirs;
bool m_changeDetected;
bool m_branchDetected;
bool m_platformDetected;
QString m_makeCommand;
QString m_qmakeCommand;
private:
friend class TestConfigurations_p;
void loadLine(QTextStream *s, const QString &id, QString &value);
void loadLine(QTextStream *s, const QString &id, int &value);
void saveLine(QTextStream *s, const QString &id, const QString &value);
};
class TestConfigurations : public QObject
{
Q_OBJECT
public:
TestConfigurations();
~TestConfigurations();
static TestConfigurations &instance();
TestConfig *activeConfiguration();
void setActiveConfiguration(ProjectExplorer::Project *project);
TestConfig *config(const QString &configName);
TestConfig *findConfig(const QString &srcPath);
void rescan();
QStringList selectedTests();
void setSelectedTests(const QStringList &list);
void setCurrentTest(const QString &testCase, const QString &testFunction);
QString currentTestCase();
QString currentTestFunction();
void delayConfigUpdates(bool delay);
bool updatesDelayed();
public slots:
void onActiveConfigurationChanged();
void onTestSelectionChanged(const QStringList&);
signals:
void activeConfigurationChanged();
void testSelectionChanged(const QStringList&, QObject*);
private:
static TestConfigurations *m_instance;
TestConfigurations_p *d;
};
#endif

View File

@@ -0,0 +1,357 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "testcontextmenu.h"
#include "testcode.h"
#include "testsettings.h"
#include "qsystem.h"
#include <coreplugin/icore.h>
#include <coreplugin/inavigationwidgetfactory.h>
#include <extensionsystem/iplugin.h>
#include <coreplugin/editormanager/editormanager.h>
TestContextMenu_p *TestContextMenu::m_instance = 0;
int TestContextMenu::m_refCount = 0;
TestContextMenu::TestContextMenu(QObject *widget)
{
if (m_refCount++ == 0)
m_instance = new TestContextMenu_p(widget);
connect(m_instance->m_testToggleCurrentSelectAction, SIGNAL(triggered()),
this, SIGNAL(toggleSelection()));
connect(m_instance->m_testSelectAllTestsAction, SIGNAL(triggered()),
this, SIGNAL(selectAllTests()));
connect(m_instance->m_testDeselectAllTestsAction, SIGNAL(triggered()),
this, SIGNAL(deselectAllTests()));
connect(m_instance->m_testSelectAllManualTestsAction, SIGNAL(triggered()),
this, SIGNAL(selectAllManualTests()));
}
TestContextMenu::~TestContextMenu()
{
if (--m_refCount == 0) {
delete m_instance;
}
}
void TestContextMenu::init(QMenu *testMenu, int mode, QObject *widget)
{
if (m_instance)
m_instance->init(testMenu, mode, widget);
}
void TestContextMenu::languageChange()
{
if (m_instance)
m_instance->languageChange();
}
void TestContextMenu::updateActions( bool testVisible, bool testBusy, bool testStopped)
{
if (m_instance)
m_instance->updateActions(testVisible, testBusy, testStopped);
}
void TestContextMenu::updateToggleAction(const QString &testName)
{
if (m_instance)
m_instance->updateToggleAction(testName);
}
void TestContextMenu::updateSingleTestAction(const QString &testName)
{
if (m_instance)
m_instance->updateSingleTestAction(testName);
}
TestContextMenu_p::TestContextMenu_p(QObject *widget)
{
m_testInsertUnitOrSystemTestAction = new QAction(widget);
m_testInsertUnitOrSystemTestAction->setEnabled(false);
m_editorInsertTestFunctionAction = new QAction(widget);
m_editorInsertTestFunctionAction->setEnabled(false);
m_testRunAction = new QAction(widget);
m_testRunAction->setIcon(QIcon(QPixmap(":/testrun.png")));
m_testRunAsManualAction = new QAction(widget);
m_testRunAsManualAction->setIcon(QIcon(QPixmap(":/testrun.png")));
m_testDebugAction = new QAction(widget);
m_testDebugAction->setIcon(QIcon(QPixmap(":/testlearn.png")));
m_editorRunSingleTestAction = new QAction(widget);
m_editorRunSingleTestAction->setIcon(QIcon(QPixmap(":/testrun.png")));
m_editorRunSingleTestAction->setVisible(false);
m_testStopTestingAction = new QAction(widget);
m_testStopTestingAction->setIcon(QIcon(QPixmap(":/teststop.png")));
m_editorStopTestingAction = new QAction(widget);
m_editorStopTestingAction->setIcon(QIcon(QPixmap(":/teststop.png")));
m_testLearnAction = new QAction(widget);
m_testLearnAction->setCheckable(true);
m_testLearnAction->setChecked(m_testSettings.learnMode() == 1);
QObject::connect(m_testLearnAction, SIGNAL(toggled(bool)), this, SLOT(onLearnChanged()));
m_testLearnAllAction = new QAction(widget);
m_testLearnAllAction->setCheckable(true);
m_testLearnAllAction->setChecked(m_testSettings.learnMode() == 2);
QObject::connect(m_testLearnAllAction, SIGNAL(toggled(bool)), this, SLOT(onLearnAllChanged()));
m_testLocalSettingsAction = new QAction(widget);
m_testToggleCurrentSelectAction = new QAction(widget);
m_testSelectAllTestsAction = new QAction(widget);
m_testSelectAllManualTestsAction = new QAction(widget);
m_testDeselectAllTestsAction = new QAction(widget);
m_testGroupsAction = new QAction(widget);
m_testRescanAction = new QAction(widget);
m_testOpenIncludeFileAction = new QAction(widget);
languageChange();
Core::ICore *core = Core::ICore::instance();
Core::EditorManager* em = core->editorManager();
QObject::connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
this, SLOT(editorChanged(Core::IEditor*)), Qt::DirectConnection);
}
TestContextMenu_p::~TestContextMenu_p()
{
}
void TestContextMenu_p::init(QMenu *testMenu, int mode, QObject *widget)
{
if (mode == 0) {
// menu bar at the top
testMenu->addAction(m_testInsertUnitOrSystemTestAction);
testMenu->addAction(m_editorInsertTestFunctionAction);
testMenu->addSeparator();
testMenu->addAction(m_testRunAction);
testMenu->addAction(m_testRunAsManualAction);
testMenu->addAction(m_testDebugAction);
testMenu->addAction(m_testStopTestingAction);
testMenu->addSeparator();
testMenu->addAction(m_testRescanAction);
testMenu->addAction(m_testLearnAction);
testMenu->addAction(m_testLearnAllAction);
} else if (mode == 1) {
// context menu in test selection navigator
testMenu->addAction(m_testToggleCurrentSelectAction);
testMenu->addAction(m_testSelectAllTestsAction);
testMenu->addAction(m_testSelectAllManualTestsAction);
testMenu->addAction(m_testGroupsAction);
testMenu->addAction(m_testDeselectAllTestsAction);
testMenu->addSeparator();
testMenu->addAction(m_testInsertUnitOrSystemTestAction);
testMenu->addSeparator();
testMenu->addAction(m_testRunAction);
testMenu->addAction(m_testRunAsManualAction);
testMenu->addAction(m_testDebugAction);
testMenu->addAction(m_testStopTestingAction);
testMenu->addSeparator();
testMenu->addAction(m_testRescanAction);
if (widget) {
QObject::connect(m_testGroupsAction, SIGNAL(triggered(bool)),
widget, SLOT(selectGroup()), Qt::DirectConnection);
QObject::connect(m_testInsertUnitOrSystemTestAction, SIGNAL(triggered(bool)),
widget, SLOT(testInsertUnitOrSystemTest()), Qt::DirectConnection);
QObject::connect(m_testRescanAction, SIGNAL(triggered(bool)),
widget, SLOT(rescan()), Qt::DirectConnection);
}
} else if (mode == 2) {
// context menu in CPP or JS editor
testMenu->addSeparator();
testMenu->addAction(m_editorInsertTestFunctionAction);
testMenu->addSeparator();
testMenu->addAction(m_editorRunSingleTestAction);
testMenu->addAction(m_editorStopTestingAction);
testMenu->addSeparator();
} else if (mode == 3) {
// Acttons handled by QtTestPlugin
QObject::connect(m_testRunAction, SIGNAL(triggered(bool)),
widget, SLOT(testRun()), Qt::DirectConnection);
QObject::connect(m_testRunAsManualAction, SIGNAL(triggered(bool)),
widget, SLOT(testRunAsManual()), Qt::DirectConnection);
QObject::connect(m_testDebugAction, SIGNAL(triggered(bool)),
widget, SLOT(testDebug()), Qt::DirectConnection);
QObject::connect(m_testStopTestingAction, SIGNAL(triggered(bool)),
widget, SLOT(stopTesting()), Qt::DirectConnection);
QObject::connect(m_editorRunSingleTestAction, SIGNAL(triggered(bool)),
widget, SLOT(testRunSingle()), Qt::DirectConnection);
QObject::connect(m_editorStopTestingAction, SIGNAL(triggered(bool)),
widget, SLOT(stopTesting()), Qt::DirectConnection);
QObject::connect(m_editorInsertTestFunctionAction, SIGNAL(triggered(bool)),
widget, SLOT(insertTestFunction()), Qt::DirectConnection);
}
}
void TestContextMenu_p::onOpenIncludeFile()
{
emit openIncludeFile(m_includeFile);
}
void TestContextMenu_p::updateToggleAction(const QString &testName)
{
m_testToggleCurrentSelectAction->setVisible(!testName.isEmpty());
m_testToggleCurrentSelectAction->setText(testName);
}
void TestContextMenu_p::updateSingleTestAction(const QString &testName)
{
m_editorRunSingleTestAction->setVisible(!testName.isEmpty());
m_editorRunSingleTestAction->setText(tr("Run: '%1'").arg(testName));
}
void TestContextMenu_p::updateActions(bool testVisible, bool testBusy, bool testStopped)
{
m_testInsertUnitOrSystemTestAction->setEnabled(testVisible);
m_editorInsertTestFunctionAction->setEnabled(testVisible);
m_testRunAction->setEnabled(!testBusy);
m_testRunAsManualAction->setEnabled(!testBusy);
m_testDebugAction->setEnabled(!testBusy);
m_editorRunSingleTestAction->setEnabled(!testBusy);
m_testStopTestingAction->setEnabled(testBusy && !testStopped);
m_editorStopTestingAction->setEnabled(testBusy && !testStopped);
}
void TestContextMenu_p::enableIncludeFile(const QString &fileName)
{
m_includeFile = fileName;
m_testOpenIncludeFileAction->setText("Open: '" + fileName + "'");
m_testOpenIncludeFileAction->setVisible(!fileName.isEmpty());
}
void TestContextMenu_p::languageChange()
{
m_testInsertUnitOrSystemTestAction->setText(tr("New Test..."));
m_testInsertUnitOrSystemTestAction->setStatusTip(
tr("Add a new unit/integration/performance/system test to the currently selected application, library or plugin."));
m_editorInsertTestFunctionAction->setText(tr("&New Test Function..."));
m_editorInsertTestFunctionAction->setStatusTip(
tr("Add a new test function to the currently selected test."));
m_testRunAction->setText(tr("&Run All Selected Tests"));
m_testRunAction->setStatusTip(
tr("Run all currently selected tests. For manual tests a dialog will pop up with a documented set of manual test steps."));
m_testRunAsManualAction->setText(tr("&Run All Selected Tests as Manual"));
m_testRunAsManualAction->setStatusTip(
tr("Run all currently checked tests as manual tests, i.e. automated tests will be converted into a documented set of manual steps and then shown in a dialog."));
m_testDebugAction->setText(tr("&Debug All Selected Tests"));
m_testDebugAction->setStatusTip(tr("Debug all currently selected tests."));
m_editorRunSingleTestAction->setText(tr("&Run"));
m_editorRunSingleTestAction->setStatusTip(tr("Run currently edited test."));
m_testStopTestingAction->setText(tr("Stop Testing"));
m_testStopTestingAction->setStatusTip(tr("Stop the execution of the current test."));
m_editorStopTestingAction->setText(tr("Stop Testing"));
m_editorStopTestingAction->setStatusTip(tr("Stop the execution of the current test."));
m_testLearnAction->setText(tr("Learn New"));
m_testLearnAction->setStatusTip(tr("Learn test data (snapshots and so on) for new tests."));
m_testLearnAllAction->setText(tr("Learn All"));
m_testLearnAllAction->setStatusTip(
tr("Learn test data (snapshots and so on) for new tests and re-learn data for existing tests."));
m_testGroupsAction->setText(tr("Select by Groups"));
m_testGroupsAction->setStatusTip(tr("Select tests based on a group."));
m_testRescanAction->setText(tr("Rescan All Tests"));
m_testRescanAction->setStatusTip(tr("Rescan all tests."));
m_testToggleCurrentSelectAction->setText(tr("Toggle Selection"));
m_testToggleCurrentSelectAction->setStatusTip(tr("Toggle selection of currently selected test(s)."));
m_testSelectAllTestsAction->setText(tr("Select All Tests"));
m_testSelectAllTestsAction->setStatusTip(tr("Select all available tests for testing."));
m_testSelectAllManualTestsAction->setText(tr("Select All Manual Tests"));
m_testSelectAllManualTestsAction->setStatusTip(tr("Select all manual tests for testing."));
m_testDeselectAllTestsAction->setText(tr("Deselect All Tests"));
m_testDeselectAllTestsAction->setStatusTip(tr("Exclude all tests from testing."));
m_testOpenIncludeFileAction->setText(tr("Open:"));
m_testOpenIncludeFileAction->setStatusTip(tr("Open the specified include file."));
}
void TestContextMenu_p::editorChanged(Core::IEditor *iface)
{
bool isTestcase = false;
if (iface) {
QString fname = iface->displayName();
isTestcase = ((fname.endsWith(".qtt") || fname.endsWith(".cpp"))
&& (fname.startsWith("tst_") || fname.startsWith("sys_")
|| fname.startsWith("int_") || fname.startsWith("prf_")));
}
if (isTestcase) {
TestCollection tc;
TestCode *code =
tc.findCode(QDir::toNativeSeparators(iface->file()->fileName()), QString(), QString());
isTestcase = (code != 0);
// Only show "run single test" in context menu if the testcase file is
// visible (i.e. has focus) in the editor
m_editorRunSingleTestAction->setVisible(isTestcase
&& m_editorRunSingleTestAction->text().contains(code->testCase()));
} else {
m_editorRunSingleTestAction->setVisible(false);
}
m_editorInsertTestFunctionAction->setVisible(isTestcase);
m_editorStopTestingAction->setVisible(isTestcase);
}
void TestContextMenu_p::onLearnChanged()
{
if (m_testLearnAction->isChecked()) {
if (m_testLearnAllAction->isChecked())
m_testLearnAllAction->setChecked(false);
m_testSettings.setLearnMode(1);
} else {
m_testSettings.setLearnMode(0);
}
}
void TestContextMenu_p::onLearnAllChanged()
{
if (m_testLearnAllAction->isChecked()) {
if (m_testLearnAction->isChecked())
m_testLearnAction->setChecked(false);
m_testSettings.setLearnMode(2);
} else {
m_testSettings.setLearnMode(0);
}
}

View File

@@ -0,0 +1,125 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTCONTEXTMENU_H
#define TESTCONTEXTMENU_H
#include "testsuite.h"
#include "testexecuter.h"
#include "testcode.h"
#include "testoutputwindow.h"
#include "testsettings.h"
#include "extensionsystem/iplugin.h"
#include "projectexplorer/projectexplorer.h"
#include <QString>
#include <QTreeWidget>
#include <QMenu>
#include <QAction>
class TestContextMenu_p;
class TestContextMenu : public QObject
{
Q_OBJECT
public:
TestContextMenu(QObject *widget);
~TestContextMenu();
void init(QMenu *testMenu, int mode, QObject *widget);
void languageChange();
void updateActions(bool testVisible, bool testBusy, bool testStopped);
void updateToggleAction(const QString &testName);
void updateSingleTestAction(const QString &testName);
signals:
void selectAllTests();
void deselectAllTests();
void selectAllManualTests();
void toggleSelection();
private:
static TestContextMenu_p *m_instance;
static int m_refCount;
};
class TestContextMenu_p : public QObject
{
Q_OBJECT
public:
TestContextMenu_p(QObject *widget);
~TestContextMenu_p();
void init(QMenu *testMenu, int mode, QObject *widget);
void languageChange();
void updateActions(bool testVisible, bool testBusy, bool testStopped);
void updateToggleAction(const QString &testName);
void updateSingleTestAction(const QString &testName);
void enableIncludeFile(const QString &fileName);
QAction *m_testInsertUnitOrSystemTestAction;
QAction *m_testRunAction;
QAction *m_testRunAsManualAction;
QAction *m_testDebugAction;
QAction *m_testStopTestingAction;
QAction *m_testLearnAction;
QAction *m_testLearnAllAction;
QAction *m_testLocalSettingsAction;
QAction *m_testToggleCurrentSelectAction;
QAction *m_testSelectAllTestsAction;
QAction *m_testSelectAllManualTestsAction;
QAction *m_testDeselectAllTestsAction;
QAction *m_testGroupsAction;
QAction *m_testRescanAction;
QAction *m_testOpenIncludeFileAction;
QAction *m_editorInsertTestFunctionAction;
QAction *m_editorRunSingleTestAction;
QAction *m_editorStopTestingAction;
signals:
void openIncludeFile(const QString &filename);
private slots:
void onOpenIncludeFile();
void editorChanged(Core::IEditor *iface);
void onLearnChanged();
void onLearnAllChanged();
private:
QString m_includeFile;
TestSettings m_testSettings;
};
#endif // TESTCONTEXTMENU_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,191 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTEXECUTER_H
#define TESTEXECUTER_H
#include "testsettings.h"
#include "testcode.h"
#include "testresultuploader.h"
#ifndef QTTEST_PLUGIN_LEAN
# include "qscriptsystemtest.h"
#endif
#ifdef QTTEST_DEBUGGER_SUPPORT
# include <debugger/qtuitest/qtuitestengine.h>
#endif
#include <QtCore/QFutureWatcher>
#include <QObject>
#include <QTimer>
#include <QProcess>
#include <QLabel>
#define NO_X_SERVER_AVAILABLE "No X-server available for testing"
#define COMPILE_ERROR "Compile error"
#define COMPILE_SUCCESS "Compile successful"
#define COMPILE_NOT_AVAIL "Binary not available for testing"
#define COMPILE_UP_TO_DATE "Not recompiled, binary is up-to-date"
#define SELF_TEST "self-test"
class TestExecuter : public QObject
{
Q_OBJECT
private:
static TestExecuter *m_instance;
public:
TestExecuter();
virtual ~TestExecuter();
static TestExecuter *instance();
bool testBusy() const;
bool testFailedUnexpectedly();
bool testStopped() const { return m_manualStop; }
#ifdef QTTEST_DEBUGGER_SUPPORT
void setDebugEngine(Debugger::Internal::QtUiTestEngine *);
Debugger::Internal::QtUiTestEngine *debugEngine() const;
#endif
void eventRecordingStarted(const QString &file, int line, const QString &steps);
void recordedCode(const QString &code);
bool mustStopEventRecording() const;
bool eventRecordingAborted() const;
void setSelectedTests(const QStringList &);
QString currentRunningTest() const;
public slots:
void runTests(bool singleTest, bool forceManual);
void runSelectedTests(bool forceManual);
void stopTesting();
void manualStop();
void syntaxError(const QString &, const QString &, int);
void onTestResult(const QVariantMap &);
signals:
void testStarted();
void testStop();
void testFinished();
private slots:
bool buildTestCase();
bool runTestCase(bool forceManual);
bool postProcess();
void parseOutput();
void onKillTestRequested();
void onExecuterFinished();
void abortRecording();
private:
// FIXME. These functions are 'borrowed' from storetestresults which isn't the smartest thing to do
QString sanitizedForFilename(const QString &in) const;
QString saveResults(const QString &changeNo, const QString &platform, const QString &branch);
QByteArray testrHeader(const QString &changeNo, const QString &platform, const QString &branch) const;
QByteArray testrFooter() const;
void endTest();
bool getNextTest();
QWidget *createProgressWidget();
bool exec(const QString &cmd, const QStringList &arguments, const QString &workDir = "", int timeout = 30000);
void addTestResult(const QString &result, const QString &test, const QString &reason,
const QString &file = QString(), int line = -1, const QString &dataTag = QString());
void applyPendingInsertions();
TestResultUploader m_testResultUploader;
TestCollection m_testCollection;
TestSettings m_testSettings;
TestConfig *m_testCfg;
QProcess m_executer;
bool m_executerFinished;
QTime m_executeTimer;
bool m_testFailedUnexpectedly;
QStringList m_selectedTests;
QStringList m_failureLines;
TestCode *m_curTestCode;
QString m_testOutputFile;
QString m_syntaxError;
#ifndef QTTEST_PLUGIN_LEAN
QScriptSystemTest m_qscriptSystemTest;
#endif
bool m_testBusy;
bool m_stopTesting;
bool m_manualStop;
bool m_runRequired;
bool m_pendingFailure;
bool m_killTestRequested;
bool m_inBuildMode;
QStringList m_xmlLog;
bool m_xmlMode;
QString m_xmlTestcase;
QString m_xmlTestfunction;
QString m_xmlDatatag;
QString m_xmlFile;
QString m_xmlLine;
QString m_xmlResult;
QString m_xmlDescription;
QString m_xmlQtVersion;
QString m_xmlQtestVersion;
// functionality to parse (system test) xml results recorded in a file
QTextStream *m_testResultsStream;
bool canReadLine();
QString readLine();
QStringList peek();
QString m_peekedResult;
// Progress reporting to the progress manager
QFutureInterface<void> *m_progressBar;
QPointer<QLabel> m_progressLabel;
int m_progress;
int m_progressFailCount;
int m_progressPassCount;
#ifdef QTTEST_DEBUGGER_SUPPORT
Debugger::Internal::QtUiTestEngine *m_debugEngine;
#endif
QPointer<QTextEdit> m_recordedEventsEdit;
bool m_recordingEvents;
bool m_abortRecording;
QMap<QPair<QString, int>, QString> m_pendingInsertions;
QString m_lastFinishedTest;
};
#endif

View File

@@ -0,0 +1,341 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "testgenerator.h"
#include "testconfigurations.h"
#include "qsystem.h"
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QDateTime>
#include <QMessageBox>
#include <QDebug>
#include <stdlib.h>
TestGenerator::TestGenerator()
{
m_generatedFilename = "";
m_initialized = false;
m_enableComponentNamedTest = true;
}
/*!
Generates a .pro file for the testCase specified in the constructor and saves
it to the path specified in the constructor.
*/
bool TestGenerator::generateProFile()
{
if (!m_initialized)
return false;
QFile F(m_generatedProname);
if (F.open(QIODevice::WriteOnly)) {
QTextStream src(&F);
if (m_genMode != SystemTest) {
src << "load(testcase)\n";
src << "TARGET = " << m_testCase.toLower() << "\n";
src << "QT += testlib\n";
src << "SOURCES = " << m_testCase.toLower() << ".cpp\n";
} else if (m_genMode == SystemTest) {
src << "TEMPLATE = subdirs\n";
src << "CONFIG += systemtest\n";
src << "SOURCES = " << m_testCase.toLower() << ".qtt\n";
}
F.close();
return true;
}
return false;
}
/*!
Generates .pro files for the parent directories of the testCase.
*/
bool TestGenerator::generateParentDirectoryProFiles()
{
if (!m_initialized)
return false;
QDir::cleanPath(m_rootDir);
return true;
}
bool TestGenerator::generateTestCode()
{
if (!m_initialized)
return false;
if (QDir().exists(m_generatedFilename)) {
int ret = QMessageBox::warning(0, "Error", "File already exists.\nDo you wish to overwrite it?",
QMessageBox::Yes|QMessageBox::No);
if (ret == QMessageBox::No) {
return false;
} else {
if (!QFile().remove(m_generatedFilename)) {
QMessageBox::warning(0, "Error", "Could not remove file", QMessageBox::Ok);
return false;
}
}
}
// create a source file that contains class definition, main implementation and class implementation
QFile sourceFile(m_generatedFilename);
if (!sourceFile.open(QIODevice::WriteOnly)) {
QMessageBox::warning(0, "Error", "Error creating source file", QMessageBox::Ok);
return false;
}
QTextStream sourceFileStream(&sourceFile);
if (m_genMode == UnitTest || m_genMode == PerformanceTest || m_genMode == IntegrationTest)
initSrc(&sourceFileStream);
else
initScript(&sourceFileStream);
sourceFile.close();
return true;
}
void TestGenerator::initSrc(QTextStream *s)
{
if (!m_initialized)
return;
TestConfig *cfg = TestConfigurations::instance().findConfig(m_generatedFilename);
if (!cfg)
return;
// First we write the license stuff to the header file
QFile crfile(cfg->copyrightHeader());
if (crfile.open(QIODevice::ReadOnly)) {
QTextStream crfileStream(&crfile);
*s << crfileStream.readAll();
}
*s << "\n";
*s << "//TESTED_COMPONENT=" << m_testedComponent << "\n";
*s << "//TESTED_CLASS=" << m_testedClass << "\n";
*s << "//TESTED_FILE=" << m_includeFile << "\n";
*s << "\n";
*s << "#include <QtTest/QtTest>\n";
if (m_includeFile != "")
*s << "#include \"" << m_includeFile << "\"\n";
*s << "\n";
*s << "/*!\n";
*s << " \\internal\n";
*s << "\n";
*s << " \\class " << m_testCase << "\n";
*s << " \\brief <put brief description here>\n";
*s << "\n";
*s << " <put extended description here>\n";
*s << "\n";
if (m_testedClass.isEmpty())
*s << " \\sa " << "<tested class name>\n";
else
*s << " \\sa " << m_testedClass << "\n";
*s << "*/\n";
*s << "class " << m_testCase << " : public QObject\n";
*s << "{\n";
*s << " Q_OBJECT\n";
*s << "\n";
*s << "public:\n";
*s << " " << m_testCase << "();\n";
*s << " virtual ~" << m_testCase << "();\n";
*s << "\n";
*s << "private slots:\n";
*s << " virtual void initTestCase();\n";
*s << " virtual void init();\n";
*s << " virtual void cleanup();\n";
*s << " virtual void cleanupTestCase();\n";
*s << "};\n";
*s << "\n";
*s << "QTEST_MAIN(" << m_testCase << ")\n";
*s << "#include " << '"' << m_testCase.toLower() << ".moc" << '"' << "\n";
*s << "\n";
*s << "\n";
*s << m_testCase << "::" << m_testCase << "()\n";
*s << "{\n";
*s << "}\n";
*s << "\n";
*s << m_testCase << "::~" << m_testCase << "()\n";
*s << "{\n";
*s << "}\n";
*s << "\n";
*s << "void " << m_testCase << "::initTestCase()\n";
*s << "{\n";
*s << "}\n";
*s << "\n";
*s << "void " << m_testCase << "::init()\n";
*s << "{\n";
*s << "}\n";
*s << "\n";
*s << "void " << m_testCase << "::cleanup()\n";
*s << "{\n";
*s << "}\n";
*s << "\n";
*s << "void " << m_testCase << "::cleanupTestCase()\n";
*s << "{\n";
*s << "}\n";
*s << "\n";
*s << "\n";
}
void TestGenerator::initScript(QTextStream *s)
{
if (!m_initialized)
return;
TestConfig *cfg = TestConfigurations::instance().findConfig(m_generatedFilename);
if (!cfg)
return;
QFile crfile(cfg->copyrightHeader());
if (crfile.open(QIODevice::ReadOnly)) {
QTextStream crfileStream(&crfile);
*s << crfileStream.readAll();
}
*s << "\n";
*s << "//TESTED_COMPONENT=" << m_testedComponent << "\n";
*s << "\n";
*s << "testcase = {\n";
*s << " initTestCase: function()\n";
*s << " {\n";
*s << " },\n";
*s << "\n";
*s << " init: function()\n";
*s << " {\n";
*s << " },\n";
*s << "\n";
*s << " cleanup: function()\n";
*s << " {\n";
*s << " },\n";
*s << "\n";
*s << " cleanupTestCase: function()\n";
*s << " {\n";
*s << " },\n";
*s << "\n";
*s << "\n";
*s << "} // end of testcase\n";
*s << "\n";
}
void TestGenerator::setTestCase(GenMode mode, const QString &rootDir, const QString &testDir,
const QString &testCase, const QString &testedComponent, const QString &testedClassName,
const QString &testedClassFile)
{
Q_UNUSED(testedClassFile);
QString testCaseNameSuffix;
m_generatedFilename = "";
m_genMode = mode;
m_testedClass = testedClassName;
m_testedComponent = testedComponent;
m_includeFile = "";
m_testCase = testCase;
m_rootDir = rootDir;
if (testDir.isEmpty()) {
// common case , auto detect test dir value
m_testDir = "auto";
if (mode == TestGenerator::SystemTest)
m_testDir = "systemtests";
else if (mode == TestGenerator::PerformanceTest)
m_testDir = "benchmarks";
} else {
m_testDir = testDir;
}
// use component name in test case directory path?
if (m_enableComponentNamedTest)
testCaseNameSuffix = testedComponent + QDir::separator();
m_tcDir = m_rootDir + QDir::separator() + m_testDir + QDir::separator()
+ testCaseNameSuffix + m_testCase.toLower();
QString fname(m_tcDir + QDir::separator() + m_testCase.toLower());
if (m_genMode == UnitTest || m_genMode == IntegrationTest || m_genMode == PerformanceTest)
fname += ".cpp";
else
fname += ".qtt";
m_generatedFilename = fname;
m_generatedProname = m_tcDir + QDir::separator() + m_testCase.toLower() + ".pro";
m_initialized = true;
}
bool TestGenerator::generateTest()
{
if (!m_initialized)
return false;
QDir().mkpath(m_tcDir);
if (!QFile::exists(m_tcDir)){
QMessageBox::warning(0, "Unable to create test directory",
QString("Unable to create test directory %1").arg(m_tcDir));
return false;
}
return (generateParentDirectoryProFiles() && generateProFile() && generateTestCode());
}
QString TestGenerator::generatedFileName()
{
return m_generatedFilename;
}
QString TestGenerator::generatedProName()
{
return m_generatedProname;
}
void TestGenerator::enableComponentInTestName(bool value)
{
m_enableComponentNamedTest = value;
}
QString TestGenerator::testCaseDirectory()
{
return m_tcDir;
}

View File

@@ -0,0 +1,77 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTGENERATOR_H
#define TESTGENERATOR_H
#include <QString>
#include <QTextStream>
#include <QStringList>
class TestGenerator
{
public:
TestGenerator();
enum GenMode { UnitTest, SystemTest, IntegrationTest, PerformanceTest };
void setTestCase(GenMode mode, const QString &rootDir, const QString &testDir, const QString &testCase,
const QString &testedComponent, const QString &testedClassName, const QString &testedClassFile);
bool generateTest();
bool generateParentDirectoryProFiles();
void enableComponentInTestName(bool value);
QString generatedFileName();
QString generatedProName();
QString testCaseDirectory();
protected:
void initSrc(QTextStream *s);
void initScript(QTextStream *s);
bool generateProFile();
bool generateTestCode();
private:
QString m_generatedFilename;
QString m_generatedProname;
QString m_testDir;
QString m_rootDir;
QString m_tcDir;
QString m_testedClass;
QString m_testedComponent;
QString m_includeFile;
QString m_testCase;
GenMode m_genMode;
bool m_initialized;
bool m_enableComponentNamedTest;
};
#endif

View File

@@ -0,0 +1,125 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "testoutputwindow.h"
#include <QtGui/QTextEdit>
#include <QDebug>
TestOutputWindow *m_instance = 0;
QTextEdit *testOutputPane()
{
if (m_instance)
return m_instance->m_widget;
return 0;
}
TestOutputWindow::TestOutputWindow()
{
m_widget = new QTextEdit;
m_widget->setReadOnly(true);
m_widget->setFrameStyle(QFrame::NoFrame);
m_instance = this;
}
TestOutputWindow::~TestOutputWindow()
{
delete m_widget;
m_instance = 0;
}
bool TestOutputWindow::hasFocus()
{
return m_widget->hasFocus();
}
bool TestOutputWindow::canFocus()
{
return true;
}
void TestOutputWindow::setFocus()
{
m_widget->setFocus();
}
void TestOutputWindow::clearContents()
{
m_widget->clear();
}
QWidget *TestOutputWindow::outputWidget(QWidget *parent)
{
m_widget->setParent(parent);
return m_widget;
}
QString TestOutputWindow::name() const
{
return tr("Test Output");
}
void TestOutputWindow::visibilityChanged(bool /*b*/)
{
}
int TestOutputWindow::priorityInStatusBar() const
{
return 50;
}
bool TestOutputWindow::canNext()
{
return false;
}
bool TestOutputWindow::canPrevious()
{
return false;
}
void TestOutputWindow::goToNext()
{
}
void TestOutputWindow::goToPrev()
{
}
bool TestOutputWindow::canNavigate()
{
return false;
}

View File

@@ -0,0 +1,72 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTOUTPUTWINDOW_H
#define TESTOUTPUTWINDOW_H
#include <coreplugin/ioutputpane.h>
#include <QTextEdit>
QTextEdit *testOutputPane();
class TestOutputWindow : public Core::IOutputPane
{
Q_OBJECT
public:
TestOutputWindow();
~TestOutputWindow();
virtual QString displayName() const { return "Test Output"; }
QWidget *outputWidget(QWidget *parent);
QList<QWidget*> toolBarWidgets() const { return QList<QWidget *>(); }
QString name() const;
int priorityInStatusBar() const;
void clearContents();
void visibilityChanged(bool visible);
bool canFocus();
bool hasFocus();
void setFocus();
virtual bool canNext();
virtual bool canPrevious();
virtual void goToNext();
virtual void goToPrev();
bool canNavigate();
QTextEdit *m_widget;
};
#endif // TESTOUTPUTWINDOW_H

View File

@@ -0,0 +1,196 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "testresultuploader.h"
#include "testoutputwindow.h"
#include <QFileInfo>
TestResultUploader::TestResultUploader(QObject *parent) :
QObject(parent)
{
m_executer.setReadChannelMode(QProcess::MergedChannels);
m_executer.setReadChannel(QProcess::StandardOutput);
connect(&m_executer, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(execFinished(int,QProcess::ExitStatus)));
connect(&m_executer, SIGNAL(readyReadStandardOutput()),
this, SLOT(readStdOut()));
m_uploadState = UploadIdle;
}
TestResultUploader::~TestResultUploader()
{
disconnect(&m_executer, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(execFinished(int,QProcess::ExitStatus)));
disconnect(&m_executer, SIGNAL(readyReadStandardOutput()),
this, SLOT(readStdOut()));
}
void TestResultUploader::uploadResultsToDatabase(const QString &fname, TestConfig *cfg)
{
if (m_uploadState != UploadIdle)
return;
m_testCfg = cfg;
m_srcFname = fname;
if (!fname.isEmpty()) {
m_logFile.setFileName(QDir::homePath() + QDir::separator() + ".qttest"
+ QDir::separator() + "test_result_upload.log");
m_logFile.open(QFile::WriteOnly);
if (m_testSettings.uploadServer().isEmpty()) {
testOutputPane()->append("-- ATTENTION: Uploading of test results to the database aborted. "
"Please specify an upload server in the Upload Test Results Settings dialog.");
return;
}
m_uploadServerName = m_testSettings.uploadServer();
int pos = m_uploadServerName.indexOf(":");
if (pos)
m_uploadServerName = m_uploadServerName.left(pos);
QFileInfo inf(fname);
if (!inf.exists())
return;
m_tgtFname = inf.fileName();
QString cmd1 = QSystem::which(m_testCfg->PATH(), "scp");
QStringList args1;
args1 << fname << QString("%1:/tmp/%2").arg(m_uploadServerName).arg(m_tgtFname);
if (exec(cmd1, QStringList() << "-q" << "-v" << "-C" << args1, "", 60000))
m_uploadState = UploadScp;
}
}
bool TestResultUploader::exec(const QString &cmd, const QStringList &arguments, const QString &workDir, int timeout)
{
Q_UNUSED(timeout);
if (!m_testCfg)
return false;
// Kill the process if it's still running
if (m_executer.state() != QProcess::NotRunning) {
m_executer.kill();
m_executer.waitForFinished();
}
Q_ASSERT(m_executer.state() == QProcess::NotRunning);
if ((workDir != "") && (m_executer.workingDirectory() != workDir))
m_executer.setWorkingDirectory(workDir);
m_executer.setEnvironment(*m_testCfg->buildEnvironment());
if (arguments.count() > 0) {
QString realCmd;
if (!cmd.contains(QDir::separator()))
realCmd = QSystem::which(m_testCfg->PATH(), cmd);
else if (QFile::exists(cmd))
realCmd = cmd;
if (realCmd.isEmpty()) {
testOutputPane()->append("-- No '" + cmd + "' instance found in PATH ("
+ QSystem::envKey(m_testCfg->buildEnvironment(), "PATH") + ").");
return false;
}
m_executer.start(realCmd,arguments);
} else {
m_executer.start(cmd);
}
if (m_logFile.isOpen()) {
m_logFile.write("exec: ");
m_logFile.write(cmd.toLatin1());
m_logFile.write(arguments.join(" ").toLatin1());
m_logFile.write("\n");
}
return m_executer.waitForStarted(30000);
}
void TestResultUploader::execFinished(int exitValue, QProcess::ExitStatus)
{
if (exitValue != 0) {
m_uploadState = UploadIdle;
if (m_logFile.isOpen()) {
m_logFile.write("Upload FAILED!");
m_logFile.close();
QString errFname = QDir::homePath() + QDir::separator() + ".qttest"
+ QDir::separator() + "last_test_result_upload_failure.log";
QFile::remove(errFname);
m_logFile.rename(m_logFile.fileName(), errFname);
QFile errorFile(errFname);
QString lastErrorMessage;
if (errorFile.open(QIODevice::ReadOnly)){
lastErrorMessage = QString("Upload FAILED: %1").arg(QString(errorFile.readAll()));
errorFile.close();
} else {
lastErrorMessage = QString("Upload FAILED, look at the log file %1").arg(errFname);
}
testOutputPane()->append(lastErrorMessage);
}
return;
}
if (m_uploadState == UploadScp) {
m_uploadState = UploadMv;
QString cmd2 = QSystem::which(m_testCfg->PATH(), "ssh");
QStringList args2;
args2 << m_uploadServerName
<< "mv"
<< "-f"
<< QString("/tmp/%1").arg(m_tgtFname)
<< QString("results/%3").arg(m_tgtFname);
exec(cmd2, QStringList() << "-q" << "-v" << args2);
} else if (m_uploadState == UploadMv) {
m_uploadState = UploadIdle;
testOutputPane()->append("\nTest results have been uploaded into the results database.\nThank you for supporting "
+ m_testCfg->configName());
QFile::remove(m_srcFname);
m_logFile.close();
m_logFile.remove();
}
}
void TestResultUploader::readStdOut()
{
if (m_logFile.isOpen())
m_logFile.write(m_executer.readAllStandardOutput());
}

View File

@@ -0,0 +1,74 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTRESULTUPLOADER_H
#define TESTRESULTUPLOADER_H
#include "testsettings.h"
#include "testconfigurations.h"
#include <QObject>
#include <QProcess>
#include <QDebug>
class TestResultUploader : public QObject
{
Q_OBJECT
public:
explicit TestResultUploader(QObject *parent = 0);
virtual ~TestResultUploader();
void uploadResultsToDatabase(const QString &fname, TestConfig *cfg);
public slots:
void execFinished(int exitValue, QProcess::ExitStatus);
void readStdOut();
private:
bool exec(const QString &cmd, const QStringList &arguments,
const QString &workDir = "", int timeout = 30000);
TestSettings m_testSettings;
TestConfig *m_testCfg;
QProcess m_executer;
QString m_uploadServerName;
QString m_srcFname;
QString m_tgtFname;
QFile m_logFile;
enum UploadState { UploadIdle, UploadScp, UploadMv };
UploadState m_uploadState;
};
#endif // TESTRESULTUPLOADER_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,214 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTSELECTOR_H
#define TESTSELECTOR_H
#include "testsuite.h"
#include "testexecuter.h"
#include "testcode.h"
#include "testsettings.h"
#include "testcontextmenu.h"
#include <extensionsystem/iplugin.h>
#include <projectexplorer/projectexplorer.h>
#include <QString>
#include <QTreeWidget>
#include <QMenu>
#include <QAction>
class TestSuiteItem;
class TestCaseItem;
class TestFunctionItem;
class TestViewItem : public QTreeWidgetItem
{
public:
TestViewItem(TestViewItem *parent, const QString &name,
bool testSuite, int type = TestViewItem::TestItemType);
TestViewItem(QTreeWidget *parent, const QString &name,
bool testSuite, int type=TestViewItem::TestItemType);
virtual ~TestViewItem();
QString name() { return m_name; }
bool isAssigned() { return m_assigned; }
bool childAssigned() { return m_childAssigned > 0; }
void resetAssignment();
void assign();
void unassign();
void childAssign();
void childUnassign();
void parentAssign(bool local);
void parentUnassign(bool local);
virtual bool findChild(const QString &className, TestViewItem *&item);
void removeAllChildren();
void toggle();
bool isTestSuite();
TestSuiteItem *parentSuite();
QString baseSuiteName();
QString suiteName();
QString fullName();
enum TestItemTypes {
TestItemType = QTreeWidgetItem::UserType + 1,
TestSuiteItemType,
TestCaseItemType,
TestFunctionItemType
};
protected:
void updatePixmap();
QString m_name;
TestViewItem *m_parent;
bool m_errored;
private:
uint m_childAssigned;
uint m_parentAssigned;
bool m_assigned;
bool m_isTestSuite;
};
class TestSelector : public QTreeWidget
{
Q_OBJECT
public:
TestSelector(QWidget *parent = 0, const char *name = 0);
virtual ~TestSelector();
void setContextMenu(TestContextMenu *contextMenu);
void setSelectedTests(bool save, const QStringList &list);
QStringList selectedTests();
protected:
virtual void resize(int w, int h);
TestViewItem *recastItem(QTreeWidgetItem *item);
QString curTestSuite(bool fullPath = false);
TestCode *curTestCode() { return m_curTest.m_code; }
TestSuiteItem *addSuite(TestCode *code);
TestSuiteItem *findSuite(const QString &suitePath);
bool removeSuite(const QString &suitePath, bool force = false);
TestCaseItem *findCase(const QString &tcFileName);
TestCaseItem *addCase(TestCode *code);
bool removeCase(TestCode *code, bool clean = false, bool force = false);
uint caseCount(const QString &suiteName);
void removeFunction(TestCaseItem *Case, const QString &funcName);
virtual void clear();
public slots:
void init();
// Action handlers...
virtual void testInsertUnitOrSystemTest();
virtual void selectGroup();
void updateActions();
void rescan();
void select(const QString &tcFileName, const QString &testFunc);
void select(TestCode *tc, const QString &testFunc);
void select(TestCaseRec rec);
void assignAll();
void assignAllManual();
void unassignAll();
void toggleSelection();
void onChanged(TestCode *testCode);
void onRemoved(TestCode *testCode);
void onSelectionChanged();
void onItemDoubleClicked(QTreeWidgetItem *, int);
void onActiveConfigurationChanged();
void onTestSelectionChanged(const QStringList &, QObject *);
virtual void setGeometry (int x, int y, int w, int h);
void setComponentViewMode(bool filter);
void showUnitTests(bool);
void showIntegrationTests(bool);
void showPerformanceTests(bool);
void showSystemTests(bool);
signals:
void activeConfigurationChanged();
void testSelectionChanged(const QStringList &);
protected:
virtual void keyPressEvent(QKeyEvent *e);
virtual void keyReleaseEvent(QKeyEvent *e);
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
public:
QAction *m_componentViewMode;
QAction *m_showUnitTests;
QAction *m_showIntegrationTests;
QAction *m_showPerformanceTests;
QAction *m_showSystemTests;
private:
bool removeSuite2(TestSuiteItem *base, const QString &suiteName, bool force);
void checkSuite(TestSuiteItem *testSuite, bool &selected, bool &multiSelection);
void getSelectedTests(TestSuiteItem *base, QStringList &list, bool isAssigned);
void resetGroupsMenu();
void addTest(TestCode *code);
TestCaseRec m_curTest;
TestContextMenu *m_testContextMenu;
TestCollection m_testCollection;
TestSettings m_testSettings;
QMenu *m_testMenu;
static int m_refCount;
TestViewItem *m_curItem;
QTimer m_initTimer;
TestCode::TestTypes m_hiddenTestTypes;
};
#endif

View File

@@ -0,0 +1,443 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "testsettings.h"
#include <QDir>
#include <QString>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
class TestIniFile
{
public:
TestIniFile(const QString &fileName);
virtual ~TestIniFile();
bool read(const QString &key, QString &ret);
bool read(const QString &key, int &ret);
bool read(const QString &key, uint &ret);
bool read(const QString &key, QDateTime &ret);
bool write(const QString &comment, const QString &key, const QString &value);
bool write(const QString &comment, const QString &key, int value);
bool write(const QString &comment, const QString &key, uint value);
bool write(const QString &comment, const QString &key, QDateTime value);
private:
bool initSaving(const QString &comment);
bool find(const QString &key, QString &line);
QStringList m_settings;
QString m_fileName;
QFile *m_outFile;
QTextStream *m_outStream;
};
#include <iostream>
using namespace std;
TestIniFile::TestIniFile(const QString &fileName)
{
m_outFile = 0;
m_outStream = 0;
m_fileName = fileName;
QFile F(m_fileName);
if (F.open(QIODevice::ReadOnly)) {
QTextStream ds(&F);
QString S;
while (!ds.atEnd()) {
S = ds.readLine().trimmed();
if (S != "" && !S.startsWith("#"))
m_settings.append(S);
}
}
}
TestIniFile::~TestIniFile()
{
if (m_outFile != 0) {
delete m_outStream;
delete m_outFile;
}
}
bool TestIniFile::find(const QString &key, QString &line)
{
foreach (const QString &S, m_settings) {
if (S.startsWith(key)) {
int pos = S.indexOf("=");
if (pos > 0) {
line = S.mid(pos+1).trimmed();
return true;
}
}
}
return false;
}
bool TestIniFile::read(const QString &key, QString &ret)
{
QString line;
if (find(key, line)) {
ret = line;
return true;
}
return false;
}
bool TestIniFile::read(const QString &key, int &ret)
{
QString line;
if (find(key, line)) {
bool ok;
ret = line.toInt(&ok);
return ok;
}
return false;
}
bool TestIniFile::read(const QString &key, uint &ret)
{
QString line;
if (find(key, line)) {
bool ok;
ret = line.toUInt(&ok);
return ok;
}
return false;
}
bool TestIniFile::read(const QString &key, QDateTime &ret)
{
QString line;
if (find(key, line)) {
if (line.isEmpty())
ret = QDateTime();
else
ret = QDateTime::fromString(line, Qt::ISODate);
return ret.isValid();
}
return false;
}
bool TestIniFile::initSaving(const QString &comment)
{
if (m_outFile == 0) {
m_outFile = new QFile(m_fileName);
if (m_outFile->open(QIODevice::WriteOnly)) {
m_outStream = new QTextStream(m_outFile);
*m_outStream << "#Lines with a # on the first position are remarks.\n";
*m_outStream << "#data on all other lines must be entered according to the hints.\n";
*m_outStream << "\n";
} else {
delete m_outFile;
m_outFile = 0;
return false;
}
}
foreach (const QString &S, comment.split("\n")) {
if (!S.startsWith("#"))
*m_outStream << "# ";
*m_outStream << S << "\n";
}
return true;
}
bool TestIniFile::write(const QString &comment, const QString &key, const QString &value)
{
if (!initSaving(comment))
return false;
*m_outStream << key << "=";
if (!value.isEmpty())
*m_outStream << value;
*m_outStream << "\n\n";
return true;
}
bool TestIniFile::write(const QString &comment, const QString &key, int value)
{
if (!initSaving(comment))
return false;
*m_outStream << key << "=" << QString("%1").arg(value) << "\n\n";
return true;
}
bool TestIniFile::write(const QString &comment, const QString &key, uint value)
{
if (!initSaving(comment))
return false;
*m_outStream << key << "=" << QString("%1").arg(value) << "\n\n";
return true;
}
bool TestIniFile::write(const QString &comment, const QString &key, QDateTime value)
{
if (!initSaving(comment))
return false;
*m_outStream << key << "=";
if (value.isValid())
*m_outStream << QString("%1").arg(value.toString(Qt::ISODate));
*m_outStream << "\n\n";
return true;
}
int TestSettings::m_refCount = 0;
TestSettings_p *TestSettings::d = 0;
TestSettings_p::TestSettings_p()
{
// Clear out the settings first incase there is no ini file or it's missing values
m_showPassedResults = 1;
m_showDebugResults = 1;
m_showSkippedResults = 1;
m_showVerbose = 0;
m_hiddenTestTypes = 0;
load();
}
TestSettings_p::~TestSettings_p()
{
save();
}
void TestSettings_p::emitChanged()
{
emit changed();
}
void TestSettings_p::load()
{
TestIniFile ini(QDir ::homePath() + QDir::separator() + ".qttest"
+ QDir::separator() + "saved_settings");
ini.read("showPassedResults", m_showPassedResults);
ini.read("showDebugResults", m_showDebugResults);
ini.read("showSkippedResults", m_showSkippedResults);
ini.read("showVerbose", m_showVerbose);
ini.read("autosaveOn", m_autosaveOn);
ini.read("componentViewMode", m_componentViewMode);
ini.read("uploadServer", m_uploadServer);
ini.read("systemTestRunner", m_systemTestRunner);
ini.read("learnMode", m_learnMode);
ini.read("hiddenTestTypes", m_hiddenTestTypes);
}
void TestSettings_p::save()
{
QDir().mkpath(QDir::homePath() + QDir::separator() + ".qttest");
TestIniFile ini(QDir::homePath() + QDir::separator() + ".qttest" + QDir::separator() + "saved_settings");
ini.write("Set to 1 if passed must be shown", "showPassedResults", m_showPassedResults);
ini.write("Set to 1 if debug must be shown", "showDebugResults", m_showDebugResults);
ini.write("Set to 1 if skipped must be shown", "showSkippedResults", m_showSkippedResults);
ini.write("Set to 1 for verbose logging", "showVerbose", m_showVerbose);
ini.write("Autosaving enabled/disabled", "autosaveOn", m_autosaveOn);
ini.write("Show tests in selection tree sorted by component", "componentViewMode", m_componentViewMode);
ini.write("The server to which test results will be uploaded", "uploadServer", m_uploadServer);
ini.write("The fully qualified path to the system test executer", "systemTestRunner", m_systemTestRunner);
ini.write("The current learn mode", "learnMode", m_learnMode);
ini.write("Test types hidden in selection tree", "hiddenTestTypes", m_hiddenTestTypes);
}
TestSettings::TestSettings()
{
if (m_refCount++ == 0) {
d = new TestSettings_p();
Q_ASSERT(d);
d->load();
}
connect(d, SIGNAL(changed()), this, SIGNAL(changed()));
}
TestSettings::~TestSettings()
{
if (--m_refCount == 0) {
delete d;
d = 0;
}
}
void TestSettings::save()
{
Q_ASSERT(d);
d->save();
}
bool TestSettings::showPassedResults()
{
Q_ASSERT(d);
return (d->m_showPassedResults != 0);
}
bool TestSettings::showDebugResults()
{
Q_ASSERT(d);
return (d->m_showDebugResults != 0);
}
bool TestSettings::showSkippedResults()
{
Q_ASSERT(d);
return (d->m_showSkippedResults != 0);
}
void TestSettings::setShowPassedResults(bool doShow)
{
Q_ASSERT(d);
if (d->m_showPassedResults ^ doShow) {
d->m_showPassedResults = (doShow ? 1 : 0);
d->emitChanged();
}
}
void TestSettings::setShowDebugResults(bool doShow)
{
Q_ASSERT(d);
if (d->m_showDebugResults ^ doShow) {
d->m_showDebugResults = (doShow ? 1 : 0);
d->emitChanged();
}
}
void TestSettings::setShowSkippedResults(bool doShow)
{
Q_ASSERT(d);
if (d->m_showSkippedResults ^ doShow) {
d->m_showSkippedResults = (doShow ? 1 : 0);
d->emitChanged();
}
}
bool TestSettings::showVerbose()
{
Q_ASSERT(d);
return (d->m_showVerbose != 0);
}
void TestSettings::setShowVerbose(bool doVerbose)
{
Q_ASSERT(d);
d->m_showVerbose = 0;
if (doVerbose)
d->m_showVerbose = 1;
}
bool TestSettings::autosaveOn()
{
Q_ASSERT(d);
return (d->m_autosaveOn != 0);
}
void TestSettings::setAutosaveOn(bool on)
{
Q_ASSERT(d);
if (on)
d->m_autosaveOn = 1;
else
d->m_autosaveOn = 0;
}
bool TestSettings::componentViewMode()
{
Q_ASSERT(d);
return (d->m_componentViewMode != 0);
}
void TestSettings::setComponentViewMode(bool on)
{
Q_ASSERT(d);
if (on)
d->m_componentViewMode = 1;
else
d->m_componentViewMode = 0;
}
int TestSettings::hiddenTestTypes()
{
Q_ASSERT(d);
return d->m_hiddenTestTypes;
}
void TestSettings::setHiddenTestTypes(int types)
{
Q_ASSERT(d);
d->m_hiddenTestTypes = types;
}
QString TestSettings::uploadServer() const
{
Q_ASSERT(d);
return d->m_uploadServer;
}
void TestSettings::setUploadServer(const QString &newValue)
{
Q_ASSERT(d);
d->m_uploadServer = newValue;
}
QString TestSettings::systemTestRunner() const
{
Q_ASSERT(d);
return d->m_systemTestRunner;
}
void TestSettings::setSystemTestRunner(const QString &newValue)
{
Q_ASSERT(d);
d->m_systemTestRunner = newValue;
}
int TestSettings::learnMode()
{
Q_ASSERT(d);
return d->m_learnMode;
}
void TestSettings::setLearnMode(int newMode)
{
Q_ASSERT(d);
d->m_learnMode = newMode;
}

View File

@@ -0,0 +1,115 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTSETTINGS_H
#define TESTSETTINGS_H
#include "qsystem.h"
#include <QString>
#include <QStringList>
// class TestSettings_p;
class TestSettings_p : public QObject
{
Q_OBJECT
public:
TestSettings_p();
~TestSettings_p();
void load();
void save();
void emitChanged();
int m_showPassedResults;
int m_showDebugResults;
int m_showSkippedResults;
int m_showVerbose;
QString m_uploadServer;
QString m_systemTestRunner;
int m_learnMode;
int m_autosaveOn;
int m_componentViewMode;
int m_hiddenTestTypes;
signals:
void changed();
};
class TestSettings : public QObject
{
Q_OBJECT
public:
TestSettings();
virtual ~TestSettings();
void save();
bool showPassedResults();
bool showDebugResults();
bool showSkippedResults();
void setShowPassedResults(bool doShow);
void setShowDebugResults(bool doShow);
void setShowSkippedResults(bool doShow);
bool showVerbose();
void setShowVerbose(bool doVerbose);
bool autosaveOn();
void setAutosaveOn(bool on);
QString systemTestRunner() const;
void setSystemTestRunner(const QString &newValue);
QString uploadServer() const;
void setUploadServer(const QString &newValue);
bool componentViewMode();
void setComponentViewMode(bool on);
int hiddenTestTypes();
void setHiddenTestTypes(int);
int learnMode(); // 0 = none, 1 = new, 2 = all;
void setLearnMode(int newMode);
signals:
void changed();
private:
static TestSettings_p *d;
static int m_refCount;
};
#endif

View File

@@ -0,0 +1,320 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "testsettingspropertiespage.h"
#include <projectexplorer/project.h>
#include <QtCore/QTextCodec>
#include <QDebug>
#include <QPlainTextEdit>
#include <QMessageBox>
#include <QFileDialog>
#include <QRegExp>
using namespace QtTest;
using namespace QtTest::Internal;
QString TestSettingsPanelFactory::id() const
{
return QLatin1String(TESTSETTINGS_PANEL_ID);
}
QString TestSettingsPanelFactory::displayName() const
{
return QCoreApplication::translate("TestSettingsPanelFactory", "Test Settings");
}
bool TestSettingsPanelFactory::supports(ProjectExplorer::Project *project)
{
Q_UNUSED(project);
return true;
}
ProjectExplorer::PropertiesPanel *TestSettingsPanelFactory::createPanel(ProjectExplorer::Project *project)
{
ProjectExplorer::PropertiesPanel *panel = new ProjectExplorer::PropertiesPanel;
panel->setWidget(new TestSettingsWidget(project));
panel->setIcon(QIcon(":/projectexplorer/images/EditorSettings.png"));
panel->setDisplayName(QCoreApplication::translate("TestSettingsPanel", "Test Settings"));
return panel;
}
TestSettingsWidget::TestSettingsWidget(ProjectExplorer::Project *project) :
QWidget(),
m_project(project)
{
m_ui.setupUi(this);
TestConfigurations::instance().delayConfigUpdates(true);
m_uploadMode.addButton(m_ui.upload_auto, 0);
m_uploadMode.addButton(m_ui.upload_ask_me, 1);
m_uploadMode.addButton(m_ui.upload_no_thanks, 2);
m_uploadMethod.addButton(m_ui.upload_scp, 0);
m_uploadMethod.addButton(m_ui.upload_email, 1);
m_testConfig = TestConfigurations::instance().config(project->displayName());
if (m_testConfig) {
m_ui.auto_detect_platform_configuration->setChecked(m_testConfig->autoDetectPlatformConfiguration());
m_ui.upload_change->setText(m_testConfig->uploadChange());
m_ui.upload_branch->setText(m_testConfig->uploadBranch());
m_ui.upload_branch_Specialization->setText(m_testConfig->uploadBranchSpecialization());
m_ui.host_platform->setText(m_testConfig->uploadPlatform());
m_ui.qmakespec->setText(m_testConfig->QMAKESPEC());
m_ui.qmakespecSpecialization->setText(m_testConfig->QMAKESPECSpecialization());
m_ui.upload_scp->setChecked(m_testConfig->uploadUsingScp());
m_ui.upload_email->setChecked(m_testConfig->uploadUsingEMail());
setExtraDirectories(m_testConfig->extraTests());
switch (m_testConfig->uploadMode()) {
case TestConfig::UploadAuto:
m_ui.upload_auto->setChecked(true);
break;
case TestConfig::UploadAskMe:
m_ui.upload_ask_me->setChecked(true);
break;
case TestConfig::UploadNoThanks:
m_ui.upload_no_thanks->setChecked(true);
break;
}
}
m_ui.upload_server->setText(m_testSettings.uploadServer());
m_ui.show_passed_results->setChecked(m_testSettings.showPassedResults());
m_ui.show_debug_results->setChecked(m_testSettings.showDebugResults());
m_ui.show_skipped_results->setChecked(m_testSettings.showSkippedResults());
m_ui.show_verbose_make_results->setChecked(m_testSettings.showVerbose());
onChanged();
connect(m_ui.upload_change, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.upload_branch, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.upload_branch_Specialization, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.auto_detect_platform_configuration, SIGNAL(toggled(bool)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.qmakespec, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.qmakespecSpecialization, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.upload_server, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.host_platform, SIGNAL(textEdited(QString)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.show_passed_results, SIGNAL(toggled(bool)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.show_debug_results, SIGNAL(toggled(bool)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.show_skipped_results, SIGNAL(toggled(bool)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.show_verbose_make_results, SIGNAL(toggled(bool)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(&m_uploadMode, SIGNAL(buttonClicked(int)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(&m_uploadMethod, SIGNAL(buttonClicked(int)),
this, SLOT(onChanged()), Qt::DirectConnection);
connect(m_ui.add_directory_btn, SIGNAL(pressed()),
this, SLOT(onAddDirectoryBtnClicked()), Qt::DirectConnection);
connect(m_ui.clear_directory_btn, SIGNAL(pressed()),
this, SLOT(onClearDirectoryBtnClicked()), Qt::DirectConnection);
connect(&m_testSettings, SIGNAL(changed()),
this, SLOT(onSettingsChanged()), Qt::DirectConnection);
setFocusPolicy(Qt::StrongFocus);
}
TestSettingsWidget::~TestSettingsWidget()
{
m_testSettings.save();
TestConfigurations::instance().delayConfigUpdates(false);
}
// Update settings before focus moves away from widget
void TestSettingsWidget::leaveEvent(QEvent *event)
{
m_testSettings.save();
TestConfigurations::instance().delayConfigUpdates(false);
QWidget::leaveEvent(event);
}
void TestSettingsWidget::enterEvent(QEvent *event)
{
TestConfigurations::instance().delayConfigUpdates(true);
QWidget::enterEvent(event);
}
void TestSettingsWidget::onChanged()
{
if (m_testConfig) {
bool auto_detect = m_ui.auto_detect_platform_configuration->isChecked();
bool auto_detect_enabled = (auto_detect && !m_testConfig->autoDetectPlatformConfiguration());
m_testConfig->setAutoDetectPlatformConfiguration(auto_detect);
m_testConfig->setUploadMethod(m_ui.upload_scp->isChecked());
m_testConfig->setExtraTests(extraDirectories());
m_ui.upload_change->setEnabled(!auto_detect);
m_ui.upload_branch->setEnabled(!auto_detect);
m_ui.host_platform->setEnabled(!auto_detect);
m_ui.qmakespec->setEnabled(!auto_detect);
m_ui.platform_label->setEnabled(!auto_detect);
m_ui.change_label->setEnabled(!auto_detect);
m_ui.branch_label->setEnabled(!auto_detect);
m_ui.qmakespec_label->setEnabled(!auto_detect);
if (auto_detect) {
m_ui.upload_change->setText(m_testConfig->uploadChange());
m_ui.upload_branch->setText(m_testConfig->uploadBranch());
m_ui.host_platform->setText(m_testConfig->uploadPlatform());
QString device_name;
Utils::SshConnectionParameters dummy(Utils::SshConnectionParameters::DefaultProxy);
QString device_type;
// do not override current choice using remote target name unless
// auto detect was just enabled by user.
if (auto_detect_enabled) {
m_ui.qmakespec->setText(m_testConfig->QMAKESPEC());
// refresh qmakespec value from autodetected value
m_testConfig->setQMAKESPEC(m_ui.qmakespec->text().trimmed());
if (m_testConfig->isRemoteTarget(device_name, device_type, dummy)){
// update branch and qmakespec specialization
m_ui.qmakespecSpecialization->setText(device_name);
m_testConfig->setQMAKESPECSpecialization(m_ui.qmakespecSpecialization->text().trimmed());
m_ui.upload_branch_Specialization->setText(device_name);
m_testConfig->setUploadBranchSpecialization(m_ui.upload_branch_Specialization->text().trimmed());
}
}
} else {
m_testConfig->setUploadChange(m_ui.upload_change->text().trimmed());
m_testConfig->setUploadBranch(m_ui.upload_branch->text().trimmed());
m_testConfig->setUploadPlatform(m_ui.host_platform->text().trimmed());
m_testConfig->setQMAKESPEC(m_ui.qmakespec->text().trimmed());
m_testConfig->setQMAKESPECSpecialization(m_ui.qmakespecSpecialization->text().trimmed());
m_testConfig->setUploadBranchSpecialization(m_ui.upload_branch_Specialization->text().trimmed());
}
m_testConfig->setUploadMode((TestConfig::UploadMode)m_uploadMode.checkedId());
}
// the effective branch and qmakespec is computed in TestExecuter::runSelectedTests()
// use same logic here to support the display of the actual branch and qmakespec
// to be used when uploading test results
if (!m_ui.upload_branch_Specialization->text().trimmed().isEmpty())
m_ui.effectiveBranchName->setText(m_ui.upload_branch->text().trimmed()
+ "-" + m_ui.upload_branch_Specialization->text().trimmed());
else
m_ui.effectiveBranchName->setText(m_ui.upload_branch->text().trimmed());
if (!m_ui.qmakespecSpecialization->text().trimmed().isEmpty())
m_ui.effectiveQMakespec->setText(m_ui.qmakespec->text().trimmed()
+ "_" + m_ui.qmakespecSpecialization->text().trimmed());
else
m_ui.effectiveQMakespec->setText(m_ui.qmakespec->text().trimmed());
m_testSettings.setUploadServer(m_ui.upload_server->text());
m_testSettings.setShowPassedResults(m_ui.show_passed_results->isChecked());
m_testSettings.setShowDebugResults(m_ui.show_debug_results->isChecked());
m_testSettings.setShowSkippedResults(m_ui.show_skipped_results->isChecked());
m_testSettings.setShowVerbose(m_ui.show_verbose_make_results->isChecked());
}
void TestSettingsWidget::onUploadScpChanged()
{
m_ui.upload_email->setChecked(!m_ui.upload_scp->isChecked());
onChanged();
}
void TestSettingsWidget::onUploadEMailChanged()
{
m_ui.upload_scp->setChecked(!m_ui.upload_email->isChecked());
onChanged();
}
void TestSettingsWidget::onAddDirectoryBtnClicked()
{
QString newDirectory = QFileDialog::getExistingDirectory(this, "Choose Extra Test Directory");
if (!newDirectory.isEmpty())
m_ui.extra_tests->addItem(newDirectory);
onChanged();
}
void TestSettingsWidget::onClearDirectoryBtnClicked()
{
m_ui.extra_tests->clear();
onChanged();
}
void TestSettingsWidget::onSettingsChanged()
{
if (m_ui.show_passed_results->isChecked() != m_testSettings.showPassedResults())
m_ui.show_passed_results->setChecked(m_testSettings.showPassedResults());
if (m_ui.show_debug_results->isChecked() != m_testSettings.showDebugResults())
m_ui.show_debug_results->setChecked(m_testSettings.showDebugResults());
if (m_ui.show_skipped_results->isChecked() != m_testSettings.showSkippedResults())
m_ui.show_skipped_results->setChecked(m_testSettings.showSkippedResults());
}
QStringList TestSettingsWidget::extraDirectories() const
{
QStringList result;
for (int index = 0; index < m_ui.extra_tests->count(); ++index)
result.append(m_ui.extra_tests->item(index)->text());
return result;
}
void TestSettingsWidget::setExtraDirectories(const QStringList list)
{
m_ui.extra_tests->clear();
foreach (const QString &s, list)
m_ui.extra_tests->addItem(s);
}

View File

@@ -0,0 +1,92 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTSETTINGSPROPERTIESPAGE_H
#define TESTSETTINGSPROPERTIESPAGE_H
#include "testconfigurations.h"
#include "testsettings.h"
#include <projectexplorer/iprojectproperties.h>
#include <projectexplorer/iprojectmanager.h>
#include <ui_testsettingspropertiespage.h>
#include <QStringList>
namespace QtTest {
namespace Internal {
const char * const TESTSETTINGS_PANEL_ID("QtTest.TestSettingsPanel");
class TestSettingsPanelFactory : public ProjectExplorer::IProjectPanelFactory
{
public:
QString id() const;
QString displayName() const;
ProjectExplorer::PropertiesPanel *createPanel(ProjectExplorer::Project *project);
bool supports(ProjectExplorer::Project *project);
};
class TestSettingsWidget : public QWidget
{
Q_OBJECT
public:
TestSettingsWidget(ProjectExplorer::Project *project);
virtual ~TestSettingsWidget();
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
public slots:
void onChanged();
void onUploadScpChanged();
void onUploadEMailChanged();
void onAddDirectoryBtnClicked();
void onClearDirectoryBtnClicked();
void onSettingsChanged();
private:
QStringList extraDirectories() const;
void setExtraDirectories(const QStringList list);
TestSettings m_testSettings;
Ui::TestSettingsPropertiesPage m_ui;
ProjectExplorer::Project *m_project;
TestConfig *m_testConfig;
QButtonGroup m_uploadMode;
QButtonGroup m_uploadMethod;
};
} // namespace Internal
} // namespace QtTest
#endif // TESTSETTINGSPROPERTIESPAGE_H

View File

@@ -0,0 +1,485 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QtTest::Internal::TestSettingsPropertiesPage</class>
<widget class="QWidget" name="QtTest::Internal::TestSettingsPropertiesPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>590</width>
<height>704</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>General</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="show_passed_results">
<property name="text">
<string>Show passing test results</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="show_debug_results">
<property name="text">
<string>Show debug messages in test tesults</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="show_skipped_results">
<property name="text">
<string>Show skipped test results</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="show_verbose_make_results">
<property name="text">
<string>Show verbose make results</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Extra tests</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Directories that contain extra tests that are relevant for this project:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="add_directory_btn">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="clear_directory_btn">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="extra_tests">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Platform configuration</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="auto_detect_platform_configuration">
<property name="text">
<string>Auto detect platform configuration</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="change_label">
<property name="text">
<string>Change</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="upload_change">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>The SHA1 of the code under test</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="branch_label">
<property name="text">
<string>Branch</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="effectiveBranchName">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="upload_branch">
<property name="toolTip">
<string>The branch related to test, eg: &lt;Product&gt;-&lt;Version&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="upload_branch_Specialization_label">
<property name="text">
<string>Specialization</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="upload_branch_Specialization">
<property name="toolTip">
<string>The value to be automatically appended to branch, e.g &lt;DeviceName&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="platform_label">
<property name="text">
<string>Host platform</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="host_platform">
<property name="toolTip">
<string>The host platform running QtCreator, e.g: Linux</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Qmakespec</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="effectiveQMakespec">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="qmakespec_label">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="qmakespec">
<property name="toolTip">
<string>The reference for the plaform under test, e.g: &lt;MkSpec&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="qmakespecSpecialization_label">
<property name="text">
<string>Specialization</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="qmakespecSpecialization">
<property name="toolTip">
<string>The value to be automatically appended to Qmakespec, e.g &lt;DeviceName&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Test result upload method</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Result uploading:</string>
</property>
</widget>
</item>
<item row="0" column="2" colspan="2">
<widget class="QRadioButton" name="upload_auto">
<property name="text">
<string>Automatic (recommended)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QRadioButton" name="upload_ask_me">
<property name="text">
<string>Ask me</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QRadioButton" name="upload_no_thanks">
<property name="text">
<string>No thanks</string>
</property>
</widget>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>84</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Method:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="upload_scp">
<property name="text">
<string>Scp</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QRadioButton" name="upload_email">
<property name="text">
<string>E-mail</string>
</property>
</widget>
</item>
<item row="1" column="3" colspan="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>404</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="7">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="server_label">
<property name="text">
<string>Upload server</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="upload_server">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For the &lt;span style=&quot; font-weight:600;&quot;&gt;scp&lt;/span&gt; upload method the upload server location must be in the form:&lt;span style=&quot; font-weight:600;&quot;&gt; &lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;&amp;lt;user&amp;gt;@&amp;lt;ServerHost&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-weight:600; font-style:italic;&quot;&gt;:/home/qt/results &lt;/span&gt;and a passphraseless SSH public key uploaded to the server.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>show_passed_results</tabstop>
<tabstop>show_debug_results</tabstop>
<tabstop>show_skipped_results</tabstop>
<tabstop>show_verbose_make_results</tabstop>
<tabstop>add_directory_btn</tabstop>
<tabstop>clear_directory_btn</tabstop>
<tabstop>auto_detect_platform_configuration</tabstop>
<tabstop>upload_change</tabstop>
<tabstop>upload_branch</tabstop>
<tabstop>upload_branch_Specialization</tabstop>
<tabstop>host_platform</tabstop>
<tabstop>qmakespec</tabstop>
<tabstop>qmakespecSpecialization</tabstop>
<tabstop>upload_auto</tabstop>
<tabstop>upload_ask_me</tabstop>
<tabstop>upload_no_thanks</tabstop>
<tabstop>upload_scp</tabstop>
<tabstop>upload_email</tabstop>
<tabstop>upload_server</tabstop>
<tabstop>extra_tests</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,50 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef TESTSUITE_H
#define TESTSUITE_H
#include "testcode.h"
#include <QString>
#include <QPointer>
class TestCaseRec
{
public:
QPointer<TestCode> m_code;
QString m_testFunction;
QString m_basePath;
int m_line;
};
#endif