Skip to content

Commit 6833920

Browse files
committed
separate widget from calculation
This allows to only use the calculation in the cucumber tests. GUI is no longer needed in CI. Also simplifies the test setup within the cucumber / C++ code.
1 parent ca81ad4 commit 6833920

File tree

9 files changed

+140
-143
lines changed

9 files changed

+140
-143
lines changed

.github/workflows/run-all.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ jobs:
3030
nlohmann-json3-dev \
3131
qtbase5-dev \
3232
ruby \
33-
ruby-dev \
34-
xvfb
33+
ruby-dev
3534
3635
- name: install ruby tools
3736
run: |
@@ -50,7 +49,6 @@ jobs:
5049
5150
- name: build and run
5251
run: |
53-
export DISPLAY=:99
5452
./run-all.sh
5553
5654
- name: code coverage summary report

examples/CalcQt/CMakeLists.txt

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,39 @@
11
project(CalcQt)
22

33
if(TARGET Qt::Core AND TARGET Qt::Gui AND TARGET Qt::Widgets AND TARGET Qt::Test)
4-
add_library(libcalcqt STATIC src/CalculatorWidget.cpp src/CalculatorWidget.hpp)
5-
target_compile_options(libcalcqt PRIVATE "-Wno-deprecated-declarations")
6-
set_target_properties(libcalcqt PROPERTIES AUTOMOC ON)
4+
set(CMAKE_AUTOMOC ON)
5+
6+
add_library(libcalcqt STATIC src/Calculator.cpp src/Calculator.hpp)
77
target_include_directories(libcalcqt INTERFACE src)
88
target_link_libraries(libcalcqt
99
PUBLIC
1010
Qt::Core
11-
Qt::Widgets
11+
)
12+
13+
add_executable(calcqt
14+
src/CalcQt.cpp
15+
src/CalculatorWidget.cpp
16+
src/CalculatorWidget.hpp
17+
)
18+
target_link_libraries(calcqt
1219
PRIVATE
20+
libcalcqt
21+
Qt::Core
1322
Qt::Gui
23+
Qt::Widgets
1424
)
1525

16-
add_executable(calcqt src/CalcQt.cpp)
17-
target_link_libraries(calcqt PRIVATE libcalcqt Qt::Widgets)
18-
1926
add_executable(QtTestCalculatorQtSteps features/step_definitions/QtTestCalculatorQtSteps.cpp)
2027
target_link_libraries(QtTestCalculatorQtSteps PRIVATE libcalcqt Qt::Test cucumber-cpp)
2128

2229
if(TARGET Boost::unit_test_framework)
2330
add_executable(BoostCalculatorQtSteps features/step_definitions/BoostCalculatorQtSteps.cpp)
24-
target_link_libraries(BoostCalculatorQtSteps PRIVATE libcalcqt Boost::unit_test_framework cucumber-cpp Qt::Test)
31+
target_link_libraries(BoostCalculatorQtSteps PRIVATE libcalcqt Boost::unit_test_framework cucumber-cpp)
2532
endif()
2633

2734
if(TARGET GTest::gtest)
2835
add_executable(GTestCalculatorQtSteps features/step_definitions/GTestCalculatorQtSteps.cpp)
29-
target_link_libraries(GTestCalculatorQtSteps PRIVATE libcalcqt cucumber-cpp GTest::gtest Qt::Test)
36+
target_link_libraries(GTestCalculatorQtSteps PRIVATE libcalcqt GTest::gtest cucumber-cpp)
3037
endif()
3138

3239
endif()
Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,19 @@
1-
#include <cstdlib>
21
#include <cucumber-cpp/autodetect.hpp>
3-
#include <QApplication>
4-
#include <QTest>
52

6-
#include "CalculatorWidget.hpp"
3+
#include "Calculator.hpp"
74

8-
/// Helper class to ensure that QApplication gets destroyed before main() returns
9-
/// and that CalculatorWidget gets destroyed before QApplication gets destroyed.
10-
struct CalculatorCtx {
11-
CalculatorCtx() :
12-
argc(0),
13-
app(argc, NULL) {
5+
class CalculatorCtx {
6+
public:
7+
CalculatorCtx() {
8+
QObject::connect(&calculator, &Calculator::updateDisplay, [this](QString value) {
9+
display = value;
10+
});
1411
}
1512

16-
int argc;
17-
QApplication app;
18-
CalculatorWidget calculator;
13+
Calculator calculator{};
14+
QString display{};
1915
};
2016

21-
static int milliseconds = -1;
22-
23-
int millisecondsToWait() {
24-
if (milliseconds < 0) {
25-
char* envVariable = getenv("CALCQT_STEP_DELAY");
26-
milliseconds = (0 != envVariable) ? atoi(envVariable) : 0;
27-
}
28-
return milliseconds;
29-
}
30-
3117
std::istream& operator>>(std::istream& in, QString& val) {
3218
std::string s;
3319
in >> s;
@@ -41,48 +27,41 @@ std::ostream& operator<<(std::ostream& out, const QString& val) {
4127

4228
GIVEN("^I just turned on the calculator$") {
4329
cucumber::ScenarioScope<CalculatorCtx> ctx;
44-
ctx->calculator.move(0, 0);
45-
ctx->calculator.show();
46-
const bool window_shown = QTest::qWaitForWindowExposed(&ctx->calculator);
47-
ASSERT_TRUE(window_shown);
48-
QTest::qWait(millisecondsToWait());
4930
}
5031

5132
WHEN("^I press (\\d+)$") {
5233
REGEX_PARAM(unsigned int, n);
5334
cucumber::ScenarioScope<CalculatorCtx> ctx;
54-
QTest::keyClick(&ctx->calculator, Qt::Key_0 + n, Qt::NoModifier, millisecondsToWait());
35+
ctx->calculator.number(n);
5536
}
5637

5738
WHEN("^I press add") {
5839
cucumber::ScenarioScope<CalculatorCtx> ctx;
59-
QTest::keyClick(&ctx->calculator, Qt::Key_Plus, Qt::NoModifier, millisecondsToWait());
40+
ctx->calculator.add();
6041
}
6142

6243
WHEN("^I press calculate") {
6344
cucumber::ScenarioScope<CalculatorCtx> ctx;
64-
QTest::keyClick(&ctx->calculator, Qt::Key_Return, Qt::NoModifier, millisecondsToWait());
45+
ctx->calculator.calculate();
6546
}
6647

6748
WHEN("^I press clear") {
6849
cucumber::ScenarioScope<CalculatorCtx> ctx;
69-
QTest::keyClick(&ctx->calculator, Qt::Key_Escape, Qt::NoModifier, millisecondsToWait());
50+
ctx->calculator.clear();
7051
}
7152

7253
WHEN("^I press subtract") {
7354
cucumber::ScenarioScope<CalculatorCtx> ctx;
74-
QTest::keyClick(&ctx->calculator, Qt::Key_Minus, Qt::NoModifier, millisecondsToWait());
55+
ctx->calculator.subtract();
7556
}
7657

7758
THEN("^the display should be empty$") {
7859
cucumber::ScenarioScope<CalculatorCtx> ctx;
79-
EXPECT_EQ(ctx->calculator.display().size(), 0);
80-
QTest::qWait(millisecondsToWait());
60+
EXPECT_EQ(QString{}, ctx->display);
8161
}
8262

8363
THEN("^the display should show (.*)$") {
8464
REGEX_PARAM(QString, expected);
8565
cucumber::ScenarioScope<CalculatorCtx> ctx;
86-
EXPECT_EQ(expected, ctx->calculator.display());
87-
QTest::qWait(millisecondsToWait());
66+
EXPECT_EQ(expected, ctx->display);
8867
}

examples/CalcQt/src/CalcQt.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include <QApplication>
22

3+
#include "Calculator.hpp"
34
#include "CalculatorWidget.hpp"
45

56
int main(int argc, char* argv[]) {
67
QApplication app(argc, argv);
78
app.setApplicationName("Qt Calculator");
8-
CalculatorWidget widget;
9+
Calculator calculator{};
10+
CalculatorWidget widget{&calculator};
911
widget.show();
1012
return app.exec();
1113
}

examples/CalcQt/src/Calculator.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "Calculator.hpp"
2+
3+
QString Calculator::calculate(const QString& expression) const {
4+
int result = 0;
5+
char operation = '+';
6+
QRegExp regexp("(\\d+)");
7+
int pos = 0;
8+
while ((pos = regexp.indexIn(expression, pos)) != -1) {
9+
int value = regexp.cap(1).toInt();
10+
switch (operation) {
11+
case '+':
12+
result += value;
13+
break;
14+
case '-':
15+
result -= value;
16+
break;
17+
}
18+
pos += regexp.matchedLength();
19+
if (pos < expression.length()) {
20+
operation = expression.at(pos).toLatin1();
21+
}
22+
}
23+
return QString::number(result);
24+
}
25+
26+
void Calculator::number(quint8 number) {
27+
expression += QString::number(number);
28+
emit updateDisplay(expression);
29+
}
30+
31+
void Calculator::add() {
32+
expression += "+";
33+
emit updateDisplay(expression);
34+
}
35+
36+
void Calculator::subtract() {
37+
expression += "-";
38+
emit updateDisplay(expression);
39+
}
40+
41+
void Calculator::calculate() {
42+
expression = calculate(expression);
43+
emit updateDisplay(expression);
44+
}
45+
46+
void Calculator::clear() {
47+
expression.clear();
48+
emit updateDisplay(expression);
49+
}

examples/CalcQt/src/Calculator.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <QObject>
4+
5+
class Calculator : public QObject {
6+
Q_OBJECT
7+
8+
public:
9+
using QObject::QObject;
10+
11+
public slots:
12+
void number(quint8);
13+
void add();
14+
void subtract();
15+
void calculate();
16+
void clear();
17+
18+
signals:
19+
void updateDisplay(QString);
20+
21+
private:
22+
QString expression{};
23+
QString calculate(const QString& expression) const;
24+
};

0 commit comments

Comments
 (0)