AutoTest: Add unit test for parsing boost tests

To execute them you need - beside the former prerequisites -
either have boost installed installed at system level (UNIX)
or you must specify BOOST_INCLUDE_DIR as environment variable
otherwise the respective test will be skipped.

Change-Id: I6bd8472e554132ab05e58b56e3ccbd5e9dffada9
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2019-05-21 13:39:00 +02:00
parent 5c6eb0a2ba
commit b86c05b96a
22 changed files with 306 additions and 9 deletions

View File

@@ -39,6 +39,7 @@
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
#include <QFileInfo>
#include <QSignalSpy> #include <QSignalSpy>
#include <QTest> #include <QTest>
@@ -53,9 +54,7 @@ namespace Internal {
AutoTestUnitTests::AutoTestUnitTests(TestTreeModel *model, QObject *parent) AutoTestUnitTests::AutoTestUnitTests(TestTreeModel *model, QObject *parent)
: QObject(parent), : QObject(parent),
m_model(model), m_model(model)
m_tmpDir(nullptr),
m_isQt4(false)
{ {
} }
@@ -74,6 +73,16 @@ void AutoTestUnitTests::initTestCase()
QSKIP("This test requires that there is a kit with a toolchain."); QSKIP("This test requires that there is a kit with a toolchain.");
m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(":/unit_test"); m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(":/unit_test");
if (!qgetenv("BOOST_INCLUDE_DIR").isEmpty()) {
m_checkBoost = true;
} else {
if (QFileInfo::exists("/usr/include/boost/version.hpp")
|| QFileInfo::exists("/usr/local/include/boost/version.hpp")) {
qDebug() << "Found boost at system level - will run boost parser test.";
m_checkBoost = true;
}
}
} }
void AutoTestUnitTests::cleanupTestCase() void AutoTestUnitTests::cleanupTestCase()
@@ -218,6 +227,7 @@ void AutoTestUnitTests::testCodeParserGTest()
QCOMPARE(m_model->namedQuickTestsCount(), 0); QCOMPARE(m_model->namedQuickTestsCount(), 0);
QCOMPARE(m_model->unnamedQuickTestsCount(), 0); QCOMPARE(m_model->unnamedQuickTestsCount(), 0);
QCOMPARE(m_model->dataTagsCount(), 0); QCOMPARE(m_model->dataTagsCount(), 0);
QCOMPARE(m_model->boostTestNamesCount(), 0);
} }
void AutoTestUnitTests::testCodeParserGTest_data() void AutoTestUnitTests::testCodeParserGTest_data()
@@ -229,5 +239,51 @@ void AutoTestUnitTests::testCodeParserGTest_data()
<< QString(m_tmpDir->path() + "/simple_gt/simple_gt.qbs"); << QString(m_tmpDir->path() + "/simple_gt/simple_gt.qbs");
} }
void AutoTestUnitTests::testCodeParserBoostTest()
{
if (!m_checkBoost)
QSKIP("This test needs boost - set BOOST_INCLUDE_DIR (or have it installed)");
QFETCH(QString, projectFilePath);
CppTools::Tests::ProjectOpenerAndCloser projectManager;
CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
QVERIFY(projectInfo.isValid());
QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished()));
QSignalSpy modelUpdateSpy(m_model, SIGNAL(sweepingDone()));
QVERIFY(parserSpy.wait(20000));
QVERIFY(modelUpdateSpy.wait());
QCOMPARE(m_model->boostTestNamesCount(), 5);
QMultiMap<QString, int> expectedSuitesAndTests;
expectedSuitesAndTests.insert(QStringLiteral("Master Test Suite"), 2); // decorators w/o suite
expectedSuitesAndTests.insert(QStringLiteral("Master Test Suite"), 2); // fixtures
expectedSuitesAndTests.insert(QStringLiteral("Master Test Suite"), 3); // functions
expectedSuitesAndTests.insert(QStringLiteral("Suite1"), 4);
expectedSuitesAndTests.insert(QStringLiteral("SuiteOuter"), 5); // 2 sub suites + 3 tests
QMultiMap<QString, int> foundNamesAndSets = m_model->boostTestSuitesAndTests();
QCOMPARE(expectedSuitesAndTests.size(), foundNamesAndSets.size());
for (const QString &name : expectedSuitesAndTests.keys())
QCOMPARE(expectedSuitesAndTests.values(name), foundNamesAndSets.values(name));
// check also that no Qt related tests have been found
QCOMPARE(m_model->autoTestsCount(), 0);
QCOMPARE(m_model->namedQuickTestsCount(), 0);
QCOMPARE(m_model->unnamedQuickTestsCount(), 0);
QCOMPARE(m_model->dataTagsCount(), 0);
QCOMPARE(m_model->gtestNamesCount(), 0);
}
void AutoTestUnitTests::testCodeParserBoostTest_data()
{
QTest::addColumn<QString>("projectFilePath");
QTest::newRow("simpleBoostTest")
<< QString(m_tmpDir->path() + "/simple_boost/simple_boost.pro");
QTest::newRow("simpleBoostTestQbs")
<< QString(m_tmpDir->path() + "/simple_boost/simple_boost.qbs");
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -51,11 +51,14 @@ private slots:
void testCodeParserSwitchStartup_data(); void testCodeParserSwitchStartup_data();
void testCodeParserGTest(); void testCodeParserGTest();
void testCodeParserGTest_data(); void testCodeParserGTest_data();
void testCodeParserBoostTest();
void testCodeParserBoostTest_data();
private: private:
TestTreeModel *m_model; TestTreeModel *m_model = nullptr;
CppTools::Tests::TemporaryCopiedDir *m_tmpDir; CppTools::Tests::TemporaryCopiedDir *m_tmpDir = nullptr;
bool m_isQt4; bool m_isQt4 = false;
bool m_checkBoost = false;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -72,5 +72,22 @@
<file>unit_test/mixed_atp/tests/auto/quickauto3/quickauto3.qbs</file> <file>unit_test/mixed_atp/tests/auto/quickauto3/quickauto3.qbs</file>
<file>unit_test/mixed_atp/tests/auto/quickauto3/tst_test1.qml</file> <file>unit_test/mixed_atp/tests/auto/quickauto3/tst_test1.qml</file>
<file>unit_test/mixed_atp/tests/auto/quickauto3/tst_test2.qml</file> <file>unit_test/mixed_atp/tests/auto/quickauto3/tst_test2.qml</file>
<file>unit_test/simple_boost/simple_boost.pro</file>
<file>unit_test/simple_boost/simple_boost.qbs</file>
<file>unit_test/simple_boost/src/main.cpp</file>
<file>unit_test/simple_boost/src/src.pro</file>
<file>unit_test/simple_boost/src/src.qbs</file>
<file>unit_test/simple_boost/tests/tests.pro</file>
<file>unit_test/simple_boost/tests/tests.qbs</file>
<file>unit_test/simple_boost/tests/deco/deco.pro</file>
<file>unit_test/simple_boost/tests/deco/deco.qbs</file>
<file>unit_test/simple_boost/tests/deco/enab.h</file>
<file>unit_test/simple_boost/tests/deco/main.cpp</file>
<file>unit_test/simple_boost/tests/fix/fix.cpp</file>
<file>unit_test/simple_boost/tests/fix/fix.pro</file>
<file>unit_test/simple_boost/tests/fix/fix.qbs</file>
<file>unit_test/simple_boost/tests/params/main.cpp</file>
<file>unit_test/simple_boost/tests/params/params.pro</file>
<file>unit_test/simple_boost/tests/params/params.qbs</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -481,24 +481,30 @@ void TestTreeModel::removeTestRootNodes()
#ifdef WITH_TESTS #ifdef WITH_TESTS
// we're inside tests - so use some internal knowledge to make testing easier // we're inside tests - so use some internal knowledge to make testing easier
TestTreeItem *qtRootNode() static TestTreeItem *qtRootNode()
{ {
return TestFrameworkManager::instance()->rootNodeForTestFramework( return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtTest")); Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtTest"));
} }
TestTreeItem *quickRootNode() static TestTreeItem *quickRootNode()
{ {
return TestFrameworkManager::instance()->rootNodeForTestFramework( return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtQuickTest")); Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtQuickTest"));
} }
TestTreeItem *gtestRootNode() static TestTreeItem *gtestRootNode()
{ {
return TestFrameworkManager::instance()->rootNodeForTestFramework( return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("GTest")); Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("GTest"));
} }
static TestTreeItem *boostTestRootNode()
{
return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("Boost"));
}
int TestTreeModel::autoTestsCount() const int TestTreeModel::autoTestsCount() const
{ {
TestTreeItem *rootNode = qtRootNode(); TestTreeItem *rootNode = qtRootNode();
@@ -570,6 +576,25 @@ QMultiMap<QString, int> TestTreeModel::gtestNamesAndSets() const
} }
return result; return result;
} }
int TestTreeModel::boostTestNamesCount() const
{
TestTreeItem *rootNode = boostTestRootNode();
return rootNode ? rootNode->childCount() : 0;
}
QMultiMap<QString, int> TestTreeModel::boostTestSuitesAndTests() const
{
QMultiMap<QString, int> result;
if (TestTreeItem *rootNode = boostTestRootNode()) {
rootNode->forFirstLevelChildren([&result](TestTreeItem *child) {
result.insert(child->name(), child->childCount());
});
}
return result;
}
#endif #endif
/***************************** Sort/Filter Model **********************************/ /***************************** Sort/Filter Model **********************************/

View File

@@ -70,6 +70,8 @@ public:
int dataTagsCount() const; int dataTagsCount() const;
int gtestNamesCount() const; int gtestNamesCount() const;
QMultiMap<QString, int> gtestNamesAndSets() const; QMultiMap<QString, int> gtestNamesAndSets() const;
int boostTestNamesCount() const;
QMultiMap<QString, int> boostTestSuitesAndTests() const;
#endif #endif
void markAllForRemoval(); void markAllForRemoval();

View File

@@ -0,0 +1,2 @@
TEMPLATE = subdirs
SUBDIRS += src tests

View File

@@ -0,0 +1,5 @@
import qbs
Project {
name: "SimpleBoost"
references: [ "src/src.qbs", "tests/tests.qbs" ]
}

View File

@@ -0,0 +1,6 @@
#include <iostream>
int main()
{
std::cout << "Hello BoostWorld!\n";
return 0;
}

View File

@@ -0,0 +1,4 @@
TEMPLATE = app
CONFIG -= qt app_bundle
CONFIG += console
SOURCES += main.cpp

View File

@@ -0,0 +1,6 @@
import qbs
CppApplication {
type: "application"
name: "HelloBoost application"
files: [ "main.cpp" ]
}

View File

@@ -0,0 +1,8 @@
TEMPLATE = app
CONFIG -= qt app_bundle
CONFIG += console
SOURCES += main.cpp
HEADERS += enab.h
isEmpty(BOOST_INCLUDE_DIR):BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $$BOOST_INCLUDE_DIR

View File

@@ -0,0 +1,11 @@
import qbs
import qbs.File
CppApplication {
name: "Decorators Test"
type: "application"
Properties {
condition: project.boostIncDir && File.exists(project.boostIncDir)
cpp.includePaths: [project.boostIncDir];
}
files: [ "enab.h", "main.cpp" ]
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <boost/test/included/unit_test.hpp>
namespace utf = boost::unit_test;
BOOST_AUTO_TEST_SUITE(Suite1, * utf::disabled())
BOOST_AUTO_TEST_CASE(test1)
{
BOOST_TEST(1 != 1);
}
BOOST_AUTO_TEST_CASE(Test2, * utf::enabled())
{
BOOST_TEST(2 != 2);
}
BOOST_AUTO_TEST_CASE(TestIo, * utf::enable_if<true>())
{
BOOST_TEST(3 != 3);
}
BOOST_AUTO_TEST_CASE(TestDb, * utf::enable_if<false>())
{
BOOST_TEST(4 != 4);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -0,0 +1,21 @@
#define BOOST_TEST_MODULE Suites and Decorators
#include <boost/test/included/unit_test.hpp>
#include "enab.h"
using boost::unit_test::label;
BOOST_AUTO_TEST_CASE(testWithout1, *label("WO")) { BOOST_TEST (true); }
BOOST_AUTO_TEST_CASE(testWithout2, *label("WO")) { BOOST_TEST (false); }
BOOST_AUTO_TEST_SUITE(SuiteOuter)
BOOST_AUTO_TEST_SUITE(SuiteInner1)
BOOST_AUTO_TEST_CASE(Test1) { BOOST_TEST (true); }
BOOST_AUTO_TEST_CASE(Test2) { BOOST_TEST (true); }
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(SuiteInner2, *boost::unit_test::disabled())
BOOST_AUTO_TEST_CASE(Test1, *label("I2")) { BOOST_TEST (false); }
BOOST_AUTO_TEST_CASE(Test2, *label("I2")) { BOOST_TEST (false); }
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(Test1, *label("O1")) { BOOST_TEST (true); }
BOOST_AUTO_TEST_CASE(Test2) { BOOST_TEST (true); }
BOOST_AUTO_TEST_CASE(Test2A) { BOOST_TEST (true); }
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -0,0 +1,18 @@
#define BOOST_TEST_MODULE fixture example
#include <boost/test/included/unit_test.hpp>
struct F {
F() : i( 0 ) { BOOST_TEST_MESSAGE( "setup fixture" ); }
~F() { BOOST_TEST_MESSAGE( "teardown fixture" ); }
int i;
};
BOOST_FIXTURE_TEST_CASE( test_case1, F )
{
BOOST_TEST( i++ == 1 );
}
BOOST_FIXTURE_TEST_CASE( test_case2, F, * boost::unit_test::disabled() )
{
BOOST_CHECK_EQUAL( i, 1 );
}

View File

@@ -0,0 +1,7 @@
TEMPLATE = app
CONFIG -= qt app_bundle
CONFIG += console
SOURCES += fix.cpp
isEmpty(BOOST_INCLUDE_DIR):BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $$BOOST_INCLUDE_DIR

View File

@@ -0,0 +1,11 @@
import qbs
import qbs.File
CppApplication {
name: "Fixture Test"
type: "application"
Properties {
condition: project.boostIncDir && File.exists(project.boostIncDir)
cpp.includePaths: [project.boostIncDir];
}
files: [ "fix.cpp" ]
}

View File

@@ -0,0 +1,41 @@
#include <boost/test/included/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>
#include <boost/bind.hpp>
using namespace boost::unit_test;
class TestClass
{
public:
void testMethod()
{
BOOST_TEST( true );
}
};
void freeTestFunction()
{
BOOST_TEST( true );
}
void freeTestFunction2(int i)
{
BOOST_TEST( i < 4 );
}
test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
{
boost::shared_ptr<TestClass> tester( new TestClass );
framework::master_test_suite().
add( BOOST_TEST_CASE( boost::bind( &TestClass::testMethod, tester )));
framework::master_test_suite().
add( BOOST_TEST_CASE( &freeTestFunction) );
int params[] = {1, 2, 3, 4, 5, 6};
framework::master_test_suite().
add( BOOST_PARAM_TEST_CASE( &freeTestFunction2, params, params + 6) );
return nullptr;
}

View File

@@ -0,0 +1,7 @@
TEMPLATE = app
CONFIG -= qt app_bundle
CONFIG += console
SOURCES += main.cpp
isEmpty(BOOST_INCLUDE_DIR):BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $$BOOST_INCLUDE_DIR

View File

@@ -0,0 +1,11 @@
import qbs
import qbs.File
CppApplication {
name: "Using Test Functions"
type: "application"
Properties {
condition: project.boostIncDir && File.exists(project.boostIncDir)
cpp.includePaths: [project.boostIncDir];
}
files: [ "main.cpp" ]
}

View File

@@ -0,0 +1,2 @@
TEMPLATE = subdirs
SUBDIRS += fix params deco

View File

@@ -0,0 +1,11 @@
import qbs
import qbs.Environment
Project {
name: "Tests"
property string boostIncDir: {
if (typeof Environment.getEnv("BOOST_INCLUDE_DIR") !== 'undefined')
return Environment.getEnv("BOOST_INCLUDE_DIR");
return undefined;
}
references: [ "deco/deco.qbs", "fix/fix.qbs", "params/params.qbs" ]
}