diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 30b490c4..889ca232 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(Calc) +add_subdirectory(CalcQt) add_subdirectory(FeatureShowcase) diff --git a/examples/CalcQt/CMakeLists.txt b/examples/CalcQt/CMakeLists.txt new file mode 100644 index 00000000..88ac7e0a --- /dev/null +++ b/examples/CalcQt/CMakeLists.txt @@ -0,0 +1,21 @@ +project(CalcQt) + +find_package(Qt4 COMPONENTS QtCore QtGui QtTest) + +if(QT4_FOUND) + include(${QT_USE_FILE}) + set(CALCQT_HEADERS CalcQt/CalculatorWidget.h) + qt4_wrap_cpp(CALCQT_HEADERS_MOC ${CALCQT_HEADERS}) + include_directories(${CUKE_INCLUDE_DIRS} CalcQt) + add_library(CalcQt CalcQt/CalculatorWidget ${CALCQT_HEADERS_MOC}) + + if(Boost_UNIT_TEST_FRAMEWORK_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + add_executable(BoostCalculatorQtSteps CalcQtFeatures/BoostCalculatorQtSteps) + target_link_libraries(BoostCalculatorQtSteps CalcQt ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${CUKE_LIBRARIES} ${QT_LIBRARIES}) + endif() + + set(CALCQT_SOURCES CalcQt/CalcQt.cpp CalcQt/CalculatorWidget.cpp) + add_executable(calcqt ${CALCQT_SOURCES} ${CALCQT_HEADERS_MOC}) + target_link_libraries(calcqt ${QT_LIBRARIES}) +endif() \ No newline at end of file diff --git a/examples/CalcQt/CalcQt/CalcQt.cpp b/examples/CalcQt/CalcQt/CalcQt.cpp new file mode 100644 index 00000000..b8fb8398 --- /dev/null +++ b/examples/CalcQt/CalcQt/CalcQt.cpp @@ -0,0 +1,11 @@ +#include + +#include "CalculatorWidget.h" + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + app.setApplicationName("Qt Calculator"); + CalculatorWidget widget; + widget.show(); + return app.exec(); +} diff --git a/examples/CalcQt/CalcQt/CalculatorWidget.cpp b/examples/CalcQt/CalcQt/CalculatorWidget.cpp new file mode 100644 index 00000000..01505727 --- /dev/null +++ b/examples/CalcQt/CalcQt/CalculatorWidget.cpp @@ -0,0 +1,130 @@ +#include "CalculatorWidget.h" + +#include +#include +#include +#include +#include +#include + +CalculatorWidget::CalculatorWidget(QWidget *parent, Qt::WindowFlags flags) : QWidget(parent, flags) { + QGridLayout *layout = new QGridLayout; + layout->setSizeConstraint(QLayout::SetFixedSize); + setLayout(layout); + + QSizePolicy policy = sizePolicy(); + + displayLabel = new QLabel(this); + layout->addWidget(displayLabel, 0, 0, 1, 3); + displayLabel->setAutoFillBackground(true); + displayLabel->setBackgroundRole(QPalette::Base); + displayLabel->setAlignment(Qt::AlignRight); + displayLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + policy = displayLabel->sizePolicy(); + policy.setVerticalPolicy(QSizePolicy::Fixed); + displayLabel->setSizePolicy(policy); + + signalMapper = new QSignalMapper(this); + QPushButton *button = new QPushButton(QString::number(0), this); + QObject::connect(button, SIGNAL(clicked()), signalMapper, SLOT(map())); + signalMapper->setMapping(button, 0); + layout->addWidget(button, 4, 1); + digitButtons.push_back(button); + for (unsigned int i = 1; i < 10; ++i) { + QPushButton *button = new QPushButton(QString::number(i), this); + QObject::connect(button, SIGNAL(clicked()), signalMapper, SLOT(map())); + signalMapper->setMapping(button, i); + layout->addWidget(button, 1+(9-i)/3, (i-1)%3); + digitButtons.push_back(button); + } + QObject::connect(signalMapper, SIGNAL(mapped(int)), SLOT(buttonClicked(int))); + + clearButton = new QPushButton("C", this); + layout->addWidget(clearButton, 1, 4); + QObject::connect(clearButton, SIGNAL(clicked()), SLOT(clearButtonClicked())); + + additionButton = new QPushButton("+", this); + layout->addWidget(additionButton, 2, 4); + QObject::connect(additionButton, SIGNAL(clicked()), SLOT(addButtonClicked())); + + subtractionButton = new QPushButton("-", this); + layout->addWidget(subtractionButton, 3, 4); + QObject::connect(subtractionButton, SIGNAL(clicked()), SLOT(subtractButtonClicked())); + + calculateButton = new QPushButton("=", this); + layout->addWidget(calculateButton, 4, 4); + QObject::connect(calculateButton, SIGNAL(clicked()), SLOT(calculateButtonClicked())); +} + +int CalculatorWidget::calculate(const QString& expression) { + int result = 0; + char operation = '+'; + QRegExp regexp("(\\d+)"); + int pos = 0; + while ((pos = regexp.indexIn(expression, pos)) != -1) { + int value = regexp.cap(1).toInt(); + switch (operation) { + case '+': result += value; break; + case '-': result -= value; break; + } + pos += regexp.matchedLength(); + if (pos < expression.length()) { + operation = expression.at(pos).toAscii(); + } + } + return result; +} + +QString CalculatorWidget::display() { + return displayLabel->text(); +} + +void CalculatorWidget::keyPressEvent(QKeyEvent *event) { + keyclickedButton = 0; + int key = event->key(); + if (key >= Qt::Key_0 && key <= Qt::Key_9) { + keyclickedButton = digitButtons[key - Qt::Key_0]; + } + else { + switch(key) + { + case Qt::Key_Plus: keyclickedButton = additionButton; break; + case Qt::Key_Minus: keyclickedButton = subtractionButton; break; + case Qt::Key_Return: + case Qt::Key_Enter: + case Qt::Key_Equal: keyclickedButton = calculateButton; break; + case Qt::Key_Escape: keyclickedButton = clearButton; break; + } + } + if (0 != keyclickedButton) { + keyclickedButton->click(); + keyclickedButton->setDown(true); + } +} + +void CalculatorWidget::keyReleaseEvent(QKeyEvent *event) { + if (0 != keyclickedButton) { + keyclickedButton->setDown(false); + keyclickedButton = 0; + } +} + +void CalculatorWidget::addButtonClicked() { + displayLabel->setText(displayLabel->text()+"+"); +} + +void CalculatorWidget::buttonClicked(int index) { + displayLabel->setText(displayLabel->text()+QString::number(index)); +} + +void CalculatorWidget::calculateButtonClicked() { + displayLabel->setText(QString::number(calculate(displayLabel->text()))); +} + +void CalculatorWidget::clearButtonClicked() { + displayLabel->setText(""); +} + +void CalculatorWidget::subtractButtonClicked() { + displayLabel->setText(displayLabel->text()+"-"); +} diff --git a/examples/CalcQt/CalcQt/CalculatorWidget.h b/examples/CalcQt/CalcQt/CalculatorWidget.h new file mode 100644 index 00000000..fe555cea --- /dev/null +++ b/examples/CalcQt/CalcQt/CalculatorWidget.h @@ -0,0 +1,44 @@ +class QLabel; +class QPushButton; +#include +class QSignalMapper; +#include + +class CalculatorWidget : public QWidget { + Q_OBJECT + +public: + + CalculatorWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0); + + QString display(); + +protected: + + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); + +private: + + QLabel *displayLabel; + QVector digitButtons; + QPushButton *additionButton; + QPushButton *calculateButton; + QPushButton *clearButton; + QPushButton *subtractionButton; + + QPushButton *keyclickedButton; + + QSignalMapper *signalMapper; + + int calculate(const QString& expression); + +private Q_SLOTS: + + void addButtonClicked(); + void buttonClicked(int index); + void calculateButtonClicked(); + void clearButtonClicked(); + void subtractButtonClicked(); +}; + diff --git a/examples/CalcQt/CalcQtFeatures/BoostCalculatorQtSteps.cpp b/examples/CalcQt/CalcQtFeatures/BoostCalculatorQtSteps.cpp new file mode 100644 index 00000000..df7d9a29 --- /dev/null +++ b/examples/CalcQt/CalcQtFeatures/BoostCalculatorQtSteps.cpp @@ -0,0 +1,73 @@ + +#include + +#include +#include + +#include +#include + +#include + +static int argc = 0; +static QApplication app(argc, 0); +static int milliseconds = -1; + +int millisecondsToWait() { + if (milliseconds < 0) + { + char* envVariable = getenv("CALCQT_STEP_DELAY"); + milliseconds = (0 != envVariable) ? atoi(envVariable) : 0; + } + return milliseconds; +} + +std::istream& operator>> (std::istream& in, QString& val) { std::string s; in >> s; val = s.c_str(); return in; } +std::ostream& operator<< (std::ostream& out, const QString& val) { out << val.toAscii().data(); return out; } + +GIVEN("^I just turned on the calculator$") { + cucumber::ScenarioScope calculator; + calculator->move(0, 0); + calculator->show(); + QTest::qWaitForWindowShown(calculator.get()); + QTest::qWait(millisecondsToWait()); +} + +WHEN("^I press (\\d+)$") { + REGEX_PARAM(unsigned int, n); + cucumber::ScenarioScope calculator; + QTest::keyClick(calculator.get(), Qt::Key_0 + n, Qt::NoModifier, millisecondsToWait()); +} + +WHEN("^I press add") { + cucumber::ScenarioScope calculator; + QTest::keyClick(calculator.get(), Qt::Key_Plus, Qt::NoModifier, millisecondsToWait()); +} + +WHEN("^I press calculate") { + cucumber::ScenarioScope calculator; + QTest::keyClick(calculator.get(), Qt::Key_Return, Qt::NoModifier, millisecondsToWait()); +} + +WHEN("^I press clear") { + cucumber::ScenarioScope calculator; + QTest::keyClick(calculator.get(), Qt::Key_Escape, Qt::NoModifier, millisecondsToWait()); +} + +WHEN("^I press subtract") { + cucumber::ScenarioScope calculator; + QTest::keyClick(calculator.get(), Qt::Key_Minus, Qt::NoModifier, millisecondsToWait()); +} + +THEN("^the display should be empty$") { + cucumber::ScenarioScope calculator; + BOOST_CHECK_EQUAL(calculator->display().size(), 0); + QTest::qWait(millisecondsToWait()); +} + +THEN("^the display should show (.*)$") { + REGEX_PARAM(QString, expected); + cucumber::ScenarioScope calculator; + BOOST_CHECK_EQUAL(expected, calculator->display()); + QTest::qWait(millisecondsToWait()); +} diff --git a/examples/CalcQt/CalcQtFeatures/features/addition.feature b/examples/CalcQt/CalcQtFeatures/features/addition.feature new file mode 100644 index 00000000..4864b19d --- /dev/null +++ b/examples/CalcQt/CalcQtFeatures/features/addition.feature @@ -0,0 +1,19 @@ +# language: en +Feature: Addition + In order to avoid silly mistakes + As a math idiot + I want to be told the sum of two numbers + + Scenario Outline: Add two numbers + Given I just turned on the calculator + When I press + And I press add + And I press + And I press calculate + Then the display should show + + Examples: + | button1 | button2 | result | + | 2 | 3 | 5 | + | 7 | 5 | 12 | + | 9 | 1 | 10 | diff --git a/examples/CalcQt/CalcQtFeatures/features/behavior.feature b/examples/CalcQt/CalcQtFeatures/features/behavior.feature new file mode 100644 index 00000000..a075b981 --- /dev/null +++ b/examples/CalcQt/CalcQtFeatures/features/behavior.feature @@ -0,0 +1,77 @@ +# language: en +Feature: GUI behavior + tests for buttons + + Scenario Outline: Digit buttons + Given I just turned on the calculator + When I press