Test-Driven Development with Qt and KDE

Similar documents
Qt in Education. Custom Models

ECE 3574: Applied Software Design. Integration Testing

Model/View Architecture of Qt

2. The quiz screen showing the question, text field (QLineEdit in QT) for the answer and the Next Question button

SERIOUS ABOUT SOFTWARE. Qt Core features. Timo Strömmer, May 26,

Qt Essentials - Model View 2 Module

NHERI SIMCENTER PROGRAMMING BOOTCAMP JULY 30 THROUGH AUGUST 3, 2018, AT UC BERKELEY S RICHMOND FIELD STATION. GUI Development

Object-Oriented Programming

Create formulas in Excel

Developing PIM Applications with Akonadi. Till Adam / Volker Krause

Qt Essentials - Objects Module

Qt Essentials - Model View Module

The Qt and KDE Frameworks: An Overview

Qt Essentials - Fundamentals of Qt Module

Rio Hondo Prep Computer Applications Class

Developement of a framework for building tools for managing observations with a generic telescope. Alessandro Corongiu

Excel Basics 1. Running Excel When you first run Microsoft Excel you see the following menus and toolbars across the top of your new worksheet

Lab 12: GUI programming with Qt

Contents. Group 3 Excel Handouts 2010

Introduction to Excel 2007

QTangoCore. Elettra Sincrotrone Trieste. Giacomo Strangolino. A multi threaded framework to develop Tango applications

EXCEL 98 TUTORIAL Chemistry C2407 fall 1998 Andy Eng, Columbia University 1998

Analysis of the Test Driven Development by Example

A Tutorial for Excel 2002 for Windows

permission by Klarälvdalens Datakonsult AB.

Microsoft Excel Microsoft Excel

Microsoft Office Excel 2007

Introduction to Excel 2007

Introduction to the Boost C++ Libraries for KDE developers. Volker Krause

Excel. Spreadsheet functions

Math 227 EXCEL / MEGASTAT Guide

D-Optimal Designs. Chapter 888. Introduction. D-Optimal Design Overview

COS2614. Tutorial letter 203/1/2018. Programming: Contemporary Concepts. Semester 1. School of Computing. Discussion of Solutions to Assignment 3

STAT 311 (3 CREDITS) VARIANCE AND REGRESSION ANALYSIS ELECTIVE: ALL STUDENTS. CONTENT Introduction to Computer application of variance and regression

OpenGL and Qt Creator: a Gentle Introduction

Formulas in Microsoft Excel

Qt Essentials - Fundamentals of Qt Module

Qt in Education. The Model View Framework

Pivot Tables, Lookup Tables and Scenarios

Qt + Maemo development

The following article is about how to develop a high quality plugin.

The Qt and KDE Frameworks: An Overview

Exercises Lecture 2 The Qt Object Model and Signal Slot Mechanism

Data needs to be prepped for loading into matlab.

Advanced Excel Macros : Data Validation/Analysis : OneDrive

3.Constructors and Destructors. Develop cpp program to implement constructor and destructor.

This book is about using Microsoft Excel to

TUTORIAL FOR IMPORTING OTTAWA FIRE HYDRANT PARKING VIOLATION DATA INTO MYSQL

3 Excel Tips for Marketing Efficiency

Basic Excel 2010 Workshop 101

Section 3. Topics Covered

And Parallelism. Parallelism in Prolog. OR Parallelism

CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM

Basic Math in Microsoft Excel

Course contents. Overview: Goodbye, calculator. Lesson 1: Get started. Lesson 2: Use cell references. Lesson 3: Simplify formulas by using functions

European Computer Driving Licence. Advanced Spreadsheet Software BCS ITQ Level 3. Syllabus Version 2.0

Pointers, Arrays and Parameters

Using Microsoft Excel to View the UCMDB Class Model

Lab 1 The Basics of Qt

ENTERING DATA & FORMULAS...

John W. Jacobs Technology Center 450 Exton Square Parkway Exton, PA Introduction to

CSE 331 Final Exam 3/16/15 Sample Solution

ANSI C. Data Analysis in Geophysics Demián D. Gómez November 2013

COIMBATORE EDUCATIONAL DISTRICT

10 Ways To Efficiently Analyze Your Accounting Data in Excel

CISC 2200 Data Structure Fall, C++ Review:3/3. 1 From last lecture:

+ C++11. Qt5 with a touch of C++11. Matthew Eshleman covemountainsoftware.com

PROBLEM SOLVING AND OFFICE AUTOMATION. A Program consists of a series of instruction that a computer processes to perform the required operation.

Do not write in this area A.1 A.2 A.3 A.4 A.5 A.6 B.1 B.2 B.3 TOTAL. Maximum possible points:

Excel Forecasting Tools Review

8. Functions (II) Control Structures: Arguments passed by value and by reference int x=5, y=3, z; z = addition ( x, y );

Chapter 3: Data Description Calculate Mean, Median, Mode, Range, Variation, Standard Deviation, Quartiles, standard scores; construct Boxplots.

Exercises Lecture 4 Datatypes, Collections and Files

CS 330 Homework Comma-Separated Expression

Using Microsoft Word. Tables

MICROSOFT EXCEL 2007 ADVANCED

5. Excel Fundamentals

John W. Jacobs Technology Center 450 Exton Square Parkway Exton, PA Introduction to

M i c r o s o f t E x c e l A d v a n c e d P a r t 3-4. Microsoft Excel Advanced 3-4

6. Essential Spreadsheet Operations

Excel Module 7: Managing Data Using Tables

Microsoft How to Series

A Tutorial for Excel 2002 for Windows

Lab 2: ADT Design & Implementation

Functions in Excel. Structure of a function: Basic Mathematical Functions. Arithmetic operators: Comparison Operators:

UNIBALANCE Users Manual. Marcin Macutkiewicz and Roger M. Cooke

M i c r o s o f t E x c e l A d v a n c e d. Microsoft Excel 2010 Advanced

C++ GUI Programming with Qt 3

Exercises Lecture 3 Layouts and widgets

Excel as a Tool to Troubleshoot SIS Data for EMIS Reporting

4. Static Data Structures

Object Oriented Software Design - I

OpenClinica - Data Import & Export

NCSS Statistical Software. Design Generator

1. Intro to the Calc User's Guide This manual is copyright (c) 1989 by D. Pankhurst. All rights reserved. It has been made available to purchasers of

Tips & Tricks: MS Excel

Microsoft Excel Level 2

USING FORMULAS AND FUNCTIONS...

Chapter 3: The IF Function and Table Lookup

A Bullseye. Problem. Output. For each dataset, print a line of the form: SCORE: N to M, PLAYER P WINS. Or: SCORE: N to M, TIE.

Transcription:

Test-Driven Development with Qt and KDE Kevin Ottens Kevin Ottens Test-Driven Development with Qt and KDE 1/45

Introduction Goals Discover the possibilities of the Qt and KDE frameworks Practice Test-Driven Development (TDD) Method Putting in place the project infrastructure Developing the GUI part of the application Show the advantages of the model/view split available in Qt Apply TDD on the application model development Kevin Ottens Test-Driven Development with Qt and KDE 2/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 3/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 4/45

CMake and first source file Create a main.cpp file containing the main() function, only displaying a debug message; Create a file CMakeLists.txt for this project named spreadsheet; Create the build directory, and compile the project using CMake. Kevin Ottens Test-Driven Development with Qt and KDE 5/45

KApplication and first display Create a KAboutData and use it with KCmdLineArgs::init() Create a KApplication and an empty QWidget as main window Kevin Ottens Test-Driven Development with Qt and KDE 6/45

Toward a standard window Add a class SpreadSheetMainWindow which inherits from KXmlGuiMainWindow, use it as main window; Put in place the following actions: New, Open, Save, SaveAs, Quit, Cut, Copy, Paste Add one slot by action in SpreadSheetMainWindow (except for Quit which will be connected to the close() slot of the window. Hint : Use the KActionCollection and the method setupgui() provided by KXmlGuiMainWindow. Kevin Ottens Test-Driven Development with Qt and KDE 7/45

Spreadsheet interface Add a QTableWidget as the window central widget (force and initial size of 100 by 100); Add the actions Cut, Copy and Paste in the contextual menu of QTableWidget; Add two QLabel to SpreadSheetMainWindow and position them in the status bar (they ll be used to indicate the coordinates of the current cell, and the formula contained). Important in the following: In SpreadSheetMainWindow, the pointer to the QTableWidget will be of type QTableView*. Kevin Ottens Test-Driven Development with Qt and KDE 8/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 9/45

Implementing the base features Until now, we only put building blocks together No test written yet Here will develop the GUI based base features Our first unit test will be written nonetheless Kevin Ottens Test-Driven Development with Qt and KDE 10/45

Populate the table Hardcode the following dataset for the table initialization: William Adama 1947-02-24 Saul Tigh 1949-03-22 Lee Adama 1973-04-03 Kara Thrace 1980-04-08 Laura Roslin 1952-04-28 Gaius Baltar 1971-06-04 Kevin Ottens Test-Driven Development with Qt and KDE 11/45

Location Write a test for a static QString locationfromindex(int row, int column) which converts (0, 0) in A1, (0, 1) in B1 and so on; Implement the method while increasing the amount of data for the test; Implement the necessary to update the status bar depending on the current cell, we ll use locationfromindex(). Kevin Ottens Test-Driven Development with Qt and KDE 12/45

Manipulate data Implement Copy, Cut and Paste for one cell at a time; Extand it for contiguous cell zones (requires to force the behavior of selections in the view), pasting starts at the current cell. Kevin Ottens Test-Driven Development with Qt and KDE 13/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 14/45

MVC for our spreadsheet We ll now create our own data model for this spreadsheet. The main features will be implemented thanks to this model. Here, the TDD approach will be fully applied. Kevin Ottens Test-Driven Development with Qt and KDE 15/45

Model/view approach setup Implement a test for a new class SpreadSheetModel inheriting from QAbtractTableModel, during its creation such a model will contain only empty cells and have a size of 2 16 columns by 2 16 lines; Create a new class SpreadSheetModel which pass the previous test; Replace the QTableWidget of exercise 8 with a QTableView, give it an empty SpreadSheetModel during its creation. Information: rowcount() and columncount() must return 0 when the QModelIndex given as parameter is valid. For more information refers to the documentation of QAbstractTableModel. Kevin Ottens Test-Driven Development with Qt and KDE 16/45

Ensure lines and columns labelling Write the unit test for a static QString SpreadSheetModel::rowNameFromIndex(int) verify that we obtain "1" for 0, "2" for 1, "10" for 9, and so on; Write the method QString rownamefromindex(int); Write the unit test for a static QString SpreadSheetModel::columnNameFromIndex(int) verify that we obtain "A" for 0, "B" for 1, "Z" for 25, "AA" for 26, "BA" for 52, and so on; Write the method QString columnnamefromindex(int); Overload headerdata() in SpreadSheeModel to use the static methods freshly implemented... hey! the tests first; Modify the method locationfromindex() of SpreadSheetMainWindow to eliminate the code duplication. Information: Latest modification done without modifying any test, you made your first refactoring avoiding regressions. Kevin Ottens Test-Driven Development with Qt and KDE 17/45

Now, the questions will only be the unit tests that the model must pass. Kevin Ottens Test-Driven Development with Qt and KDE 18/45

Store text void SpreadSheetTest::testThatTextIsStored() { SpreadSheetModel m; QModelIndex index = m.index(21, 0); m.setdata(index, "A string"); QCOMPARE(m.data(index).toString(), QString("A string")); m.setdata(index, "A different string"); QCOMPARE(m.data(index).toString(), QString("A different string")); } m.setdata(index, ""); QCOMPARE(m.data(index).toString(), QString("")); Kevin Ottens Test-Driven Development with Qt and KDE 19/45

Verify that many cells exist void SpreadSheetTest::testThatManyCellsExist() { SpreadSheetModel m; QModelIndex a = m.index(0, 0); QModelIndex b = m.index(23, 26); QModelIndex c = m.index(699, 900); m.setdata(a, "One"); m.setdata(b, "Two"); m.setdata(c, "Three"); QCOMPARE(m.data(a).toString(), QString("One")); QCOMPARE(m.data(b).toString(), QString("Two")); QCOMPARE(m.data(c).toString(), QString("Three")); //=> Kevin Ottens Test-Driven Development with Qt and KDE 20/45

Verify that many cells exist //=> m.setdata(a, "Four"); } QCOMPARE(m.data(a).toString(), QString("Four")); QCOMPARE(m.data(b).toString(), QString("Two")); QCOMPARE(m.data(c).toString(), QString("Three")); Kevin Ottens Test-Driven Development with Qt and KDE 21/45

Store numeric data void SpreadSheetTest::testNumericCells() { SpreadSheetModel m; QModelIndex index = m.index(0, 20); m.setdata(index, "X99"); // String QCOMPARE(m.data(index).toString(), QString("X99")); m.setdata(index, "14"); // Number QCOMPARE(m.data(index).toString(), QString("14")); QCOMPARE(m.data(index).toInt(), 14); //=> Kevin Ottens Test-Driven Development with Qt and KDE 22/45

Store numeric data //=> // Whole string must be numeric m.setdata(index, "99 X"); QCOMPARE(m.data(index).toString(), QString("99 X")); bool ok; m.data(index).toint(&ok); QVERIFY(!ok); m.setdata(index, " 1234 "); // Blanks ignored QCOMPARE(m.data(index).toString(), QString("1234")); QCOMPARE(m.data(index).toInt(), 1234); } m.setdata(index, " "); // Just a blank QCOMPARE(m.data(index).toString(), QString(" ")); Hint : Add the asserts one by one. Kevin Ottens Test-Driven Development with Qt and KDE 23/45

Access to the original data for editing void SpreadSheetTest::testAccessToLiteralForEditing() { SpreadSheetModel m; QModelIndex index = m.index(0, 20); m.setdata(index, "Some string"); QCOMPARE(m.data(index, Qt::EditRole).toString(), QString("Some string")); m.setdata(index, " 1234 "); QCOMPARE(m.data(index, Qt::EditRole).toString(), QString(" 1234 ")); } m.setdata(index, "=7"); QCOMPARE(m.data(index, Qt::EditRole).toString(), QString("=7")); Kevin Ottens Test-Driven Development with Qt and KDE 24/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 25/45

Add the support for formulas It is wise to add asserts of each proposed test one by one Or to add more tests... It depends on your confidence level concerning formulas processing Kevin Ottens Test-Driven Development with Qt and KDE 26/45

Formulas support basics SpreadSheetTest::testFormulaBasics() { SpreadSheetModel m; QModelIndex index = m.index(2, 10); m.setdata(index, " =7"); // note leading space QCOMPARE(m.data(index).toString(), QString("=7")); QCOMPARE(m.data(index, Qt::EditRole).toString(), QString(" =7")); m.setdata(index, "=7"); // constant formula QCOMPARE(m.data(index).toString(), QString("7")); QCOMPARE(m.data(index, Qt::EditRole).toString(), QString("=7")); // Adding intermediate tests here to guide you is fine // Go ahead! //=> Kevin Ottens Test-Driven Development with Qt and KDE 27/45

Formulas support basics //=> m.setdata(index, "=(7)"); // parenthesis QCOMPARE(m.data(index).toString(), QString("7")); m.setdata(index, "=(((10)))"); // more parenthesis QCOMPARE(m.data(index).toString(), QString("10")); m.setdata(index, "=2*3*4"); // multiply QCOMPARE(m.data(index).toString(), QString("24")); m.setdata(index, "=12+3+4"); // add QCOMPARE(m.data(index).toString(), QString("19")); m.setdata(index, "=4+3*2"); // precedence QCOMPARE(m.data(index).toString(), QString("10")); //=> Kevin Ottens Test-Driven Development with Qt and KDE 28/45

Formulas support basics //=> } m.setdata(index, "=5*(4+3)*(((2+1)))"); // full expression QCOMPARE(m.data(index).toString(), QString("105")); Kevin Ottens Test-Driven Development with Qt and KDE 29/45

Error management void SpreadSheetTest::testFormulaErrors() { SpreadSheetModel m; QModelIndex index = m.index(0, 0); m.setdata(index, "=5*"); QCOMPARE(m.data(index).toString(), QString("#Error")); } m.setdata(index, "=((((5))"); QCOMPARE(m.data(index).toString(), QString("#Error")); Kevin Ottens Test-Driven Development with Qt and KDE 30/45

Minus, divide, negate The client notices that he forgot to ask for the support of the minus, divide and negate operators in formulas. You now have to add them: Add tests for minus and then implement Add tests for divide and then implement Add tests for negate and then implement Kevin Ottens Test-Driven Development with Qt and KDE 31/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 32/45

Verify that a reference works void SpreadSheetTest::testThatReferenceWorks() { SpreadSheetModel m; QModelIndex a = m.index(0, 0); QModelIndex b = m.index(10, 20); m.setdata(a, "8"); m.setdata(b, "=A1"); } QCOMPARE(m.data(b).toString(), QString("8")); Kevin Ottens Test-Driven Development with Qt and KDE 33/45

Verify that changes propagate void SpreadSheetTest::testThatChangesPropagate() { SpreadSheetModel m; QModelIndex a = m.index(0, 0); QModelIndex b = m.index(10, 20); m.setdata(a, "8"); m.setdata(b, "=A1"); QCOMPARE(m.data(b).toString(), QString("8")); } m.setdata(a, "9"); QCOMPARE(m.data(b).toString(), QString("9")); Kevin Ottens Test-Driven Development with Qt and KDE 34/45

Verify that formulas are recalculated void SpreadSheetTest::testThatFormulasRecalculate() { SpreadSheetModel m; QModelIndex a = m.index(0, 0); QModelIndex b = m.index(1, 0); QModelIndex c = m.index(0, 1); m.setdata(a, "8"); m.setdata(b, "3"); m.setdata(c, "=A1*(A1-A2)+A2/3"); QCOMPARE(m.data(c).toString(), QString("41")); m.setdata(b, "6"); } QCOMPARE(m.data(c).toString(), QString("18")); Kevin Ottens Test-Driven Development with Qt and KDE 35/45

Verify that changes propagate on several levels void SpreadSheetTest::testThatDeepChangesPropagate() { SpreadSheetModel m; QModelIndex a1 = m.index(0, 0); QModelIndex a2 = m.index(1, 0); QModelIndex a3 = m.index(2, 0); QModelIndex a4 = m.index(3, 0); m.setdata(a1, "8"); m.setdata(a2, "=A1"); m.setdata(a3, "=A2"); m.setdata(a4, "=A3"); QCOMPARE(m.data(a4).toString(), QString("8")); } m.setdata(a2, "6"); QCOMPARE(m.data(a4).toString(), QString("6")); Kevin Ottens Test-Driven Development with Qt and KDE 36/45

Verify the use of cells in several formulas void SpreadSheetTest::testThatFormulasWorkWithManyCells() { SpreadSheetModel m; QModelIndex a1 = m.index(0, 0); QModelIndex a2 = m.index(1, 0); QModelIndex a3 = m.index(2, 0); QModelIndex a4 = m.index(3, 0); QModelIndex b1 = m.index(0, 1); QModelIndex b2 = m.index(1, 1); QModelIndex b3 = m.index(2, 1); QModelIndex b4 = m.index(3, 1); //=> Kevin Ottens Test-Driven Development with Qt and KDE 37/45

Verify the use of cells in several formulas //=> m.setdata(a1, "10"); m.setdata(a2, "=A1+B1"); m.setdata(a3, "=A2+B2"); m.setdata(a4, "=A3"); m.setdata(b1, "7"); m.setdata(b2, "=A2"); m.setdata(b3, "=A3-A2"); m.setdata(b4, "=A4+B3"); } QCOMPARE(m.data(a4).toString(), QString("34")); QCOMPARE(m.data(b4).toString(), QString("51")); Kevin Ottens Test-Driven Development with Qt and KDE 38/45

Verify that the circular references give an error void SpreadSheetTest::testCircularReferences() { SpreadSheetModel m; QModelIndex a1 = m.index(0, 0); QModelIndex a2 = m.index(1, 0); QModelIndex a3 = m.index(2, 0); m.setdata(a1, "=A1"); m.setdata(a2, "=A1"); m.setdata(a3, "=A2"); QCOMPARE(m.data(a1).toString(), QString("#Error")); m.setdata(a1, "=A3"); } QCOMPARE(m.data(a1).toString(), QString("#Error")); Kevin Ottens Test-Driven Development with Qt and KDE 39/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 40/45

GUI cleanup If not done yet, remove the initialization of the table which was implemented previously If necessary, modify Cut, Copy and Paste so that they recopy formulas and not results; Add a test to ensure that the status bar displays the formula of the current cell, not its value; Add the code necessary to make the test pass. Hint: Use the parent/child relationship of QObject and its name property. Kevin Ottens Test-Driven Development with Qt and KDE 41/45

To go further... Some aspects are ignored in this training, and it would be necessary to see them to complete the application : saving, for this it d be required to take a look at QIODevice, KIO::NetAccess and KFileDialog; some small display issues tied to the lack of events emitted by the model, then it d be necessary to take care of the QAbstractItemModel signals like datachanged(); function support in formulas; and probably more... Kevin Ottens Test-Driven Development with Qt and KDE 42/45

Outline 1 Project setup and Main window 2 Implementing the base features 3 MVC for our spreadsheet 4 Add the support for formulas 5 Implement the support for references in formulas 6 Finalizing the application 7 Conclusion Kevin Ottens Test-Driven Development with Qt and KDE 43/45

Conclusion Facts We got a decent spreadsheet for the given effort The application is 433 lines of code, and only has two classes; Our tests are 368 lines of code, and they cover our model as well as a part of the GUI (we could have made more); We progressed by small modifications by adding a constraint at a time. What have you learned? How to apply test-driven development and its advantages Now you can add complex features progressibely and avoiding regressions Better understand the features provided by Qt and KDE How to obtain a lot of results with a few lines of code Kevin Ottens Test-Driven Development with Qt and KDE 44/45

Questions? Kevin Ottens ervin@kde.org Kevin Ottens Test-Driven Development with Qt and KDE 45/45