diff --git a/CHANGELOG.md b/CHANGELOG.md index e812d58e..ca3b5e05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CO ### Added +* QtTest based test driver for cucumber-cpp ([#165](https://github.com/cucumber/cucumber-cpp/pull/165) Kamil Strzempowicz) * Listen on localhost by default to avoid firewall warnings ([#158](https://github.com/cucumber/cucumber-cpp/pull/158) Nik Reiman) * Better integrate Qt into buildsystem, it can now be disabled, and test it in CI ([#160](https://github.com/cucumber/cucumber-cpp/pull/160) Kamil Strzempowicz & Giel van Schijndel) * Support taking regex captures as arguments to the step definition's function ([#159](https://github.com/cucumber/cucumber-cpp/pull/159) Giel van Schijndel) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6aef791..4b71a62e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,10 @@ if(NOT CUKE_DISABLE_QT) if(${Qt5Core_FOUND} AND ${Qt5Widgets_FOUND} AND ${Qt5Test_FOUND}) message(STATUS "Found Qt version: ${Qt5Core_VERSION_STRING}") set(QT_LIBRARIES Qt5::Core Qt5::Widgets Qt5::Test) + if(NOT Qt5Core_VERSION_STRING VERSION_LESS 5.7 AND (NOT DEFINED CMAKE_CXX_STANDARD OR NOT CMAKE_CXX_STANDARD STREQUAL 98)) + message(STATUS "C++11 is needed from Qt version 5.7.0, building with c++11 enabled") + set(CMAKE_CXX_STANDARD 11) + endif() else() find_package(Qt4 COMPONENTS QtCore QtGui QtTest) if(QT4_FOUND) diff --git a/README.md b/README.md index 84f0c4f7..143b93d5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ It relies on a few libraries: Optional for the GTest driver. By default downloaded and built by CMake. * [GMock](http://code.google.com/p/googlemock/) 1.6 or later. Optional for the internal test suite. By default downloaded and built by CMake. -* [Qt 4 or 5](http://qt-project.org/). Optional for the CalcQt example. +* [Qt 4 or 5](http://qt-project.org/). Optional for the CalcQt example and QtTest driver (only Qt 5). This header-only library is included in the source code: diff --git a/examples/Calc/CMakeLists.txt b/examples/Calc/CMakeLists.txt index 128bab60..e0e04c1d 100644 --- a/examples/Calc/CMakeLists.txt +++ b/examples/Calc/CMakeLists.txt @@ -20,3 +20,8 @@ if(Boost_UNIT_TEST_FRAMEWORK_FOUND) add_executable(BoostCalculatorSteps features/step_definitions/BoostCalculatorSteps) target_link_libraries(BoostCalculatorSteps Calc ${CUKE_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) endif() + +if(Qt5TEST_FOUND) + add_executable(QtTestCalculatorSteps features/step_definitions/QtTestCalculatorSteps) + target_link_libraries(QtTestCalculatorSteps Calc Qt5::Test ${CUKE_LIBRARIES}) +endif() diff --git a/examples/Calc/features/step_definitions/QtTestCalculatorSteps.cpp b/examples/Calc/features/step_definitions/QtTestCalculatorSteps.cpp new file mode 100644 index 00000000..d7bf4600 --- /dev/null +++ b/examples/Calc/features/step_definitions/QtTestCalculatorSteps.cpp @@ -0,0 +1,4 @@ +#include +// Pretend to be GTest +#define EXPECT_EQ QCOMPARE +#include "CalculatorSteps.cpp" diff --git a/examples/CalcQt/CMakeLists.txt b/examples/CalcQt/CMakeLists.txt index 6af66d3b..9388267c 100644 --- a/examples/CalcQt/CMakeLists.txt +++ b/examples/CalcQt/CMakeLists.txt @@ -9,12 +9,19 @@ if(QT_LIBRARIES) add_executable(calcqt src/CalcQt.cpp) target_link_libraries(calcqt libcalcqt ${QT_LIBRARIES}) + if(Qt5TEST_FOUND) + add_executable(QtTestCalculatorQtSteps features/step_definitions/QtTestCalculatorQtSteps) + target_link_libraries(QtTestCalculatorQtSteps PRIVATE libcalcqt ${QT_LIBRARIES} ${CUKE_LIBRARIES}) + endif() + if(Boost_UNIT_TEST_FRAMEWORK_FOUND) add_executable(BoostCalculatorQtSteps features/step_definitions/BoostCalculatorQtSteps) target_link_libraries(BoostCalculatorQtSteps libcalcqt ${CUKE_LIBRARIES} ${QT_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) endif() + if(GTEST_FOUND) add_executable(GTestCalculatorQtSteps features/step_definitions/GTestCalculatorQtSteps) target_link_libraries(GTestCalculatorQtSteps libcalcqt ${CUKE_LIBRARIES} ${CUKE_GTEST_LIBRARIES} ${QT_LIBRARIES}) endif() + endif() diff --git a/examples/CalcQt/features/step_definitions/QtTestCalculatorQtSteps.cpp b/examples/CalcQt/features/step_definitions/QtTestCalculatorQtSteps.cpp new file mode 100644 index 00000000..895f2ad3 --- /dev/null +++ b/examples/CalcQt/features/step_definitions/QtTestCalculatorQtSteps.cpp @@ -0,0 +1,4 @@ +#include +// Pretend to be GTest +#define EXPECT_EQ QCOMPARE +#include "CalculatorQtSteps.cpp" diff --git a/include/cucumber-cpp/internal/drivers/DriverSelector.hpp b/include/cucumber-cpp/internal/drivers/DriverSelector.hpp index f4ac8567..559be1ab 100644 --- a/include/cucumber-cpp/internal/drivers/DriverSelector.hpp +++ b/include/cucumber-cpp/internal/drivers/DriverSelector.hpp @@ -2,4 +2,6 @@ #include "GTestDriver.hpp" #elif defined(BOOST_TEST_CASE) #include "BoostDriver.hpp" +#elif defined(QTEST_H) + #include "QtTestDriver.hpp" #endif diff --git a/include/cucumber-cpp/internal/drivers/QtTestDriver.hpp b/include/cucumber-cpp/internal/drivers/QtTestDriver.hpp new file mode 100644 index 00000000..94e3ab22 --- /dev/null +++ b/include/cucumber-cpp/internal/drivers/QtTestDriver.hpp @@ -0,0 +1,40 @@ +#ifndef CUKE_QTTESTDRIVER_HPP_ +#define CUKE_QTTESTDRIVER_HPP_ + +#include "../step/StepManager.hpp" +#include + +namespace cucumber { +namespace internal { + +class QtTestStep : public BasicStep { + friend class QtTestObject; + +public: + QtTestStep() : BasicStep() {} + +protected: + const InvokeResult invokeStepBody(); +}; + +#define STEP_INHERITANCE(step_name) ::cucumber::internal::QtTestStep + +class QtTestObject : public QObject { + Q_OBJECT +public: + QtTestObject(QtTestStep* qtTestStep) : step(qtTestStep) {} + virtual ~QtTestObject() {} + +protected: + QtTestStep* step; + +private slots: + void test() const { + step->body(); + } +}; + +} +} + +#endif /* CUKE_QTTESTDRIVER_HPP_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 818d7b83..1430b9db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,13 @@ if(Boost_UNIT_TEST_FRAMEWORK_FOUND) list(APPEND CUKE_SOURCES drivers/BoostDriver.cpp) endif() +if(Qt5TEST_FOUND) + qt5_wrap_cpp(MOC_FILE ../include/cucumber-cpp/internal/drivers/QtTestDriver.hpp) + list(APPEND CUKE_SOURCES ${MOC_FILE}) + list(APPEND CUKE_SOURCES drivers/QtTestDriver.cpp) + list(APPEND CUKE_DEP_LIBRARIES Qt5::Test) +endif() + if(CMAKE_EXTRA_GENERATOR OR MSVC_IDE) message(STATUS "Adding header files to project") file(GLOB_RECURSE CUKE_HEADERS "${CUKE_INCLUDE_DIR}/cucumber-cpp/*.hpp") diff --git a/src/drivers/QtTestDriver.cpp b/src/drivers/QtTestDriver.cpp new file mode 100644 index 00000000..f55b3005 --- /dev/null +++ b/src/drivers/QtTestDriver.cpp @@ -0,0 +1,33 @@ +#include "cucumber-cpp/internal/drivers/QtTestDriver.hpp" + +#include +#include +#include + +namespace cucumber { +namespace internal { + +const InvokeResult QtTestStep::invokeStepBody() { + QTemporaryFile file; + if (!file.open()) { + return InvokeResult::failure("Unable to open temporary file needed for this test"); + } + file.close(); + + QtTestObject testObject(this); + int returnValue = QTest::qExec(&testObject, + QStringList() << "test" + << "-o" + << file.fileName()); + if (returnValue == 0) { + return InvokeResult::success(); + } else { + file.open(); + QTextStream ts(&file); + return InvokeResult::failure(ts.readAll().toLocal8Bit()); + } +} + +} +} + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6e13c887..300dac5d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -48,4 +48,8 @@ if(Boost_UNIT_TEST_FRAMEWORK_FOUND) cuke_add_driver_test(integration/drivers/BoostDriverTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) endif() +if(Qt5TEST_FOUND) + cuke_add_driver_test(integration/drivers/QtTestDriverTest ${QT_LIBRARIES}) +endif() + cuke_add_driver_test(integration/drivers/GenericDriverTest) diff --git a/tests/integration/drivers/QtTestDriverTest.cpp b/tests/integration/drivers/QtTestDriverTest.cpp new file mode 100644 index 00000000..6f4373f6 --- /dev/null +++ b/tests/integration/drivers/QtTestDriverTest.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include "../../utils/DriverTestRunner.hpp" + +using namespace cucumber; + +THEN(SUCCEED_MATCHER) { + ScenarioScope ctx; + QVERIFY(true); +} + +THEN(FAIL_MATCHER) { + ScenarioScope ctx; + QVERIFY(false); +} + +THEN(PENDING_MATCHER_1) { + pending(); +} + +THEN(PENDING_MATCHER_2) { + pending(PENDING_DESCRIPTION); +} + +using namespace cucumber::internal; + +class QtTestStepDouble : public QtTestStep { +public: + QtTestStepDouble() : QtTestStep(), testRun(false) {} + + const InvokeResult invokeStepBody() { + return QtTestStep::invokeStepBody(); + } + + void body() { + testRun = true; + } + + bool testRun; +}; + +class QtTestDriverTest : public DriverTest { +public: + virtual void runAllTests() { + stepInvocationRunsStepBody(); + DriverTest::runAllTests(); + } + +private: + void stepInvocationRunsStepBody() { + QtTestStepDouble framework; + expectFalse("The test body has not been run", framework.testRun); + framework.invokeStepBody(); + expectTrue("The test body has been run", framework.testRun); + } +}; + +int main() { + QtTestDriverTest test; + return test.run(); +} diff --git a/travis.sh b/travis.sh index 423f31c9..1bab7969 100755 --- a/travis.sh +++ b/travis.sh @@ -59,6 +59,7 @@ startXvfb # Start virtual X display server for TEST in \ build/examples/Calc/GTestCalculatorSteps \ + build/examples/Calc/QtTestCalculatorSteps \ build/examples/Calc/BoostCalculatorSteps \ build/examples/Calc/FuncArgsCalculatorSteps \ ; do @@ -72,6 +73,7 @@ done for TEST in \ build/examples/CalcQt/GTestCalculatorQtSteps \ + build/examples/CalcQt/QtTestCalculatorQtSteps \ build/examples/CalcQt/BoostCalculatorQtSteps \ ; do if [ -f "${TEST}" -a -n "${DISPLAY:-}" ]; then