diff --git a/src/libs/extensionsystem/optionsparser.cpp b/src/libs/extensionsystem/optionsparser.cpp
index 8aa26f3ec576b22c2a3b5fca46860425bf4700c4..e0fb2921c8c77825330237f218261a3ff4913160 100644
--- a/src/libs/extensionsystem/optionsparser.cpp
+++ b/src/libs/extensionsystem/optionsparser.cpp
@@ -107,8 +107,8 @@ bool OptionsParser::checkForTestOption()
     if (nextToken(RequiredToken)) {
         if (m_currentArg == QLatin1String("all")) {
             foreach (PluginSpec *spec, m_pmPrivate->pluginSpecs) {
-                if (spec && !m_pmPrivate->testSpecs.contains(spec))
-                    m_pmPrivate->testSpecs.append(spec);
+                if (spec && !m_pmPrivate->containsTestSpec(spec))
+                    m_pmPrivate->testSpecs.append(PluginManagerPrivate::TestSpec(spec));
             }
         } else {
             PluginSpec *spec = m_pmPrivate->pluginByName(m_currentArg);
@@ -117,8 +117,20 @@ bool OptionsParser::checkForTestOption()
                     *m_errorString = QCoreApplication::translate("PluginManager",
                                                                  "The plugin '%1' does not exist.").arg(m_currentArg);
                 m_hasError = true;
-            } else if (!m_pmPrivate->testSpecs.contains(spec)) {
-                m_pmPrivate->testSpecs.append(spec);
+            } else if (!m_pmPrivate->containsTestSpec(spec)) {
+                    // Collect optional test functions. Everything following the plugin
+                    // name until the next option is interpreted as a test function. E.g.
+                    // in './qtcreator -test Git myFile' the argument 'myFile' will be
+                    // be interpreted as an function name and not a file to open.
+                    const QStringList::const_iterator current(m_it);
+                    QStringList testFunctions;
+                    while (nextToken() && !m_currentArg.startsWith(QLatin1Char('-')))
+                           testFunctions.append(m_currentArg);
+                    // Make sure a following nextToken() call will get the current/next option.
+                    if (current != m_it && m_it != m_end)
+                        --m_it;
+                    m_pmPrivate->testSpecs.append(
+                        PluginManagerPrivate::TestSpec(spec, testFunctions));
             }
         }
     }
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 76a67eb93599b42f55fc5e985d279f34e0786170..4109c533d7cf401ec93cbe3fae3a237798362321 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -616,8 +616,11 @@ void PluginManager::formatOptions(QTextStream &str, int optionIndentation, int d
                  QString(), QLatin1String("Profile plugin loading"),
                  optionIndentation, descriptionIndentation);
 #ifdef WITH_TESTS
-    formatOption(str, QLatin1String(OptionsParser::TEST_OPTION),
-                 QLatin1String("plugin|all"), QLatin1String("Run plugin's tests"),
+    formatOption(str, QString::fromLatin1(OptionsParser::TEST_OPTION)
+                 + QLatin1String(" <plugin> [testfunction[:testdata]]..."), QString(),
+                 QLatin1String("Run plugin's tests"), optionIndentation, descriptionIndentation);
+    formatOption(str, QString::fromLatin1(OptionsParser::TEST_OPTION) + QLatin1String(" all"),
+                 QString(), QLatin1String("Run tests from all plugins"),
                  optionIndentation, descriptionIndentation);
 #endif
 }
@@ -662,13 +665,15 @@ void PluginManager::formatPluginVersions(QTextStream &str)
 void PluginManager::startTests()
 {
 #ifdef WITH_TESTS
-    foreach (PluginSpec *pluginSpec, d->testSpecs) {
+    foreach (const PluginManagerPrivate::TestSpec &testSpec, d->testSpecs) {
+        const PluginSpec * const pluginSpec = testSpec.pluginSpec;
         if (!pluginSpec->plugin())
             continue;
+
+        // Collect all test functions/methods of the plugin.
+        QStringList allTestFunctions;
         const QMetaObject *mo = pluginSpec->plugin()->metaObject();
-        QStringList methods;
-        methods.append(QLatin1String("arg0"));
-        // We only want slots starting with "test"
+
         for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
 #if QT_VERSION >= 0x050000
             const QByteArray signature = mo->method(i).methodSignature();
@@ -677,13 +682,49 @@ void PluginManager::startTests()
 #endif
             if (signature.startsWith("test") && !signature.endsWith("_data()")) {
                 const QString method = QString::fromLatin1(signature);
-                methods.append(method.left(method.size()-2));
+                allTestFunctions.append(method.left(method.size()-2));
+            }
+        }
+
+        QStringList testFunctionsToExecute;
+
+        // User did not specify any test functions, so add every test function.
+        if (testSpec.testFunctions.isEmpty()) {
+            testFunctionsToExecute = allTestFunctions;
+
+        // User specified test functions. Add them if they are valid.
+        } else {
+            foreach (const QString &userTestFunction, testSpec.testFunctions) {
+                // There might be a test data suffix like in "testfunction:testdata1".
+                QString testFunctionName = userTestFunction;
+                const int index = testFunctionName.indexOf(QLatin1Char(':'));
+                if (index != -1)
+                    testFunctionName = testFunctionName.left(index);
+
+                if (allTestFunctions.contains(testFunctionName)) {
+                    // If the specified test data is invalid, the QTest framework will
+                    // print a reasonable error message for us.
+                    testFunctionsToExecute.append(userTestFunction);
+                } else {
+                    QTextStream out(stdout);
+                    out << "Unknown test function \"" << testFunctionName
+                        << "\" for plugin \"" << pluginSpec->name() << "\"." << endl
+                        << "  Available test functions for plugin \"" << pluginSpec->name()
+                        << "\" are:" << endl;
+                    foreach (const QString &testFunction, allTestFunctions)
+                        out << "    " << testFunction << endl;
+                }
             }
         }
+
+        // QTest::qExec() expects basically QCoreApplication::arguments(),
+        // so prepend a fake argument for the application name.
+        testFunctionsToExecute.prepend(QLatin1String("arg0"));
+
         // Don't run QTest::qExec with only one argument, that'd run
         // *all* slots as tests.
-        if (methods.size() > 1)
-            QTest::qExec(pluginSpec->plugin(), methods);
+        if (testFunctionsToExecute.size() > 1)
+            QTest::qExec(pluginSpec->plugin(), testFunctionsToExecute);
     }
     if (!d->testSpecs.isEmpty())
         QTimer::singleShot(1, QCoreApplication::instance(), SLOT(quit()));
diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h
index b267fc8eb934dec007ad166839fd66887f563c9b..5654e5718d9f6f8262224ee288e13273b670cbb6 100644
--- a/src/libs/extensionsystem/pluginmanager_p.h
+++ b/src/libs/extensionsystem/pluginmanager_p.h
@@ -79,9 +79,26 @@ public:
     void writeSettings();
     void disablePluginIndirectly(PluginSpec *spec);
 
+    class TestSpec {
+    public:
+        TestSpec(PluginSpec *pluginSpec, const QStringList &testFunctions = QStringList())
+            : pluginSpec(pluginSpec), testFunctions(testFunctions) {}
+        PluginSpec *pluginSpec;
+        QStringList testFunctions;
+    };
+
+    bool containsTestSpec(PluginSpec *pluginSpec) const
+    {
+        foreach (const TestSpec &testSpec, testSpecs) {
+            if (testSpec.pluginSpec == pluginSpec)
+                return true;
+        }
+        return false;
+    }
+
     QHash<QString, PluginCollection *> pluginCategories;
     QList<PluginSpec *> pluginSpecs;
-    QList<PluginSpec *> testSpecs;
+    QList<TestSpec> testSpecs;
     QStringList pluginPaths;
     QString extension;
     QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ?