forked from qt-creator/qt-creator
AutoTest: Add possibility to trigger test run from source
Change-Id: Iceed69747de64d76f34451d41f719c8dbdd81e44 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -11,6 +11,7 @@ QtcPlugin {
|
|||||||
Depends { name: "QmlJSTools" }
|
Depends { name: "QmlJSTools" }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
Depends { name: "Debugger" }
|
Depends { name: "Debugger" }
|
||||||
|
Depends { name: "TextEditor" }
|
||||||
|
|
||||||
pluginTestDepends: [
|
pluginTestDepends: [
|
||||||
"QbsProjectManager",
|
"QbsProjectManager",
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ QTC_PLUGIN_DEPENDS += \
|
|||||||
projectexplorer \
|
projectexplorer \
|
||||||
cpptools \
|
cpptools \
|
||||||
qmljstools \
|
qmljstools \
|
||||||
debugger
|
debugger \
|
||||||
|
texteditor
|
||||||
|
|
||||||
QTC_LIB_DEPENDS += \
|
QTC_LIB_DEPENDS += \
|
||||||
cplusplus \
|
cplusplus \
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace Constants {
|
|||||||
const char ACTION_SCAN_ID[] = "AutoTest.ScanAction";
|
const char ACTION_SCAN_ID[] = "AutoTest.ScanAction";
|
||||||
const char ACTION_RUN_ALL_ID[] = "AutoTest.RunAll";
|
const char ACTION_RUN_ALL_ID[] = "AutoTest.RunAll";
|
||||||
const char ACTION_RUN_SELECTED_ID[] = "AutoTest.RunSelected";
|
const char ACTION_RUN_SELECTED_ID[] = "AutoTest.RunSelected";
|
||||||
|
const char ACTION_RUN_UCURSOR[] = "AutoTest.RunUnderCursor";
|
||||||
|
const char ACTION_RUN_DBG_UCURSOR[] = "AutoTest.RunDebugUnderCursor";
|
||||||
const char MENU_ID[] = "AutoTest.Menu";
|
const char MENU_ID[] = "AutoTest.Menu";
|
||||||
const char AUTOTEST_ID[] = "AutoTest.ATP";
|
const char AUTOTEST_ID[] = "AutoTest.ATP";
|
||||||
const char AUTOTEST_CONTEXT[] = "Auto Tests";
|
const char AUTOTEST_CONTEXT[] = "Auto Tests";
|
||||||
@@ -41,7 +43,6 @@ const char TASK_PARSE[] = "AutoTest.Task.Parse";
|
|||||||
const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests";
|
const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests";
|
||||||
const char AUTOTEST_SETTINGS_TR[] = QT_TRANSLATE_NOOP("AutoTest", "Testing");
|
const char AUTOTEST_SETTINGS_TR[] = QT_TRANSLATE_NOOP("AutoTest", "Testing");
|
||||||
const char FRAMEWORK_PREFIX[] = "AutoTest.Framework.";
|
const char FRAMEWORK_PREFIX[] = "AutoTest.Framework.";
|
||||||
|
|
||||||
const char SETTINGSPAGE_PREFIX[] = "A.AutoTest.";
|
const char SETTINGSPAGE_PREFIX[] = "A.AutoTest.";
|
||||||
const char SETTINGSGROUP[] = "Autotest";
|
const char SETTINGSGROUP[] = "Autotest";
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
|
|||||||
@@ -47,16 +47,22 @@
|
|||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <coreplugin/actionmanager/command.h>
|
#include <coreplugin/actionmanager/command.h>
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
|
#include <coreplugin/messagemanager.h>
|
||||||
|
#include <cppeditor/cppeditorconstants.h>
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
#include <projectexplorer/buildmanager.h>
|
#include <projectexplorer/buildmanager.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/projectexplorericons.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
|
#include <utils/textutils.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QTextCursor>
|
||||||
#include <QtPlugin>
|
#include <QtPlugin>
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
@@ -164,6 +170,29 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri
|
|||||||
|
|
||||||
void AutotestPlugin::extensionsInitialized()
|
void AutotestPlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
|
ActionContainer *contextMenu = ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT);
|
||||||
|
QTC_ASSERT(contextMenu, return);
|
||||||
|
|
||||||
|
QAction *action = new QAction(tr("&Run Test Under Cursor"), this);
|
||||||
|
action->setEnabled(false);
|
||||||
|
action->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR.icon());
|
||||||
|
|
||||||
|
Command *command = ActionManager::registerAction(action, Constants::ACTION_RUN_UCURSOR);
|
||||||
|
connect(action, &QAction::triggered, std::bind(&AutotestPlugin::onRunUnderCursorTriggered, this,
|
||||||
|
TestRunMode::Run));
|
||||||
|
contextMenu->addSeparator();
|
||||||
|
contextMenu->addAction(command);
|
||||||
|
|
||||||
|
action = new QAction(tr("&Debug Test Under Cursor"), this);;
|
||||||
|
action->setEnabled(false);
|
||||||
|
action->setIcon(ProjectExplorer::Icons::DEBUG_START_SMALL.icon());
|
||||||
|
|
||||||
|
|
||||||
|
command = ActionManager::registerAction(action, Constants::ACTION_RUN_DBG_UCURSOR);
|
||||||
|
connect(action, &QAction::triggered, std::bind(&AutotestPlugin::onRunUnderCursorTriggered, this,
|
||||||
|
TestRunMode::Debug));
|
||||||
|
contextMenu->addAction(command);
|
||||||
|
contextMenu->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown()
|
ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown()
|
||||||
@@ -188,6 +217,35 @@ void AutotestPlugin::onRunSelectedTriggered()
|
|||||||
runner->prepareToRunTests(TestRunMode::Run);
|
runner->prepareToRunTests(TestRunMode::Run);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutotestPlugin::onRunUnderCursorTriggered(TestRunMode mode)
|
||||||
|
{
|
||||||
|
QTextCursor cursor = Utils::Text::wordStartCursor(
|
||||||
|
TextEditor::BaseTextEditor::currentTextEditor()->editorWidget()->textCursor());
|
||||||
|
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||||
|
const QString text = cursor.selectedText();
|
||||||
|
if (text.isEmpty())
|
||||||
|
return; // Do not trigger when no name under cursor
|
||||||
|
|
||||||
|
const QList<TestTreeItem *> testsItems = TestTreeModel::instance()->testItemsByName(text);
|
||||||
|
if (testsItems.isEmpty())
|
||||||
|
return; // Wrong location triggered
|
||||||
|
|
||||||
|
QList<TestConfiguration *> testsToRun;
|
||||||
|
for (const TestTreeItem * item : testsItems){
|
||||||
|
if (TestConfiguration *cfg = item->asConfiguration(mode))
|
||||||
|
testsToRun << cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testsToRun.isEmpty()) {
|
||||||
|
MessageManager::write(tr("Selected test was not found (%1).").arg(text), MessageManager::Flash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto runner = TestRunner::instance();
|
||||||
|
runner->setSelectedTests(testsToRun);
|
||||||
|
runner->prepareToRunTests(mode);
|
||||||
|
}
|
||||||
|
|
||||||
void AutotestPlugin::updateMenuItemsEnabledState()
|
void AutotestPlugin::updateMenuItemsEnabledState()
|
||||||
{
|
{
|
||||||
const bool canScan = !TestRunner::instance()->isTestRunning()
|
const bool canScan = !TestRunner::instance()->isTestRunning()
|
||||||
@@ -200,6 +258,13 @@ void AutotestPlugin::updateMenuItemsEnabledState()
|
|||||||
ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(canRun);
|
ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(canRun);
|
||||||
ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()->setEnabled(canRun);
|
ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()->setEnabled(canRun);
|
||||||
ActionManager::command(Constants::ACTION_SCAN_ID)->action()->setEnabled(canScan);
|
ActionManager::command(Constants::ACTION_SCAN_ID)->action()->setEnabled(canScan);
|
||||||
|
|
||||||
|
ActionContainer *contextMenu = ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT);
|
||||||
|
if (!contextMenu)
|
||||||
|
return; // When no context menu, actions do not exists
|
||||||
|
|
||||||
|
ActionManager::command(Constants::ACTION_RUN_UCURSOR)->action()->setEnabled(canRun);
|
||||||
|
ActionManager::command(Constants::ACTION_RUN_DBG_UCURSOR)->action()->setEnabled(canRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QObject *> AutotestPlugin::createTestObjects() const
|
QList<QObject *> AutotestPlugin::createTestObjects() const
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class TestNavigationWidgetFactory;
|
|||||||
class TestResultsPane;
|
class TestResultsPane;
|
||||||
struct TestSettings;
|
struct TestSettings;
|
||||||
class TestSettingsPage;
|
class TestSettingsPage;
|
||||||
|
enum class TestRunMode;
|
||||||
|
|
||||||
class AutotestPlugin : public ExtensionSystem::IPlugin
|
class AutotestPlugin : public ExtensionSystem::IPlugin
|
||||||
{
|
{
|
||||||
@@ -59,6 +60,7 @@ private:
|
|||||||
void initializeMenuEntries();
|
void initializeMenuEntries();
|
||||||
void onRunAllTriggered();
|
void onRunAllTriggered();
|
||||||
void onRunSelectedTriggered();
|
void onRunSelectedTriggered();
|
||||||
|
void onRunUnderCursorTriggered(TestRunMode mode);
|
||||||
QList<QObject *> createTestObjects() const override;
|
QList<QObject *> createTestObjects() const override;
|
||||||
const QSharedPointer<TestSettings> m_settings;
|
const QSharedPointer<TestSettings> m_settings;
|
||||||
TestFrameworkManager *m_frameworkManager = nullptr;
|
TestFrameworkManager *m_frameworkManager = nullptr;
|
||||||
|
|||||||
@@ -110,19 +110,7 @@ void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
|
|||||||
|
|
||||||
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
|
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
|
||||||
{
|
{
|
||||||
TestConfiguration *configuration;
|
TestConfiguration *configuration = item->asConfiguration(mode);
|
||||||
switch (mode) {
|
|
||||||
case TestRunMode::Run:
|
|
||||||
case TestRunMode::RunWithoutDeploy:
|
|
||||||
configuration = item->testConfiguration();
|
|
||||||
break;
|
|
||||||
case TestRunMode::Debug:
|
|
||||||
case TestRunMode::DebugWithoutDeploy:
|
|
||||||
configuration = item->debugConfiguration();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
configuration = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
setSelectedTests({configuration});
|
setSelectedTests({configuration});
|
||||||
|
|||||||
@@ -236,6 +236,20 @@ TestTreeItem *TestTreeItem::findChildByNameAndFile(const QString &name, const QS
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestConfiguration *TestTreeItem::asConfiguration(TestRunMode mode) const
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case TestRunMode::Run:
|
||||||
|
case TestRunMode::RunWithoutDeploy:
|
||||||
|
return testConfiguration();
|
||||||
|
case TestRunMode::Debug:
|
||||||
|
case TestRunMode::DebugWithoutDeploy:
|
||||||
|
return debugConfiguration();
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<TestConfiguration *> TestTreeItem::getAllTestConfigurations() const
|
QList<TestConfiguration *> TestTreeItem::getAllTestConfigurations() const
|
||||||
{
|
{
|
||||||
return QList<TestConfiguration *>();
|
return QList<TestConfiguration *>();
|
||||||
|
|||||||
@@ -48,10 +48,11 @@ namespace Internal {
|
|||||||
|
|
||||||
class TestParseResult;
|
class TestParseResult;
|
||||||
class TestConfiguration;
|
class TestConfiguration;
|
||||||
|
enum class TestRunMode;
|
||||||
class TestTreeItem : public Utils::TreeItem
|
class TestTreeItem : public Utils::TreeItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
Root,
|
Root,
|
||||||
@@ -108,6 +109,7 @@ public:
|
|||||||
virtual bool canProvideDebugConfiguration() const { return false; }
|
virtual bool canProvideDebugConfiguration() const { return false; }
|
||||||
virtual TestConfiguration *testConfiguration() const { return 0; }
|
virtual TestConfiguration *testConfiguration() const { return 0; }
|
||||||
virtual TestConfiguration *debugConfiguration() const { return 0; }
|
virtual TestConfiguration *debugConfiguration() const { return 0; }
|
||||||
|
TestConfiguration *asConfiguration(TestRunMode mode) const;
|
||||||
virtual QList<TestConfiguration *> getAllTestConfigurations() const;
|
virtual QList<TestConfiguration *> getAllTestConfigurations() const;
|
||||||
virtual QList<TestConfiguration *> getSelectedTestConfigurations() const;
|
virtual QList<TestConfiguration *> getSelectedTestConfigurations() const;
|
||||||
virtual bool lessThan(const TestTreeItem *other, SortMode mode) const;
|
virtual bool lessThan(const TestTreeItem *other, SortMode mode) const;
|
||||||
|
|||||||
@@ -158,6 +158,45 @@ QList<TestConfiguration *> TestTreeModel::getSelectedTests() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<TestTreeItem *> TestTreeModel::testItemsByName(TestTreeItem *root, const QString &testName)
|
||||||
|
{
|
||||||
|
QList<TestTreeItem *> result;
|
||||||
|
|
||||||
|
for (int row = 0, count = root->childCount(); row < count; ++row){
|
||||||
|
TestTreeItem *node = root->childItem(row);
|
||||||
|
|
||||||
|
if (node->type() == TestTreeItem::TestCase) {
|
||||||
|
if (node->name() == testName) {
|
||||||
|
result << node;
|
||||||
|
continue; // prioritize Tests over TestCases
|
||||||
|
}
|
||||||
|
|
||||||
|
TestTreeItem *testCase = node->findChildBy([testName](const TestTreeItem *it) {
|
||||||
|
QTC_ASSERT(it, return false);
|
||||||
|
return it->type() == TestTreeItem::TestFunctionOrSet && it->name() == testName;
|
||||||
|
}); // collect only actual tests, not special functions like init, cleanup etc,
|
||||||
|
|
||||||
|
if (!testCase)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result << testCase;
|
||||||
|
} else {
|
||||||
|
result << testItemsByName(node, testName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<TestTreeItem *> TestTreeModel::testItemsByName(const QString &testName)
|
||||||
|
{
|
||||||
|
QList<TestTreeItem *> result;
|
||||||
|
for (Utils::TreeItem *frameworkRoot : *rootItem())
|
||||||
|
result << testItemsByName(static_cast<TestTreeItem *>(frameworkRoot), testName);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void TestTreeModel::syncTestFrameworks()
|
void TestTreeModel::syncTestFrameworks()
|
||||||
{
|
{
|
||||||
// remove all currently registered
|
// remove all currently registered
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
bool hasTests() const;
|
bool hasTests() const;
|
||||||
QList<TestConfiguration *> getAllTestCases() const;
|
QList<TestConfiguration *> getAllTestCases() const;
|
||||||
QList<TestConfiguration *> getSelectedTests() const;
|
QList<TestConfiguration *> getSelectedTests() const;
|
||||||
|
QList<TestTreeItem *> testItemsByName(const QString &testName);
|
||||||
void syncTestFrameworks();
|
void syncTestFrameworks();
|
||||||
void rebuild(const QList<Core::Id> &frameworkIds);
|
void rebuild(const QList<Core::Id> &frameworkIds);
|
||||||
|
|
||||||
@@ -91,6 +91,7 @@ private:
|
|||||||
void revalidateCheckState(TestTreeItem *item);
|
void revalidateCheckState(TestTreeItem *item);
|
||||||
explicit TestTreeModel(QObject *parent = 0);
|
explicit TestTreeModel(QObject *parent = 0);
|
||||||
void setupParsingConnections();
|
void setupParsingConnections();
|
||||||
|
QList<TestTreeItem *> testItemsByName(TestTreeItem *root, const QString &testName);
|
||||||
|
|
||||||
TestCodeParser *m_parser;
|
TestCodeParser *m_parser;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user