Getting started with unit tests in Qt Creator and Catch

来源:互联网 发布:软件离职项目交接 编辑:程序博客网 时间:2024/05/24 05:21

转自

https://dragly.org/2015/11/24/getting-started-with-unit-tests-in-qt-creator-with-catch/


I have written about unit testing in Qt Creator on multiple occasions earlier. Since then, a new testing framework seems to have become a new leader in the field, and that is Catch. It is similar to UnitTest++ and Google's gtest and brings the best of both worlds. It is header-only and appears to reduce the amount of code that must be written in comparison to the other two.

This is an adopted version my previous posts that shows how to use Catch in a Qt Creator project. It doesn't any longer integrate the testing output into Qt Creator's issue pane. Instead I've started to rely on Travis CI or Jenkins to run the tests and notify me about any newly introduced errors.

An example project using this code structure has been posted on Github by Filip Sund (thanks, Filip!) and further adapted by us with the move to Catch.

The structure of the project is as follows:

MyProject├─ MyProject.pro├─ defaults.pri├─ app/│  ├─ app.pro│  └─ main.cpp├─ src/│  ├─ src.pro│  └─ myclass.cpp└─ tests/   ├─ tests.pro   └─ main.cpp

The main project file, MyProject.pro will now be based on a subdirs template, and may look like this:

TEMPLATE = subdirsCONFIG+=orderedSUBDIRS =      src      app      testsapp.depends = srctests.depends = src

The app.depends and tests.depends statements makes sure that the src project is compiled before the application and tests. This is because the src directory contains the library that will be used by both the app and the tests.

CONFIG+=ordered is needed because depends doesn't affect the order during make install.

defaults.pri

Each of the other .pro files will include defaults.pri to have all the headers available. defaults.pri contains the following:

INCLUDEPATH += $$PWD/srcSRC_DIR = $$PWD

If the library, main program and tests use common libraries, it is very useful to have the defaults.pri define these dependencies too.

./src

In the src folder, I have myclass.cpp, which is the class that I want to use and test. The src.pro needs to compile to a library, so that it may be used both by app and tests, and could look something like this:

include(../defaults.pri)CONFIG -= qtTARGET = myappTEMPLATE = libSOURCES += myclass.cppHEADERS += myclass.h

What this class does is not so interesting, it could be anything. A simple example could be this header file:

#ifndef MYCLASS_H#define MYCLASS_Hclass MyClass {public:    double addition(double a, double b);};#endif // MYCLASS_H

With this accompaning source file:

#include "myclass.h"double MyClass::addition(double a, double b) {    return a * b;}

./app

I only have a main.cpp file in app, because the app is basically just something that uses everything in the src folder. It will depend on the shared compiled library from src, and app.pro would look something like this:

include(../defaults.pri)TEMPLATE = appCONFIG += consoleCONFIG -= app_bundleCONFIG -= qtSOURCES += main.cppLIBS += -L../src -lmyapp

The main.cpp file could be a simple program that uses MyClass:

#include <myclass.h>#include <iostream>using namespace std;int main(){    MyClass adder;    cout << adder.addition(10, 20) << endl;    return 0;}

./tests

In the tests folder I have simply added a main.cpp which will run the tests. Then tests.pro has the following contents:

include(../defaults.pri)TEMPLATE = appCONFIG   += consoleCONFIG   -= app_bundleCONFIG   -= qtSOURCES += main.cppLIBS += -L../src -lmyapp

Which now links to the myapp library in addition to the unit tests.

The main.cpp in tests file which could contain the following, if we were to use UnitTest++ as our testing library:

#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file#include "catch.hpp"#include <myclass.h>TEST_CASE( "MyMath", "[mymath]" ) {    SECTION("Addition") {        MyClass my;        REQUIRE(my.addition(3,4) == 7);    }}

This test will fail because my implementation of MyClass::addition is completely wrong:

class MyClass {public:    double addition(double a, double b) {        return a * b;    }};

Note that I'm including MyClass by through <myclass.h> which is possible because of the INCLUDEPATH variable in defaults.pri.

This should help you define a project that compiles a library, as well as tests and an application using the library.




原创粉丝点击