forked from qt-creator/qt-creator
AutoTest: Handle test tools inside project settings
This effectively enables to handle ctest project wise instead of just globally. So far only code based test frameworks could be enabled or disabled by project. Change-Id: I491f91119c3500131ca51af4d55b0e68d47debf0 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "testtreemodel.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QComboBox>
|
||||
@@ -40,7 +41,10 @@
|
||||
namespace Autotest {
|
||||
namespace Internal {
|
||||
|
||||
enum ItemDataRole { FrameworkIdRole = Qt::UserRole + 1 };
|
||||
enum ItemDataRole {
|
||||
BaseIdRole = Qt::UserRole + 1,
|
||||
BaseTypeRole
|
||||
};
|
||||
|
||||
static QSpacerItem *createSpacer(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
|
||||
{
|
||||
@@ -90,13 +94,15 @@ ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *p
|
||||
m_useGlobalSettings->setCurrentIndex(m_projectSettings->useGlobalSettings() ? 0 : 1);
|
||||
generalWidget->setDisabled(m_projectSettings->useGlobalSettings());
|
||||
|
||||
populateFrameworks(m_projectSettings->activeFrameworks());
|
||||
populateFrameworks(m_projectSettings->activeFrameworks(),
|
||||
m_projectSettings->activeTestTools());
|
||||
|
||||
connect(m_useGlobalSettings, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, [this, generalWidget](int index) {
|
||||
generalWidget->setEnabled(index != 0);
|
||||
m_projectSettings->setUseGlobalSettings(index == 0);
|
||||
m_syncFrameworksTimer.start(3000);
|
||||
m_syncTimer.start(3000);
|
||||
m_syncType = ITestBase::Framework | ITestBase::Tool;
|
||||
});
|
||||
connect(m_activeFrameworks, &QTreeWidget::itemChanged,
|
||||
this, &ProjectTestSettingsWidget::onActiveFrameworkChanged);
|
||||
@@ -104,29 +110,53 @@ ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *p
|
||||
this, [this](int index) {
|
||||
m_projectSettings->setRunAfterBuild(RunAfterBuildMode(index));
|
||||
});
|
||||
m_syncFrameworksTimer.setSingleShot(true);
|
||||
connect(&m_syncFrameworksTimer, &QTimer::timeout,
|
||||
TestTreeModel::instance(), &TestTreeModel::synchronizeTestFrameworks);
|
||||
m_syncTimer.setSingleShot(true);
|
||||
connect(&m_syncTimer, &QTimer::timeout,
|
||||
[this]() {
|
||||
auto testTreeModel = TestTreeModel::instance();
|
||||
if (m_syncType & ITestBase::Framework)
|
||||
testTreeModel->synchronizeTestFrameworks();
|
||||
if (m_syncType & ITestBase::Tool)
|
||||
testTreeModel->synchronizeTestTools();
|
||||
m_syncType = ITestBase::None;
|
||||
});
|
||||
}
|
||||
|
||||
void ProjectTestSettingsWidget::populateFrameworks(const QHash<ITestFramework *, bool> &frameworks)
|
||||
void ProjectTestSettingsWidget::populateFrameworks(const QHash<ITestFramework *, bool> &frameworks,
|
||||
const QHash<ITestTool *, bool> &testTools)
|
||||
{
|
||||
TestFrameworks sortedFrameworks = frameworks.keys();
|
||||
Utils::sort(sortedFrameworks, &ITestFramework::priority);
|
||||
|
||||
for (ITestFramework *framework : sortedFrameworks) {
|
||||
auto item = new QTreeWidgetItem(m_activeFrameworks, QStringList(QLatin1String(framework->name())));
|
||||
auto generateItem = [this](ITestBase *frameworkOrTestTool, bool checked) {
|
||||
auto item = new QTreeWidgetItem(m_activeFrameworks, {QLatin1String(frameworkOrTestTool->name())});
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(0, frameworks.value(framework) ? Qt::Checked : Qt::Unchecked);
|
||||
item->setData(0, FrameworkIdRole, framework->id().toSetting());
|
||||
}
|
||||
item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
|
||||
item->setData(0, BaseIdRole, frameworkOrTestTool->id().toSetting());
|
||||
item->setData(0, BaseTypeRole, frameworkOrTestTool->type());
|
||||
};
|
||||
|
||||
for (ITestFramework *framework : qAsConst(sortedFrameworks))
|
||||
generateItem(framework, frameworks.value(framework));
|
||||
|
||||
// FIXME: testTools aren't sorted and we cannot use priority here
|
||||
auto end = testTools.cend();
|
||||
for (auto it = testTools.cbegin(); it != end; ++it)
|
||||
generateItem(it.key(), it.value());
|
||||
}
|
||||
|
||||
void ProjectTestSettingsWidget::onActiveFrameworkChanged(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
auto id = Utils::Id::fromSetting(item->data(column, FrameworkIdRole));
|
||||
m_projectSettings->activateFramework(id, item->data(0, Qt::CheckStateRole) == Qt::Checked);
|
||||
m_syncFrameworksTimer.start(3000);
|
||||
auto id = Utils::Id::fromSetting(item->data(column, BaseIdRole));
|
||||
int type = item->data(column, BaseTypeRole).toInt();
|
||||
if (type == ITestBase::Framework)
|
||||
m_projectSettings->activateFramework(id, item->data(0, Qt::CheckStateRole) == Qt::Checked);
|
||||
else if (type == ITestBase::Tool)
|
||||
m_projectSettings->activateTestTool(id, item->data(0, Qt::CheckStateRole) == Qt::Checked);
|
||||
else
|
||||
QTC_ASSERT(! "unexpected test base type", return);
|
||||
m_syncTimer.start(3000);
|
||||
m_syncType |= type;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace ProjectExplorer { class Project; }
|
||||
namespace Autotest {
|
||||
|
||||
class ITestFramework;
|
||||
class ITestTool;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
@@ -51,13 +52,15 @@ public:
|
||||
explicit ProjectTestSettingsWidget(ProjectExplorer::Project *project,
|
||||
QWidget *parent = nullptr);
|
||||
private:
|
||||
void populateFrameworks(const QHash<Autotest::ITestFramework *, bool> &frameworks);
|
||||
void populateFrameworks(const QHash<Autotest::ITestFramework *, bool> &frameworks,
|
||||
const QHash<Autotest::ITestTool *, bool> &testTools);
|
||||
void onActiveFrameworkChanged(QTreeWidgetItem *item, int column);
|
||||
TestProjectSettings *m_projectSettings;
|
||||
QComboBox *m_useGlobalSettings = nullptr;
|
||||
QTreeWidget *m_activeFrameworks = nullptr;
|
||||
QComboBox *m_runAfterBuild = nullptr;
|
||||
QTimer m_syncFrameworksTimer;
|
||||
QTimer m_syncTimer;
|
||||
int m_syncType = 0;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -99,6 +99,14 @@ ITestFramework *TestFrameworkManager::frameworkForId(Id frameworkId)
|
||||
});
|
||||
}
|
||||
|
||||
ITestTool *TestFrameworkManager::testToolForId(Id testToolId)
|
||||
{
|
||||
return Utils::findOrDefault(s_instance->m_registeredTestTools,
|
||||
[testToolId](ITestTool *testTool) {
|
||||
return testTool->id() == testToolId;
|
||||
});
|
||||
}
|
||||
|
||||
ITestTool *TestFrameworkManager::testToolForBuildSystemId(Id buildSystemId)
|
||||
{
|
||||
if (!buildSystemId.isValid())
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
void synchronizeSettings(QSettings *s);
|
||||
|
||||
static ITestFramework *frameworkForId(Utils::Id frameworkId);
|
||||
static ITestTool *testToolForId(Utils::Id testToolId);
|
||||
static ITestTool *testToolForBuildSystemId(Utils::Id buildSystemId);
|
||||
static void activateFrameworksAndToolsFromSettings(const Internal::TestSettings *settings);
|
||||
static const TestFrameworks registeredFrameworks();
|
||||
|
||||
@@ -73,26 +73,43 @@ void TestProjectSettings::activateFramework(const Utils::Id &id, bool activate)
|
||||
framework->resetRootNode();
|
||||
}
|
||||
|
||||
void TestProjectSettings::activateTestTool(const Utils::Id &id, bool activate)
|
||||
{
|
||||
ITestTool *testTool = TestFrameworkManager::testToolForId(id);
|
||||
m_activeTestTools[testTool] = activate;
|
||||
if (!activate)
|
||||
testTool->resetRootNode();
|
||||
}
|
||||
|
||||
void TestProjectSettings::load()
|
||||
{
|
||||
const QVariant useGlobal = m_project->namedSettings(Constants::SK_USE_GLOBAL);
|
||||
m_useGlobalSettings = useGlobal.isValid() ? useGlobal.toBool() : true;
|
||||
|
||||
const TestFrameworks registered = TestFrameworkManager::registeredFrameworks();
|
||||
qCDebug(LOG) << "Registered frameworks sorted by priority" << registered;
|
||||
const TestFrameworks registeredFrameworks = TestFrameworkManager::registeredFrameworks();
|
||||
qCDebug(LOG) << "Registered frameworks sorted by priority" << registeredFrameworks;
|
||||
const TestTools registeredTestTools = TestFrameworkManager::registeredTestTools();
|
||||
const QVariant activeFrameworks = m_project->namedSettings(SK_ACTIVE_FRAMEWORKS);
|
||||
|
||||
m_activeTestFrameworks.clear();
|
||||
m_activeTestTools.clear();
|
||||
if (activeFrameworks.isValid()) {
|
||||
const QMap<QString, QVariant> frameworksMap = activeFrameworks.toMap();
|
||||
for (ITestFramework *framework : registered) {
|
||||
for (ITestFramework *framework : registeredFrameworks) {
|
||||
const Utils::Id id = framework->id();
|
||||
bool active = frameworksMap.value(id.toString(), framework->active()).toBool();
|
||||
m_activeTestFrameworks.insert(framework, active);
|
||||
}
|
||||
for (ITestTool *testTool : registeredTestTools) {
|
||||
const Utils::Id id = testTool->id();
|
||||
bool active = frameworksMap.value(id.toString(), testTool->active()).toBool();
|
||||
m_activeTestTools.insert(testTool, active);
|
||||
}
|
||||
} else {
|
||||
for (ITestFramework *framework : registered)
|
||||
for (ITestFramework *framework : registeredFrameworks)
|
||||
m_activeTestFrameworks.insert(framework, framework->active());
|
||||
for (ITestTool *testTool : registeredTestTools)
|
||||
m_activeTestTools.insert(testTool, testTool->active());
|
||||
}
|
||||
|
||||
const QVariant runAfterBuild = m_project->namedSettings(SK_RUN_AFTER_BUILD);
|
||||
@@ -108,6 +125,9 @@ void TestProjectSettings::save()
|
||||
auto end = m_activeTestFrameworks.cend();
|
||||
for (auto it = m_activeTestFrameworks.cbegin(); it != end; ++it)
|
||||
activeFrameworks.insert(it.key()->id().toString(), it.value());
|
||||
auto endTools = m_activeTestTools.cend();
|
||||
for (auto it = m_activeTestTools.cbegin(); it != endTools; ++it)
|
||||
activeFrameworks.insert(it.key()->id().toString(), it.value());
|
||||
m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks);
|
||||
m_project->setNamedSettings(SK_RUN_AFTER_BUILD, int(m_runAfterBuild));
|
||||
m_project->setNamedSettings(SK_CHECK_STATES, m_checkStateCache.toSettings());
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace ProjectExplorer { class Project; }
|
||||
namespace Autotest {
|
||||
|
||||
class ITestFramework;
|
||||
class ITestTool;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
@@ -40,17 +41,21 @@ class TestProjectSettings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestProjectSettings(ProjectExplorer::Project *project);
|
||||
explicit TestProjectSettings(ProjectExplorer::Project *project);
|
||||
~TestProjectSettings();
|
||||
|
||||
void setUseGlobalSettings(bool useGlobal);
|
||||
bool useGlobalSettings() const { return m_useGlobalSettings; }
|
||||
void setRunAfterBuild(RunAfterBuildMode mode) {m_runAfterBuild = mode; }
|
||||
RunAfterBuildMode runAfterBuild() const { return m_runAfterBuild; }
|
||||
void setActiveFrameworks(const QHash<ITestFramework *, bool> enabledFrameworks)
|
||||
void setActiveFrameworks(const QHash<ITestFramework *, bool> &enabledFrameworks)
|
||||
{ m_activeTestFrameworks = enabledFrameworks; }
|
||||
QHash<ITestFramework *, bool> activeFrameworks() const { return m_activeTestFrameworks; }
|
||||
void activateFramework(const Utils::Id &id, bool activate);
|
||||
void setActiveTestTools(const QHash<ITestTool *, bool> &enabledTestTools)
|
||||
{ m_activeTestTools = enabledTestTools; }
|
||||
QHash<ITestTool *, bool> activeTestTools() const { return m_activeTestTools; }
|
||||
void activateTestTool(const Utils::Id &id, bool activate);
|
||||
Internal::ItemDataCache<Qt::CheckState> *checkStateCache() { return &m_checkStateCache; }
|
||||
private:
|
||||
void load();
|
||||
@@ -60,6 +65,7 @@ private:
|
||||
bool m_useGlobalSettings = true;
|
||||
RunAfterBuildMode m_runAfterBuild = RunAfterBuildMode::None;
|
||||
QHash<ITestFramework *, bool> m_activeTestFrameworks;
|
||||
QHash<ITestTool *, bool> m_activeTestTools;
|
||||
Internal::ItemDataCache<Qt::CheckState> m_checkStateCache;
|
||||
};
|
||||
|
||||
|
||||
@@ -353,7 +353,21 @@ void TestTreeModel::synchronizeTestFrameworks()
|
||||
|
||||
void TestTreeModel::synchronizeTestTools()
|
||||
{
|
||||
// currently no project settings...
|
||||
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
|
||||
TestTools tools;
|
||||
if (!project || AutotestPlugin::projectSettings(project)->useGlobalSettings()) {
|
||||
tools = Utils::filtered(TestFrameworkManager::registeredTestTools(),
|
||||
&ITestFramework::active);
|
||||
qCDebug(LOG) << "Active test tools" << tools; // FIXME tools aren't sorted
|
||||
} else { // we've got custom project settings
|
||||
const TestProjectSettings *settings = AutotestPlugin::projectSettings(project);
|
||||
const QHash<ITestTool *, bool> active = settings->activeTestTools();
|
||||
tools = Utils::filtered(TestFrameworkManager::registeredTestTools(),
|
||||
[active](ITestTool *testTool) {
|
||||
return active.value(testTool, false);
|
||||
});
|
||||
}
|
||||
|
||||
// pre-check to avoid further processing when test tools are unchanged
|
||||
Utils::TreeItem *invisibleRoot = rootItem();
|
||||
QSet<ITestTool *> newlyAdded;
|
||||
@@ -367,7 +381,7 @@ void TestTreeModel::synchronizeTestTools()
|
||||
for (ITestTreeItem *oldFrameworkRoot : oldFrameworkRoots)
|
||||
takeItem(oldFrameworkRoot); // do NOT delete the ptr is still held by TestFrameworkManager
|
||||
|
||||
for (ITestTool *testTool : TestFrameworkManager::registeredTestTools()) {
|
||||
for (ITestTool *testTool : tools) {
|
||||
ITestTreeItem *testToolRootNode = testTool->rootNode();
|
||||
if (testTool->active()) {
|
||||
invisibleRoot->appendChild(testToolRootNode);
|
||||
@@ -376,7 +390,6 @@ void TestTreeModel::synchronizeTestTools()
|
||||
}
|
||||
}
|
||||
|
||||
const Project *project = SessionManager::startupProject();
|
||||
if (project) {
|
||||
const QList<Target *> &allTargets = project->targets();
|
||||
auto target = allTargets.empty() ? nullptr : allTargets.first();
|
||||
|
||||
Reference in New Issue
Block a user