AutoTest: Fix running test cases with grouping

When gathering information for running tests we need to
take the grouping into account if enabled.
This patch amends 4eabcda3a1.

Task-number: QTCREATORBUG-17979
Change-Id: I27c17a5de8596c95f3b207530560d2a7c2cb5e99
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2018-01-17 09:51:45 +01:00
parent 78b9d642e3
commit a5b82fe827
4 changed files with 185 additions and 173 deletions

View File

@@ -31,6 +31,7 @@
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/session.h>
#include <utils/algorithm.h>
#include <utils/asconst.h>
#include <utils/qtcassert.h>
namespace Autotest {
@@ -122,35 +123,67 @@ TestConfiguration *GTestTreeItem::debugConfiguration() const
return config;
}
QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
struct TestCases
{
QStringList filters;
int testSetCount = 0;
QSet<QString> internalTargets;
};
static void collectTestInfo(const GTestTreeItem *item,
QHash<QString, TestCases> &testCasesForProFile,
bool ignoreCheckState)
{
QTC_ASSERT(item, return);
if (item->type() == TestTreeItem::GroupNode) {
for (int row = 0, count = item->childCount(); row < count; ++row) {
auto child = static_cast<const GTestTreeItem *>(item->childItem(row));
collectTestInfo(child, testCasesForProFile, ignoreCheckState);
}
return;
}
const int childCount = item->childCount();
QTC_ASSERT(childCount != 0, return);
QTC_ASSERT(item->type() == TestTreeItem::TestCase, return);
if (ignoreCheckState || item->checked() == Qt::Checked) {
const QString &projectFile = item->childItem(0)->proFile();
testCasesForProFile[projectFile].filters.append(
gtestFilter(item->state()).arg(item->name()).arg('*'));
testCasesForProFile[projectFile].testSetCount += childCount - 1;
testCasesForProFile[projectFile].internalTargets.unite(item->internalTargets());
} else if (item->checked() == Qt::PartiallyChecked) {
for (int childRow = 0; childRow < childCount; ++childRow) {
const TestTreeItem *child = item->childItem(childRow);
QTC_ASSERT(child->type() == TestTreeItem::TestFunctionOrSet, continue);
if (child->checked() == Qt::Checked) {
testCasesForProFile[child->proFile()].filters.append(
gtestFilter(item->state()).arg(item->name()).arg(child->name()));
testCasesForProFile[child->proFile()].internalTargets.unite(
child->internalTargets());
}
}
}
}
QList<TestConfiguration *> GTestTreeItem::getTestConfigurations(bool ignoreCheckState) const
{
QList<TestConfiguration *> result;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project || type() != Root)
return result;
QHash<QString, int> proFilesWithTestSets;
QHash<QString, QSet<QString> > proFilesWithInternalTargets;
QHash<QString, TestCases> testCasesForProFile;
for (int row = 0, count = childCount(); row < count; ++row) {
const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row));
const int grandChildCount = child->childCount();
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
const TestTreeItem *grandChild = child->childItem(grandChildRow);
const QString &key = grandChild->proFile();
proFilesWithTestSets.insert(key, proFilesWithTestSets[key] + 1);
proFilesWithInternalTargets[key].unite(grandChild->internalTargets());
}
auto child = static_cast<const GTestTreeItem *>(childItem(row));
collectTestInfo(child, testCasesForProFile, ignoreCheckState);
}
QHash<QString, int>::ConstIterator it = proFilesWithTestSets.begin();
QHash<QString, int>::ConstIterator end = proFilesWithTestSets.end();
for ( ; it != end; ++it) {
const QSet<QString> &internalTargets = proFilesWithInternalTargets[it.key()];
for (const QString &target : internalTargets) {
for (auto it = testCasesForProFile.begin(), end = testCasesForProFile.end(); it != end; ++it) {
for (const QString &target : Utils::asConst(it.value().internalTargets)) {
GTestConfiguration *tc = new GTestConfiguration;
tc->setTestCaseCount(it.value());
if (!ignoreCheckState)
tc->setTestCases(it.value().filters);
tc->setTestCaseCount(tc->testCaseCount() + it.value().testSetCount);
tc->setProjectFile(it.key());
tc->setProject(project);
tc->setInternalTarget(target);
@@ -161,69 +194,14 @@ QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
return result;
}
struct TestCases
QList<TestConfiguration *> GTestTreeItem::getAllTestConfigurations() const
{
QStringList filters;
int additionalTestCaseCount = 0;
};
return getTestConfigurations(true);
}
QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const
{
QList<TestConfiguration *> result;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project || type() != Root)
return result;
QHash<QString, TestCases> proFilesWithCheckedTestSets;
QHash<QString, QSet<QString> > proFilesWithInternalTargets;
for (int row = 0, count = childCount(); row < count; ++row) {
const GTestTreeItem *child = static_cast<const GTestTreeItem *>(childItem(row));
const int grandChildCount = child->childCount();
QTC_ASSERT(grandChildCount != 0, continue);
switch (child->checked()) {
case Qt::Unchecked:
continue;
case Qt::Checked: {
auto &testCases = proFilesWithCheckedTestSets[child->childItem(0)->proFile()];
testCases.filters.append(gtestFilter(child->state()).arg(child->name()).arg('*'));
testCases.additionalTestCaseCount += grandChildCount - 1;
proFilesWithInternalTargets[child->childItem(0)->proFile()].unite(
child->internalTargets());
break;
}
case Qt::PartiallyChecked: {
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
const TestTreeItem *grandChild = child->childItem(grandChildRow);
if (grandChild->checked() == Qt::Checked) {
proFilesWithCheckedTestSets[grandChild->proFile()].filters.append(
gtestFilter(child->state()).arg(child->name()).arg(grandChild->name()));
proFilesWithInternalTargets[grandChild->proFile()].unite(
grandChild->internalTargets());
}
}
break;
}
}
}
QHash<QString, TestCases>::ConstIterator it = proFilesWithCheckedTestSets.begin();
QHash<QString, TestCases>::ConstIterator end = proFilesWithCheckedTestSets.end();
for ( ; it != end; ++it) {
const QSet<QString> &internalTargets = proFilesWithInternalTargets[it.key()];
for (const QString &target : internalTargets) {
GTestConfiguration *tc = new GTestConfiguration;
tc->setTestCases(it.value().filters);
tc->setTestCaseCount(tc->testCaseCount() + it.value().additionalTestCaseCount);
tc->setProjectFile(it.key());
tc->setProject(project);
tc->setInternalTarget(target);
result << tc;
}
}
return result;
return getTestConfigurations(false);
}
TestTreeItem *GTestTreeItem::find(const TestParseResult *result)

View File

@@ -71,6 +71,7 @@ public:
private:
bool modifyTestSetContent(const GTestParseResult *result);
QList<TestConfiguration *> getTestConfigurations(bool ignoreCheckState) const;
GTestTreeItem::TestStates m_state;
};

View File

@@ -139,6 +139,53 @@ TestConfiguration *QtTestTreeItem::testConfiguration() const
return config;
}
static void fillTestConfigurationsFromCheckState(const TestTreeItem *item,
QList<TestConfiguration *> &testConfigurations)
{
QTC_ASSERT(item, return);
if (item->type() == TestTreeItem::GroupNode) {
for (int row = 0, count = item->childCount(); row < count; ++row)
fillTestConfigurationsFromCheckState(item->childItem(row), testConfigurations);
return;
}
QTC_ASSERT(item->type() == TestTreeItem::TestCase, return);
QtTestConfiguration *testConfig = nullptr;
switch (item->checked()) {
case Qt::Unchecked:
return;
case Qt::Checked:
testConfig = static_cast<QtTestConfiguration *>(item->testConfiguration());
QTC_ASSERT(testConfig, return);
testConfigurations << testConfig;
return;
case Qt::PartiallyChecked:
default:
int grandChildCount = item->childCount();
QStringList testCases;
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
const TestTreeItem *grandChild = item->childItem(grandChildRow);
if (grandChild->checked() == Qt::Checked) {
testCases << grandChild->name();
} else if (grandChild->checked() == Qt::PartiallyChecked) {
const int dtCount = grandChild->childCount();
const QString funcName = grandChild->name();
for (int dtRow = 0; dtRow < dtCount; ++dtRow) {
const TestTreeItem *dataTag = grandChild->childItem(dtRow);
if (dataTag->checked() == Qt::Checked)
testCases << funcName + ':' + dataTag->name();
}
}
}
testConfig = new QtTestConfiguration();
testConfig->setTestCases(testCases);
testConfig->setProjectFile(item->proFile());
testConfig->setProject(ProjectExplorer::SessionManager::startupProject());
testConfig->setInternalTargets(item->internalTargets());
testConfigurations << testConfig;
}
}
TestConfiguration *QtTestTreeItem::debugConfiguration() const
{
QtTestConfiguration *config = static_cast<QtTestConfiguration *>(testConfiguration());
@@ -157,13 +204,19 @@ QList<TestConfiguration *> QtTestTreeItem::getAllTestConfigurations() const
for (int row = 0, count = childCount(); row < count; ++row) {
const TestTreeItem *child = childItem(row);
TestConfiguration *tc = new QtTestConfiguration();
tc->setTestCaseCount(child->childCount());
tc->setProjectFile(child->proFile());
tc->setProject(project);
tc->setInternalTargets(child->internalTargets());
TestConfiguration *tc = nullptr;
if (child->type() == TestCase) {
tc = child->testConfiguration();
QTC_ASSERT(tc, continue);
result << tc;
} else if (child->type() == GroupNode) {
const int groupChildCount = child->childCount();
for (int groupChildRow = 0; groupChildRow < groupChildCount; ++groupChildRow) {
tc = child->childItem(groupChildRow)->testConfiguration();
QTC_ASSERT(tc, continue);
result << tc;
}
}
}
return result;
}
@@ -175,49 +228,8 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const
if (!project || type() != Root)
return result;
QtTestConfiguration *testConfiguration = nullptr;
for (int row = 0, count = childCount(); row < count; ++row) {
const TestTreeItem *child = childItem(row);
switch (child->checked()) {
case Qt::Unchecked:
continue;
case Qt::Checked:
testConfiguration = new QtTestConfiguration();
testConfiguration->setTestCaseCount(child->childCount());
testConfiguration->setProjectFile(child->proFile());
testConfiguration->setProject(project);
testConfiguration->setInternalTargets(child->internalTargets());
result << testConfiguration;
continue;
case Qt::PartiallyChecked:
default:
int grandChildCount = child->childCount();
QStringList testCases;
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
const TestTreeItem *grandChild = child->childItem(grandChildRow);
if (grandChild->checked() == Qt::Checked) {
testCases << grandChild->name();
} else if (grandChild->checked() == Qt::PartiallyChecked) {
const int dtCount = grandChild->childCount();
const QString funcName = grandChild->name();
for (int dtRow = 0; dtRow < dtCount; ++dtRow) {
const TestTreeItem *dataTag = grandChild->childItem(dtRow);
if (dataTag->checked() == Qt::Checked)
testCases << funcName + ':' + dataTag->name();
}
}
}
testConfiguration = new QtTestConfiguration();
testConfiguration->setTestCases(testCases);
testConfiguration->setProjectFile(child->proFile());
testConfiguration->setProject(project);
testConfiguration->setInternalTargets(child->internalTargets());
result << testConfiguration;
}
}
for (int row = 0, count = childCount(); row < count; ++row)
fillTestConfigurationsFromCheckState(childItem(row), result);
return result;
}

View File

@@ -153,6 +153,43 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const
return config;
}
static void testConfigurationFromCheckState(const TestTreeItem *item,
QHash<QString, QuickTestConfiguration *> &foundProFiles)
{
QTC_ASSERT(item, return);
if (item->type() == TestTreeItem::GroupNode) {
for (int row = 0, count = item->childCount(); row < count; ++row)
testConfigurationFromCheckState(item->childItem(row), foundProFiles);
return;
}
QTC_ASSERT(item->type() == TestTreeItem::TestCase, return);
QuickTestConfiguration *tc = nullptr;
if (item->checked() == Qt::Unchecked)
return;
QStringList testFunctions;
const int childCount = item->childCount();
for (int childRow = 0; childRow < childCount; ++childRow) {
const TestTreeItem *child = item->childItem(childRow);
if (child->checked() != Qt::Checked || child->type() != TestTreeItem::TestFunctionOrSet)
continue;
testFunctions << item->name() + "::" + child->name();
}
if (foundProFiles.contains(item->proFile())) {
tc = foundProFiles[item->proFile()];
QStringList oldFunctions(tc->testCases());
oldFunctions << testFunctions;
tc->setTestCases(oldFunctions);
} else {
tc = new QuickTestConfiguration;
tc->setTestCases(testFunctions);
tc->setProjectFile(item->proFile());
tc->setProject(ProjectExplorer::SessionManager::startupProject());
tc->setInternalTargets(item->internalTargets());
foundProFiles.insert(item->proFile(), tc);
}
}
TestConfiguration *QuickTestTreeItem::debugConfiguration() const
{
QuickTestConfiguration *config = static_cast<QuickTestConfiguration *>(testConfiguration());
@@ -161,6 +198,17 @@ TestConfiguration *QuickTestTreeItem::debugConfiguration() const
return config;
}
struct Tests {
int testCount = 0;
QSet<QString> internalTargets;
};
static void addTestsForItem(Tests &tests, const TestTreeItem *item)
{
tests.testCount += item->childCount();
tests.internalTargets = item->internalTargets();
}
QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
{
QList<TestConfiguration *> result;
@@ -169,8 +217,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
if (!project || type() != Root)
return result;
QHash<QString, int> foundProFiles;
QHash<QString, QSet<QString> > proFilesWithTargets;
QHash<QString, Tests> testsForProfile;
for (int row = 0, count = childCount(); row < count; ++row) {
const TestTreeItem *child = childItem(row);
// unnamed Quick Tests must be handled separately
@@ -178,25 +225,29 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) {
const TestTreeItem *grandChild = child->childItem(childRow);
const QString &proFile = grandChild->proFile();
foundProFiles.insert(proFile, foundProFiles[proFile] + 1);
proFilesWithTargets.insert(proFile, grandChild->internalTargets());
++(testsForProfile[proFile].testCount);
testsForProfile[proFile].internalTargets = grandChild->internalTargets();
}
continue;
}
// named Quick Test
const QString &proFile = child->proFile();
foundProFiles.insert(proFile, foundProFiles[proFile] + child->childCount());
proFilesWithTargets.insert(proFile, child->internalTargets());
if (child->type() == TestCase) {
addTestsForItem(testsForProfile[child->proFile()], child);
} else if (child->type() == GroupNode) {
const int groupCount = child->childCount();
for (int groupRow = 0; groupRow < groupCount; ++groupRow) {
const TestTreeItem *grandChild = child->childItem(groupRow);
addTestsForItem(testsForProfile[grandChild->proFile()], grandChild);
}
}
}
// create TestConfiguration for each project file
QHash<QString, int>::ConstIterator it = foundProFiles.begin();
QHash<QString, int>::ConstIterator end = foundProFiles.end();
for ( ; it != end; ++it) {
for (auto it = testsForProfile.begin(), end = testsForProfile.end(); it != end; ++it) {
QuickTestConfiguration *tc = new QuickTestConfiguration;
tc->setTestCaseCount(it.value());
tc->setTestCaseCount(it.value().testCount);
tc->setProjectFile(it.key());
tc->setProject(project);
tc->setInternalTargets(proFilesWithTargets[it.key()]);
tc->setInternalTargets(it.value().internalTargets);
result << tc;
}
return result;
@@ -209,7 +260,6 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
if (!project || type() != Root)
return result;
QuickTestConfiguration *tc = nullptr;
QHash<QString, QuickTestConfiguration *> foundProFiles;
for (int row = 0, count = childCount(); row < count; ++row) {
@@ -219,39 +269,10 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
continue;
// named Quick Tests
switch (child->checked()) {
case Qt::Unchecked:
continue;
case Qt::Checked:
case Qt::PartiallyChecked:
default:
QStringList testFunctions;
int grandChildCount = child->childCount();
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
const TestTreeItem *grandChild = child->childItem(grandChildRow);
if (grandChild->checked() != Qt::Checked || grandChild->type() != TestFunctionOrSet)
continue;
testFunctions << child->name() + "::" + grandChild->name();
testConfigurationFromCheckState(child, foundProFiles);
}
if (foundProFiles.contains(child->proFile())) {
tc = foundProFiles[child->proFile()];
QStringList oldFunctions(tc->testCases());
oldFunctions << testFunctions;
tc->setTestCases(oldFunctions);
} else {
tc = new QuickTestConfiguration;
tc->setTestCases(testFunctions);
tc->setProjectFile(child->proFile());
tc->setProject(project);
tc->setInternalTargets(child->internalTargets());
foundProFiles.insert(child->proFile(), tc);
}
break;
}
}
QHash<QString, QuickTestConfiguration *>::ConstIterator it = foundProFiles.begin();
QHash<QString, QuickTestConfiguration *>::ConstIterator end = foundProFiles.end();
for ( ; it != end; ++it) {
for (auto it = foundProFiles.begin(), end = foundProFiles.end(); it != end; ++it) {
QuickTestConfiguration *config = it.value();
if (!config->unnamedOnly())
result << config;