Pages

Unit Testing Your QT Application And Analyzing the Coverage

Monday, May 2, 2016 0 comments

Testing your GUI application is undoubtedly a crucial, but difficult part of front end development life cycle. Unlike back-end development where you can mock or simulate the inputs and outputs, front end development requires a different method for simulating the input and validating the output.
 When testing a gui based application one can choose to

1.Simply test the model part of the application, which probably is shared by other back-end applications as well.
2. Isolate test the control to model part of the application (In a MVC architecture application)
3. Simulate user inputs and test the application from input to output

If we think about it option 3 is more towards a component test where you test your application end to end. If the developers practice testing with the code writing, chances are that unit tests will already be written to test the model classes before the GUI is even developed. It should be possible to use any existing testing framework to test the model of the application.
Testing control to model testing will require View part of your application mocked, which will require some additional effort during designing.

QT Test framework supports testing your GUI part of the application. Following is a method to setup a test project for your already developed application using QT test framework.
1. Create a separate QT project for the testing.
2. Add the test lib to .pro file
QT       += core gui testlib
3. Include your application to the test project pro file
include(/home/kanishka/Projects/CRM/CRM.pro)
4. Include the application sources, so that it could compile
INCLUDEPATH += "/home/kanishka/Projects/MyApp"
5. Comment the main file from the applications pro file during testing (I couldn't find any other way to continue the process)
6. Add Coverage flags to pro file
QMAKE_CXXFLAGS += -g -Wall -fprofile-arcs -ftest-coverage -O0

QMAKE_LFLAGS += -g -Wall -fprofile-arcs -ftest-coverage  -O0

LIBS += \
    -lgcov

After these configurations are complete, you can add classes to the test project. A test class is a normal class deriving from the QObject. Users are supposed to write the tests as private 
slots.
class NewTest : public QObject
{
    Q_OBJECT
public:
    explicit NewTest(QObject *parent = 0);

private slots:
    void initTestCase(); //Running once for the whole test case
    void init(){} // Runs for each test
    void DoAddNewTest(); //Test
    void cleanup(){}// Runs for each test
    void cleanupTestCase();//Running once for the whole test case

};

To run each test
NewTest myNewTestObject;
QTest::qExec(&myNewTestObject,argc, argv);


Writing a test and verifying is very well documented. Please refer the verification macros in http://doc.qt.io/qt-5/qtest.html

Coverage with LCOV
We have already configured g++ to provide gcov information during compilation. During compilation these information will be compiled to *.gcno files in your build directory.  When you run the tests coverage information will be written to *.gcda files. To convert them to LCOV files you need to run lcov utility.
lcov --base-directory . --directory . -c -o myapplication.info
genhtml -o ../my_html_output_dir  -t "My Application Test Coverage" --num-spaces 4 myapplication.info
This will dump your line coverage information using  LCOV  to ../my_html_output_dir which you can rename.


Using Google Test Framework with QT Application

Saturday, February 13, 2016 3 comments

QT includes it own testing frame work: QTTest. QTTest has good facilities to test a gui based application such as simulating a button click. Many developers will prefer to use QTest against GTest due to this reason. Anyway if we think GTest serves our needs better we can very easily setup it in our environment as well.
Steps to install google test
Download or clone the google test frame work from : https://github.com/google/googletest
. If download extract it and move to the directory. there is a sub directory named google test change directory to it.
At the moment google test guys are providing us a cmake file to generate the make. So
cmake .
make
sudo make install

Simple as that. It will give you an idea where the libraries were built and installed. For me libgtest.a  got installed at /usr/local/lib

To build your test you need to statically link this library. To do so add the following line to the .pro file will appropriate path changes.

LIBS += -L/usr/local/lib -lgtest

When you try to use the gtest library QT Creator will automatically provide you will the auto completes related to GTest( which looks amazing :) )

Prepare the main.cpp
To use this to test a QT application we need to do two things. Initialize QTApplication, initialize test framework.

#include 
#include 
int main(int argc, char *argv[])
{
    ::testing::InitGoogleTest(&argc, argv);
    QApplication a(argc, argv);

    return RUN_ALL_TESTS();
    a.exec();



}

If you try to run exec of the QT application you will get undefined behaviour. Eg. If you start the event loop the tests will never run. If tests are running you are never in the event loop. So these test should exclude anything related to QT event mechanism.

I used the bellow test to check if every thing was working
#include 
#include 
#include 
class FirstTest : public ::testing::Test
{
public:
    FirstTest();
    virtual void SetUp();
    virtual void TearDown();
};

TEST_F(FirstTest, HelloWorld)
{
    std::cout << "Hello" << std::endl;
    TesTee oTestee;
    int iAdded = oTestee.Add(5,2);
    oTestee.show();
    EXPECT_EQ(iAdded,7);

}
Even with limited testing capabilities for a gui test. QT testing framework can help us identify many issues in the code.
As a side note, Setup and TearDown gets called once for all tests it seems. Not for the entire class.

Managing Modularized Projects with QT Creator and Other tricks

Saturday, January 23, 2016 0 comments

One of the targets of good programming is to avoid rework. There are many ways to do this: use of libraries, use common code bases etc. This post will describe solutions to problems that are encounted  when attempting to create your module based application.

User of Pri and Pro Files

Usually .Pro files are used by complete projects, which you intend to run qmake directly. Pri files are intended to be included by other projects. There is no difference between these, to my knowledge. If you plan on making your project a module that is supposed to be used by other projects, simply copy the pro file and create a pri file. If anything is added to pro file, it should be added to pri file as well.
Though this seems duplicate, this will give you the flexibility to maintain separate configurations when the project is directly run and when run as a dependency (Ex: you may want to remove the main.cpp from the pri file since the other project will have a main.cpp as well).

Dependency file locations:

SOURCES += 
    MainWnd.cpp \
    MyTestWindow.cpp \

 
This is how QT Creator will add the cpp files. Similarly it will add ui files and header files as well.
When using as a dependency you may have to change this to


SOURCES += 
    $$PWD/MainWnd.cpp \
    $$PWD/MyTestWindow.cpp \


This will code the actual location of these files, without expecting them to be in the same directory as .pro file.



To use the header files during compilation
INCLUDEPATH += "../MyModule"
DEPENDPATH +="../MyModule" ""

Which will add header files and cpp files for compilation.

Customizing Ui file in parent module


Compile Parallel 

When compiling on linux make can use multiple threads for independent paths. We simply set the GMAKE_FLAGS. This can be alternatively done by adding the flag to QT Creator by opening the project -> Select Build and Run -> Click on build steps -> add the -j 4 [4 this the max threads] to the arguments section.


Using CMake with QT

Saturday, December 19, 2015 0 comments

Most QT developers prefer using qmake as the build management software as it is the widely used tool to maintain the build process in a platform independent way. CMake is the most common tool for this purpose in a non QT environment. I personalty do not see advantages in shifting to CMake in a QT development project, but if the project contains QT and non QT sections CMake can be the preffered tool for build process management. CMake can be used in a Continuous Integration tool to build the platform independent code in batches for automated builds as well.

The main configuration file for cmake is : CMakeLists.txt
I have added the following sample project with a single ui file.
git@bitbucket.org:kanishka_3000/styleeditor.git

Required configurations

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)

These will request cmake to add uic and moc steps into the build process.

Specify the ui files so that build process will include the uic

set(UI_HEADERS "")
set(UI_RESOURCES "")

qt5_wrap_ui(UI_HEADERS StyleEditor.ui)

Now add QT library dependencies 

set(CMAKE_PREFIX_PATH "/opt/Qt5.5.0/5.5/gcc_64" ${CMAKE_PREFIX_PATH} )
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Xml REQUIRED)
find_package(Qt5XmlPatterns REQUIRED)
find_package(Qt5OpenGL REQUIRED)

The highlighted line will append the CMake_Prefix path.

target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
target_link_libraries(${PROJECT_NAME} Qt5::Core)
target_link_libraries(${PROJECT_NAME} Qt5::Gui)

QT libraries are required for linking as well.

With the above minimum configurations for QT, CMake will create an appropriate make file or a visual studio configuration file (vcxproj) to build the project. 

It is possible to open the CMake project using the QTCreator as well. But when opened it does not allow us to open the ui files and change them accordingly. QTCreator will function as a simple text editor and cmake command executor. 


Bind Functions with std::bind and Member function pointers

Friday, September 25, 2015 0 comments

Another C++11 feature that comes into mind with the function objects is the bind function. Bind function, as the name suggests, returns a function object with some parameters hard bonded. In our previous example the routing function needs the *this bound to the function. It is a constant when the function is called by the object itself.



1
2
3
class Sorter;
typedef std::function<void(double)> FuncPointers;
using namespace std::placeholders;
The function now has only a single parameter. We have removed the Sorter* from the function object. The bind function will return a function object with the bounded parameters internally stored.

1
2
3
mapValues[0] = std::bind(&Sorter::OnSecondData,this,_1);
mapValues[1] = std::bind(&Sorter::OnFirstData,this,_1);
//mapValues[0] = &Sorter::OnSecondData;


Now the function object can be called just by passing the parameter value without passing the this object all the time.
1
2
3
4
5
void Sorter::OnData(int iRouter, double dValue)
{
    std::function<void(double)> myFunction = mapValues[iRouter];
    myFunction(dValue);
}
We can achieve the same result using member function pointers. But the syntax for member function pointers is extremely hard to read and remember. (At least for me).



1
2
3
class Sorter;
typedef void (Sorter::* FuncPointers)(double) ;
using namespace std::placeholders;

1
2
mapValues[0] =  &Sorter::OnSecondData;
mapValues[1] = &Sorter::OnFirstData;
Calling the function through member function pointer is more confusing syntax.
1
2
3
4
5
void Sorter::OnData(int iRouter, double dValue)
{
    void (Sorter::* myfunction)(double) = mapValues[iRouter];
    (this->*myfunction)(dValue);
}
Both these methods can be used for a routing function to route a data set to different data member functions.

C++11 Function Objects

Thursday, September 24, 2015 0 comments

C++11, is not exactly new any more, but many of us tend to stick to old version of C++. There are many cool features of C++11 that can ease our lives. One such feature is function objects, which has nothing to do with Functors (that was the first thing came into my mind). Function object are wrappers to functions. This is similar to storing the function pointer, but function object has characteristics of an object, so one may argue it to be more object oriented in nature.

In almost all over codes a pattern to route data to different functions based on and ID/Index can be found.
function First(void*);
function Second(void*);

function Router(int ID, void* Data)
{
    switch(ID)
          case 1:
           First(Data);
          case 2:
           Second(Data);
}

We can replace the above code with a much cooler alternative either using function pointers of function objects.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <cassert>
#include <map>
#include <functional>
#include <iostream>
using namespace std;
class Sorter;
typedef std::function<void(Sorter*,double)> FuncPointers;
using namespace std::placeholders;
class Sorter
{
    public:
        Sorter();
        virtual ~Sorter();
        void OnData(int iRouter, double dValue);
        void OnFirstData(double dValue);
        void OnSecondData(double dValue);
    protected:
    private:
    std::map<int , FuncPointers> mapValues;
};
Line 7 typedef is used to keep the code readable. Similar to function pointers, when referring a member function you need to add the pointer to object as the first parameter (you should have seen this in a core dump of a process). Therefore the function object takes takes a Sorter* and the double pointer to the function (The method does not specify the class object, the compiler adds it later on). Now we should add the functions to the map, so that the routing function has access to it.
1
2
3
4
5
6
Sorter::Sorter()
{

mapValues[0] = &Sorter::OnSecondData;
mapValues[1] = &Sorter::OnFirstData;
}
Now the routing method can get the function through this function pointers inside the map.
1
2
3
4
5
void Sorter::OnData(int iRouter, double dValue)
{
    std::function<void(Sorter*,double)> myFunction = mapValues[iRouter];
    myFunction(this,dValue);
}
As you can see, the methods are now stored inside the map and based on the routing ID the correct function is selected. This method of routing is obviously more costly than the traditional approach of using switch case. But in my opinion this is more maintainable.

Basics of MVC with QT tables

Sunday, June 14, 2015 1 comments

Most QT developers(including me) prefer using Qt Widgets directly instead of using Qt Views and Models. This approach is quite convenient for a very small program where you only need one view and one model, but with an application of  notable size, this would not do.

To start using QTs MVC we can start with the already implemented QTableModel and QTableView, which are obviously the most used MVC objects of QT. View in our case will most probably be declared using QT creator form editor. It is just an display item without any knowledge about model. QTableView has rows can columns based on the number it receives from the attached from the model. View will request data from the model once the respective rows are in view. It will not request data initially and store them.



#include <QAbstractTableModel>

class SampleModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit SampleModel(QObject *parent = 0);
    //View will request row count during initialization
    int rowCount(const QModelIndex & parent)const;
    //View will request row count during initialization
    int columnCount(const QModelIndex &parent) const;
    //View will request data when required row is in visible area.
    QVariant data(const QModelIndex &index, int role) const;

   QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
signals:

public slots:

};

To implement a model above functions need to be overridden. RowCount and ColumnCount functions are self explanatory. data() is called by view with the QModelIndex Object, which will contain the row and column information for which the view needs information.

Roles in Qt handles different behaviors of a particular data point. In this case the display role provides the data when the view needs to show a graphical item representing the data item. Another role would be Qt::ToolTipRole which will request data when view needs to show a tool tip for the data point. You can find different role at : http://doc.qt.io/qt-4.8/qt.html#ItemDataRole-enum  



QVariant SampleModel::data(const QModelIndex &index, int role) const
{
    if(role == Qt::DisplayRole)
    {
        QString sRet=  QString("%1:%2").arg(index.row()).arg(index.column());
        qDebug() << sRet;
        return sRet;
    }
    return QVariant();
}

QVariant SampleModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role == Qt::DisplayRole)
    {
        return QString("%1").arg(section+1);
    }
    return QVariant();
}

Above provides sample implementations of for data, which will simply send row and column information. For all other roles the implementation provides an empty QVariant, which should be interpreted as 'don't do anything' by the view.
 
Copyright © පොඩ්ඩාගේ ලෝකය..........
Blogger Theme by BloggerThemes Sponsored by Busy Buzz Blogging