From e9b28403273fb2522ecf34164f8f768bbc7c644e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 16 Apr 2015 14:04:36 +0200 Subject: [PATCH] Provide 'Run This Test' context menu entry This menu entry will be added only if current selected test (function) is not an unnamed Quick Test. Otherwise it's now possible to execute a particular test case or just a single test function by using the context menu. This avoids the need of (de)selecting inside the model. Change-Id: I857a3ffe72c72a9dbb06e948045cfe2c7843935d Reviewed-by: David Schulz Reviewed-by: Christian Stenger --- plugins/autotest/testnavigationwidget.cpp | 44 +++++++++++++++++++ plugins/autotest/testnavigationwidget.h | 1 + plugins/autotest/testtreemodel.cpp | 51 +++++++++++++++++++++++ plugins/autotest/testtreemodel.h | 4 +- 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index f9847a57827..da0de8a7619 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -89,7 +89,27 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) const bool enabled = !TestRunner::instance()->isTestRunning() && m_model->parser()->state() == TestCodeParser::Idle; const bool hasTests = m_model->hasTests(); + QMenu menu; + QAction *runThisTest = 0; + const QModelIndexList list = m_view->selectionModel()->selectedIndexes(); + if (list.size() == 1) { + const QModelIndex index = list.first(); + QRect rect(m_view->visualRect(index)); + if (rect.contains(event->pos())) { + // do not provide this menu entry for unnamed Quick Tests as it makes no sense + int type = index.data(TypeRole).toInt(); + const QString &unnamed = tr(Constants::UNNAMED_QUICKTESTS); + if ((type == TestTreeItem::TEST_FUNCTION && index.parent().data().toString() != unnamed) + || (type == TestTreeItem::TEST_CLASS && index.data().toString() != unnamed)) { + runThisTest = new QAction(tr("Run This Test"), &menu); + runThisTest->setEnabled(enabled); + connect(runThisTest, &QAction::triggered, + this, &TestNavigationWidget::onRunThisTestTriggered); + } + } + } + QAction *runAll = Core::ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action(); QAction *runSelected = Core::ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action(); QAction *selectAll = new QAction(tr("Select All"), &menu); @@ -106,6 +126,10 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) deselectAll->setEnabled(enabled && hasTests); rescan->setEnabled(enabled); + if (runThisTest) { + menu.addAction(runThisTest); + menu.addSeparator(); + } menu.addAction(runAll); menu.addAction(runSelected); menu.addSeparator(); @@ -210,6 +234,26 @@ void TestNavigationWidget::initializeFilterMenu() m_filterMenu->addAction(action); } +void TestNavigationWidget::onRunThisTestTriggered() +{ + const QModelIndexList selected = m_view->selectionModel()->selectedIndexes(); + // paranoia + if (selected.isEmpty()) + return; + const QModelIndex sourceIndex = m_sortFilterModel->mapToSource(selected.first()); + if (!sourceIndex.isValid()) + return; + + TestTreeItem *item = static_cast(sourceIndex.internalPointer()); + if (item->type() == TestTreeItem::TEST_CLASS || item->type() == TestTreeItem::TEST_FUNCTION) { + if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests( {configuration} ); + runner->runTests(); + } + } +} + TestNavigationWidgetFactory::TestNavigationWidgetFactory() { setDisplayName(tr("Tests")); diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index a4b4c6f0610..ef281308170 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -69,6 +69,7 @@ private slots: private: void initializeFilterMenu(); + void onRunThisTestTriggered(); TestTreeModel *m_model; TestTreeSortFilterModel *m_sortFilterModel; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 602cea007a7..4639cbd1e94 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -255,6 +255,8 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const default: return false; } + case TypeRole: + return item->type(); } // TODO ? @@ -506,6 +508,55 @@ QList TestTreeModel::getSelectedTests() const return result; } +TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) const +{ + QTC_ASSERT(item != 0, return 0); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + QTC_ASSERT(project, return 0); + + TestConfiguration *config = 0; + switch (item->type()) { + case TestTreeItem::TEST_CLASS: { + if (item->parent() == m_quickTestRootItem) { + // Quick Test TestCase + QStringList testFunctions; + for (int row = 0, count = item->childCount(); row < count; ++row) { + testFunctions << item->name() + QLatin1String("::") + item->child(row)->name(); + } + config = new TestConfiguration(QString(), testFunctions); + config->setMainFilePath(item->mainFile()); + config->setProject(project); + } else { + // normal auto test + config = new TestConfiguration(item->name(), QStringList(), item->childCount()); + config->setMainFilePath(item->filePath()); + config->setProject(project); + } + break; + } + case TestTreeItem::TEST_FUNCTION: { + const TestTreeItem *parent = item->parent(); + if (parent->parent() == m_quickTestRootItem) { + // it's a Quick Test function of a named TestCase + QStringList testFunction(parent->name() + QLatin1String("::") + item->name()); + config = new TestConfiguration(QString(), testFunction); + config->setMainFilePath(parent->mainFile()); + config->setProject(project); + } else { + // normal auto test + config = new TestConfiguration(parent->name(), QStringList() << item->name()); + config->setMainFilePath(parent->filePath()); + config->setProject(project); + } + break; + } + // not supported items + default: + return 0; + } + return config; +} + QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) const { const TestTreeItem *unnamed = unnamedQuickTests(); diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 15a00ecb387..785606c36a8 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -31,7 +31,8 @@ namespace { enum ItemRole { // AnnotationRole = Qt::UserRole + 1, LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back - ItalicRole // used only inside the delegate + ItalicRole, // used only inside the delegate + TypeRole }; } @@ -71,6 +72,7 @@ public: bool hasTests() const; QList getAllTestCases() const; QList getSelectedTests() const; + TestConfiguration *getTestConfiguration(const TestTreeItem *item) const; QString getMainFileForUnnamedQuickTest(const QString &qmlFile) const; void qmlFilesForMainFile(const QString &mainFile, QSet *filePaths) const; QList getUnnamedQuickTestFunctions() const;