I want to do unit testing for some simple exercises i have done in c++ using Qt. i figured using QtTest seemed like a reasonable place to start.
i have a class that returns an integer and i want to test that the expected result is the same as the actual.
am i right in thinking i make a new c++ source file in the project to use as the QtTest
heres what i have but from reading the Qt documentation i cant work out what i have to do?
#include "Conversion.h"
#include <QtTest/QtTest>
class ConversionTest : public QObject
{
private slots:
void testConvert();
};
void ConversionTest::testConvert()
{
int unit1 = 1, unit2 = 10;
std::string sUnit1 = "stone", sUnit2 = "pound";
double expected = 10.8862;
double actual;
Conversion c;
actual = c.convert(unit1, unit2, sUnit1, sUnit2);
QCOMPARE(expected, actual);
}
QTEST_MAIN (ConversionTest)
#include "conversiontest.moc"
this is what i produced after reading the documentation but now what how do i run it and get the (what i think is) console output that says pass/fail?
any help would be great thanks
You need to create an app with it (QTEST_MAIN(..) builds the main function for you), and specify CONFIG += qtestlib in the .pro file.
When you run it, a console opens that prints out the test results.
I solved this myself the problem was just Qt errors no problem with the code at all, for some reason it didnt like that my project files were in a folder structure of more than one folder before my project files, used the exact same code in a new dir and it worked?? :S
Related
I used QT Desginer to create a finalversion_with_buttons.ui file,
later i converted it to finalversion_with_buttons.h file using the command
uic -o finalversion_with_buttons.h finalversion_with_buttons.ui
in command prompt.
I got to know that we cannot have a .cpp file and .h file contains everything we need, now how do i execute/run this .h file ?
Please check Qt Creator documentation e.g. "Creating a Qt Widget Based Application". It will give you some overview how to setup qmake/CMake project based on UI form files (aka Qt Widgets). The UI files itself may not be used standalone. It is only UI description.
It is always of benefit to create a ".pro" or ".cmake" file that contails all the stuff for the compilation of the project that has several benefits, even for
small programms.
I highly suggest reading through this sites, that helped me a lot in creating/compiling projects:
https://www.cprogramming.com/tutorial/makefiles.html
https://www.cprogramming.com/tutorial/makefiles_continued.html
This is what an automatic generated .pro file of the qt creator contains and I guess self explainatory:
QT += core gui multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
mainwindow.qrc
If you are working with the qt designer part of the qt creator you got this xml .ui file and the easiest way to compile it would be just clicking on Build->Run or ctrl+R. If your .pro file looks like the above example with the right file names you should be good to go.
Actually it is possible to have just a c++ file and no header files - thats invented to make the projects more modular with classes - thats what c++ is all about compared with c. To quote Bjarne "Classes use to hide the ugly stuff" ..so you can read the programm and understand it without even knowing what the class files contain and do with your code with a proper reference, and you don't should have to care. And thats what qt does - hiding the ugly stuff you would have to do all by yourself in its classes so you can just call QPushButton and it works. (and many more benefits but to keep it simple, qt is just c++ classes)
This is an example for a class in the code without a header file:
[//example from here https://www.cprogramming.com/tutorial/lesson12.html][1]
#include <iostream>
using namespace std;
class Computer // Standard way of defining the class
{
public:
// This means that all of the functions below this(and any variables)
// are accessible to the rest of the program.
// NOTE: That is a colon, NOT a semicolon...
Computer();
// Constructor
~Computer();
// Destructor
void setspeed ( int p );
int readspeed();
protected:
// This means that all the variables under this, until a new type of
// restriction is placed, will only be accessible to other functions in the
// class. NOTE: That is a colon, NOT a semicolon...
int processorspeed;
};
// Do Not forget the trailing semi-colon
Computer::Computer()
{
//Constructors can accept arguments, but this one does not
processorspeed = 0;
}
Computer::~Computer()
{
//Destructors do not accept arguments
}
void Computer::setspeed ( int p )
{
// To define a function outside put the name of the class
// after the return type and then two colons, and then the name
// of the function.
processorspeed = p;
}
int Computer::readspeed()
{
// The two colons simply tell the compiler that the function is part
// of the class
return processorspeed;
}
int main()
{
Computer compute;
// To create an 'instance' of the class, simply treat it like you would
// a structure. (An instance is simply when you create an actual object
// from the class, as opposed to having the definition of the class)
compute.setspeed ( 100 );
// To call functions in the class, you put the name of the instance,
// a period, and then the function name.
cout<< compute.readspeed();
// See above note.
}
And a compiler doesn't see something else after the linker is done than that.
so
"I got to know that we cannot have a .cpp file and .h file contains
everything we need"
is not right because you can as seen in the example above. Just its not how c++ (or c with classes as it was called in the early days) should be used.
But to answer your question:
"how do i execute/run this .h file ?"
like said before, just use the qt creator and click on Run or crtl + R
(it is free for opensource and edu)
create a project file like exampled before and use qmake SampleProject.pro
in the command line. This will create a file by the name of “Makefile” in the project directory.
(like described here https://vitux.com/compiling-your-first-qt-program-in-ubuntu/
than issue the command make in the same directory
(also described here)
Create a make file like described in link 1 and 2.
Everything else is beyond the scope of this question like fiddling out the semantic for using gcc or g++
That being said, you can create QPushButtons and all the stuff with the qt creator or you can create push buttons just in the code without using the .ui xml - file
like described here:
https://www.bogotobogo.com/Qt/Qt5_LayoutNotUsingDesigner.php
But what all of the guys here highly suggest is: Get yourself a goot qt/c++ book or tutorial and learn the foundations about classes and qt and you gonna get to be a really good programmer in no time. I also hope deeply this post is able to clarify a lot of qt programming/compiling for you and you start to have fun and will create really nice applications :) Cheers
In windows runtime component project (BackgroundTask c++)
#include "pch.h"
#include "BackgroundTask.h"
using namespace Platform;
namespace SyncBackground {
void BackgroundTask::Run(IBackgroundTaskInstance^ taskInstance) {
_taskInstance = taskInstance;
taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &BackgroundTask::OnCanceled);
_deferral = taskInstance->GetDeferral();
OutputDebugString(L"Debug: CPP\r\n");
}
void BackgroundTask::OnCanceled(IBackgroundTaskInstance^ sender, BackgroundTaskCancellationReason reason) {
_deferral->Complete();
}
}
I try ApplicationTrigger from c# project, but OutputDebugString write only one times from first trigger. In the same BackgroundTask C#, Debug.WriteLine() write every trigger.
Then why in c++ do it only one times? And how make it work look like c# (i need send some data and command via trigger)
Thank
I need it still run background
If I understand correctly, you just want to run background tasks indefinitely. If so, even if you don't call TaskDeferral.Complete();, it won't still run background, after a period of time, it will still be terminated. In that case, you can refer to this document to configure. But it mentions if you use it, you can't put an app into the Microsoft Store. If not, please point me out.
i am at wit's end trying to make SWI-Prolog play nice with C++. Now, before i start explaining exactly what my problem is, i want to first state what my project is about and what tools i chose in order to develop a solution.
My professor assigned to me the task of developing a GUI program that serves as a frontend to SWI-prolog, and this frontend is to be developed in C++. I chose to use Qt to design the GUI and use C++ as a backend to bridge SWI-Prolog to the application. The user of this application should be able to input some lists and then choose operations to be applied to them through prolog, like if, for example, I input a list of numbers, then by click of a button the user gets another list of all the numbers that are pairs in this list (if there are any). I am developing on a unix OS, more specifically, netrunner rolling release, based on archlinux and manjaro.
I did some research, and it seemed that the best course of action in order to interface SWI-Prolog (may i also mention that my professor also recommended this), is to use the header and source file developed by Volker Wysk; for reference, here is the link to the compressed file that contains these files http://www.volker-wysk.de/swiprolog-c++/index.html
Now here is my problem: if you visited the page i just gave you you will see that this C++ implementation of the SWI-Prolog interface is quite old: last time it was worked on was in the year 2002. I had to modify the header file so that i could get rid of some of the errors, like putting using namespace std or changing #include ostream.h to #include ostream, and so i managed to get the error count to only two which i can't manage to fix and which i think i won't be able to because there are two functions whose implementation i can't find anywhere: the function is declared but the code that it is supposed to run when they are called can't be found.
I will now list the contents of the files i consider to be most relevant. I have the latest version of SWI-Prolog installed, and so the SWI-Prolog.h header is the latest one that comes with the installation of the newest prolog (version 6.6.5).
#-------------------------------------------------
#
# Project created by QtCreator 2014-07-05T12:38:45
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = prologFrontend
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
../../../../../../../../usr/local/share/swiprolog-c++/prolog.cpp
LIBS += -L/usr/lib/swipl-6.6.5/lib/x86_64-linux -lswipl
HEADERS += mainwindow.h
FORMS += mainwindow.ui
contents of the prologFrontend.pro file (Qt creator project file)
#include "mainwindow.h"
#include <QApplication>
#include <prolog.hpp>
int main(int argc, char *argv[])
{
try {
Prolog_impl::prolog_init(argc, argv);
} catch(Prolog_impl::PlError &error) {
}
QApplication prog(argc, argv);
MainWindow w;
w.show();
return prog.exec();
}
contents of the main.cpp file
I would copy the whole contents of the header and source files made by Volker Wysk, but it's too long to fit in here. You can take a look at them if you download it from the link to his site i already posted. Next are the errors i am getting and the two corresponding code snippets where they happen in the .cpp file that he made:
// part of SWI-Prolog, but not exportet by header file
// /usr/local/src/swiprolog-4.0.9/src/pl-funcs.h
//NOTE: this function is declared here but it's even not to be found in the header file
//prolog.hpp. Its implementation can't be found anywhere using the function definition
//navigation capability of Qt so, basically, its a function that does nothing.
extern "C"{
unsigned long pl_atom_to_term(term_t in_atom,
term_t out_term,
term_t out_bindings);
}
bool Prolog_impl::atom_to_term(const char* text, Term* t, list<Term::Binding>* b)
{
Term in_atom = Atom(text);
Term out_term;
Term out_bindings;
if (!pl_atom_to_term(in_atom.lsi, out_term.lsi, out_bindings.lsi))
return false;
if (t) *t = out_term;
if (b) *b = out_bindings;
return true;
}
And the error that this code throws: /usr/local/share/swiprolog-c++/prolog.cpp:45: error: undefined reference to `pl_atom_to_term'.
//Note that this code has the same issues as the one above: no implementation to be found
extern "C"{
unsigned long pl_copy_term(term_t in, term_t out);
}
Term Prolog_impl::copy_term(Term t)
{
term_t t2 = PL_new_term_ref();
if (!pl_copy_term(t.lsi, t2))
throw LogicError("copy_term(Term)", "failure calling pl_copy_term()");
return Term(t2);
}
and the error that this code throws: /usr/local/share/swiprolog-c++/prolog.cpp:60: error: undefined reference to `pl_copy_term'.
Aside from the changes I had to make to the header file I already mentioned, I had to fix this line of code in the header file:
#include <SWI-Prolog.h>
to this:
#include "/usr/lib/swipl-6.6.5/include/SWI-Prolog.h"
This is because, otherwise, the compiler complains that it can't find that header file.
My guess is that these functions used to exist in an older SWI-Prolog version. I have no real clue about what to do with this task, i tried reading up on other alternatives to using volker's implementation but it's like there is close to none good information on the net about how to interface Prolog with C++.
Thank you so very much for taking your time to read my question. If you have a solution that works, please let me know. It doesn't have to be SWI-Prolog, it could be any other Prolog environment that interfaces nicely with C++ and that uses more or less about the same syntax that SWI-Prolog uses, though i think that the syntax is already standard for all environments.
Package swipl-win is a working SWI-Prolog / Qt interface, portable on Linux,MacOS,Windows. I have many others here, but these are restricted to running on Linux by now...
I wonder why, apart Qt specific problems, have you chosen an old, unmaintained C++ interface, when there is an 'official' one here. This interface is working pretty well, giving parameter validation based on exception handling and automatic type conversion. Then it's easy to add to the interface - for instance, from PREDICATE.h
typedef PlTerm T;
#define LOOP__ { } operator bool() { return next_solution(); }
#define query0(P) struct P : PlQuery { P() : PlQuery(#P, V()) LOOP__ };
#define query1(P) struct P : PlQuery { P(T A) : PlQuery(#P, V(A)) LOOP__ };
...
allows
query1(current_predicate)
void Completion::initialize(QSet<QString> &strings, bool reload) {
Q_UNUSED(reload)
T PRED;
for (current_predicate cp(PRED); cp; ) {
QString p = t2w(PRED);
if (p[0].isLetter())
strings.insert(p);
}
qDebug() << "Completion::initialize loaded" << strings.count();
}
About your specific problems, probably those functions are obsolete, you should stick to C Api (also know as foreign language interface) documented here.
Looking into the Makefile for swiprolog-c++-0.1.0, it looks like a special linker needs to be used, called plld. So you need to use your usual compiler to generate only the object files, then use that linker to create the executable.
The plld line in the makefile looks like this:
main : main.o prolog.o test.pl
plld -o $# -ld $(CC) $^ -lstdc++
The "recipe" line expands to this:
plld -o main -ld gcc main.o prolog.o test.pl -lstdc++
This is a weird question in that I'm not sure where to start looking.
First of all, I haven't done any C++ programming for the last 10 years so it could be me thats forgotten a few things. Secondly, the IDE I'm using is Eclipse based (which I've never used) and customized for Samsung bada based mobile development (it kicks off an emulator for debugging purposes)
I'm posting my code samples as images because the StackOverflow WYSIWYG editor seems to have a problem parsing C++.
[EDIT] Due to complaints I've edited my question to remove the images. Hope that helps :)
I have the following header file...
#include <FApp.h>
#include <FBase.h>
#include <FGraphics.h>
#include <FSystem.h>
#include <FMedia.h>
using namespace Osp::Media;
using namespace Osp::Graphics;
class NineAcross :
public Osp::App::Application,
public Osp::System::IScreenEventListener
{
public:
static Osp::App::Application* CreateInstance(void);
public:
NineAcross();
~NineAcross();
public:
bool OnAppInitializing(Osp::App::AppRegistry& appRegistry);
private:
Image *_problematicDecoder;
};
...and the following cpp file...
#include "NineAcross.h"
using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::System;
using namespace Osp::Graphics;
using namespace Osp::Media;
NineAcross::NineAcross()
{
}
NineAcross::~NineAcross()
{
}
Application* NineAcross::CreateInstance(void)
{
// Create the instance through the constructor.
return new NineAcross();
}
bool NineAcross::OnAppInitializing(AppRegistry& appRegistry)
{
Image *workingDecoder;
workingDecoder->Construct();
_problematicDecoder->Construct();
return true;
}
Now, in my cpp file, if I comment out the line that reads _problematicDecoder->Construct();...I'm able to set a breakpoint and happily step over the call to Constuct() on workingDecoder. However, as soon as I uncomment the line that reads _problematicDecoder->Construct();... I end up with the IDE telling me...
"No source available for "Osp::Media::Image::Construct()"
In other words, why can I NOT debug this code when I reference Image *image from a header file?
Any ideas?
Thanks :-)
This usually means you're stepping through some code which you do not posses its source.
I assume here that Osp::Media::Image is a class supplied by Samsung or similar for which you do not have the cpp file. So this means the debugger can't show you the current code line while you're at a function of Osp::Media::Image.
Alternatively, there's a good chance you do have all of the source code for this class, but Eclipse doesn't know where it is. In this case you can add the correct directories under the Debug Configurations window.
Ok, problem solved.
The idea is to first new up an instance of Image like so...
_decoder = new Osp::Media::Image();
And then do _decoder->Construct().
Funny enough, this seems blatantly obvious to me now coming from the C# world, though why the code I posted for workingDecoder works is still somewhat mysterious to me. The fact the sample projects pre-loaded with the bada IDE don't seem to make a call to new() leads me to believe that perhaps those samples are outdated our out of synch.
Either that or I really AM wildly out of the C++ loop.
Anyway thanks so much for the effort guys.
Appreciated :)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
I am just starting up a new project that needs some cross-platform GUI, and we have chosen Qt as the GUI-framework.
We need a unit-testing framework, too. Until about a year ago we used an in-house developed unit-testing framework for C++-projects, but we are now transitioning to using Google Test for new projects.
Does anyone have any experience with using Google Test for Qt-applications? Is QtTest/QTestLib a better alternative?
I am still not sure how much we want to use Qt in the non-GUI parts of the project - we would probably prefer to just use STL/Boost in the core-code with a small interface to the Qt-based GUI.
EDIT: It looks like many are leaning towards QtTest. Is there anybody who has any experience with integrating this with a continous integration server? Also, it would seem to me that having to handle a separate application for each new test case would cause a lot of friction. Is there any good way to solve that? Does Qt Creator have a good way of handling such test cases or would you need to have a project per test case?
You don't have to create separate tests applications. Just use qExec in an independent main() function similar to this one:
int main(int argc, char *argv[])
{
TestClass1 test1;
QTest::qExec(&test1, argc, argv);
TestClass2 test2;
QTest::qExec(&test2, argc, argv);
// ...
return 0;
}
This will execute all test methods in each class in one batch.
Your testclass .h files would look as follows:
class TestClass1 : public QObject
{
Q_OBJECT
private slots:
void testMethod1();
// ...
}
Unfortunately this setup isn't really described well in the Qt documentation even though it would seem to be quite useful for a lot of people.
I started off using QtTest for my app and very, very quickly started running into limitations with it. The two main problems were:
1) My tests run very fast - sufficiently quickly that the overhead of loading an executable, setting up a Q(Core)Application (if needed) etc often dwarfs the running time of the tests themselves! Linking each executable takes up a lot of time, too.
The overhead just kept on increasing as more and more classes were added, and it soon became a problem - one of the goals of unit tests are to have a safety net that runs so fast that it is not a burden at all, and this was rapidly becoming not the case. The solution is to glob multiple test suites into one executable, and while (as shown above) this is mostly do-able, it is not supported and has important limitations.
2) No fixture support - a deal-breaker for me.
So after a while, I switched to Google Test - it is a far more featureful and sophisticated unit testing framework (especially when used with Google Mock) and solves 1) and 2), and moreover, you can still easily use the handy QTestLib features such as QSignalSpy and simulation of GUI events, etc. It was a bit of a pain to switch, but thankfully the project had not advanced too far and many of the changes could be automated.
Personally, I will not be using QtTest over Google Test for future projects - if offers no real advantages that I can see, and has important drawbacks.
To append to Joe's answer.
Here's a small header I use (testrunner.h), containing an utility class spawning an event loop (which is, for example, needed to test queued signal-slot connections and databases) and "running" QTest-compatible classes:
#ifndef TESTRUNNER_H
#define TESTRUNNER_H
#include <QList>
#include <QTimer>
#include <QCoreApplication>
#include <QtTest>
class TestRunner: public QObject
{
Q_OBJECT
public:
TestRunner()
: m_overallResult(0)
{}
void addTest(QObject * test) {
test->setParent(this);
m_tests.append(test);
}
bool runTests() {
int argc =0;
char * argv[] = {0};
QCoreApplication app(argc, argv);
QTimer::singleShot(0, this, SLOT(run()) );
app.exec();
return m_overallResult == 0;
}
private slots:
void run() {
doRunTests();
QCoreApplication::instance()->quit();
}
private:
void doRunTests() {
foreach (QObject * test, m_tests) {
m_overallResult|= QTest::qExec(test);
}
}
QList<QObject *> m_tests;
int m_overallResult;
};
#endif // TESTRUNNER_H
Use it like this:
#include "testrunner.h"
#include "..." // header for your QTest compatible class here
#include <QDebug>
int main() {
TestRunner testRunner;
testRunner.addTest(new ...()); //your QTest compatible class here
qDebug() << "Overall result: " << (testRunner.runTests()?"PASS":"FAIL");
return 0;
}
I don't know that QTestLib is "better" than one framework for another in such general terms. There is one thing that it does well, and that's provide a good way to test Qt based applications.
You could integrate QTest into your new Google Test based setup. I haven't tried it, but based on how QTestLib is architected, it seems like it would not be too complicated.
Tests written with pure QTestLib have an -xml option that you could use, along with some XSLT transformations to convert to the needed format for a continuous integration server. However, a lot of that depends on which CI server you go with. I would imagine the same applies to GTest.
A single test app per test case never caused a lot of friction for me, but that depends on having a build system that would do a decent job of managing the building and execution of the test cases.
I don't know of anything in Qt Creator that would require a seperate project per test case but it could have changed since the last time I looked at Qt Creator.
I would also suggest sticking with QtCore and staying away from the STL. Using QtCore throughout will make dealing with the GUI bits that require the Qt data types easier. You won't have to worry about converting from one data type to another in that case.
Why not using the unit-testing framework included in Qt?
An example : QtTestLib Tutorial.
I unit tested our libraries using gtest and QSignalSpy. Use QSignalSpy to catch signals. You can call slots directly (like normal methods) to test them.
QtTest is mostly useful for testing parts that require the Qt event loop/signal dispatching. It's designed in a way that each test case requires a separate executable, so it should not conflict with any existing test framework used for the rest of the application.
(Btw, I highly recommend using QtCore even for non-GUI parts of the applications. It's much nicer to work with.)
To extend mlvljr's and Joe's solution we can even support complete QtTest options per one test class and still run all in a batch plus logging:
usage:
help: "TestSuite.exe -help"
run all test classes (with logging): "TestSuite.exe"
print all test classes: "TestSuite.exe -classes"
run one test class with QtTest parameters: "TestSuite.exe testClass [options] [testfunctions[:testdata]]...
Header
#ifndef TESTRUNNER_H
#define TESTRUNNER_H
#include <QList>
#include <QTimer>
#include <QCoreApplication>
#include <QtTest>
#include <QStringBuilder>
/*
Taken from https://stackoverflow.com/questions/1524390/what-unit-testing-framework-should-i-use-for-qt
BEWARE: there are some concerns doing so, see https://bugreports.qt.io/browse/QTBUG-23067
*/
class TestRunner : public QObject
{
Q_OBJECT
public:
TestRunner() : m_overallResult(0)
{
QDir dir;
if (!dir.exists(mTestLogFolder))
{
if (!dir.mkdir(mTestLogFolder))
qFatal("Cannot create folder %s", mTestLogFolder);
}
}
void addTest(QObject * test)
{
test->setParent(this);
m_tests.append(test);
}
bool runTests(int argc, char * argv[])
{
QCoreApplication app(argc, argv);
QTimer::singleShot(0, this, SLOT(run()));
app.exec();
return m_overallResult == 0;
}
private slots:
void run()
{
doRunTests();
QCoreApplication::instance()->quit();
}
private:
void doRunTests()
{
// BEWARE: we assume either no command line parameters or evaluate first parameter ourselves
// usage:
// help: "TestSuite.exe -help"
// run all test classes (with logging): "TestSuite.exe"
// print all test classes: "TestSuite.exe -classes"
// run one test class with QtTest parameters: "TestSuite.exe testClass [options] [testfunctions[:testdata]]...
if (QCoreApplication::arguments().size() > 1 && QCoreApplication::arguments()[1] == "-help")
{
qDebug() << "Usage:";
qDebug().noquote() << "run all test classes (with logging):\t\t" << qAppName();
qDebug().noquote() << "print all test classes:\t\t\t\t" << qAppName() << "-classes";
qDebug().noquote() << "run one test class with QtTest parameters:\t" << qAppName() << "testClass [options][testfunctions[:testdata]]...";
qDebug().noquote() << "get more help for running one test class:\t" << qAppName() << "testClass -help";
exit(0);
}
foreach(QObject * test, m_tests)
{
QStringList arguments;
QString testName = test->metaObject()->className();
if (QCoreApplication::arguments().size() > 1)
{
if (QCoreApplication::arguments()[1] == "-classes")
{
// only print test classes
qDebug().noquote() << testName;
continue;
}
else
if (QCoreApplication::arguments()[1] != testName)
{
continue;
}
else
{
arguments = QCoreApplication::arguments();
arguments.removeAt(1);
}
}
else
{
arguments.append(QCoreApplication::arguments()[0]);
// log to console
arguments.append("-o"); arguments.append("-,txt");
// log to file as TXT
arguments.append("-o"); arguments.append(mTestLogFolder % "/" % testName % ".log,txt");
// log to file as XML
arguments.append("-o"); arguments.append(mTestLogFolder % "/" % testName % ".xml,xunitxml");
}
m_overallResult |= QTest::qExec(test, arguments);
}
}
QList<QObject *> m_tests;
int m_overallResult;
const QString mTestLogFolder = "testLogs";
};
#endif // TESTRUNNER_H
own code
#include "testrunner.h"
#include "test1"
...
#include <QDebug>
int main(int argc, char * argv[])
{
TestRunner testRunner;
//your QTest compatible class here
testRunner.addTest(new Test1);
testRunner.addTest(new Test2);
...
bool pass = testRunner.runTests(argc, argv);
qDebug() << "Overall result: " << (pass ? "PASS" : "FAIL");
return pass?0:1;
}
If you are using Qt, I would recommend using QtTest, because is has facilities to test the UI and is simple to use.
If you use QtCore, you can probably do without STL. I frequently find the Qt classes easier to use than the STL counterparts.
I've just been playing around with this. The main advantage of using Google Test over QtTest for us is that we do all our UI development in Visual Studio. If you use Visual Studio 2012 and install the Google Test Adapter you can get VS to recognise the tests and include them in its Test Explorer. This is great for developers to be able to use as they write code, and because Google Test is portable we can also add the tests to the end of our Linux build.
I'm hoping in the future that someone will add support for C++ to one of the concurrent testing tools that C# have, like NCrunch, Giles and ContinuousTests.
Of course, you might find someone writes another adapter for VS2012 that adds QtTest support to Test Adapter in which case this advantage goes away! If anyone is interested in this there's a good blog post Authoring a new Visual studio unit test adapter.
For Visual Studio test adapter tool support with the QtTest framework use this Visual Studio extension: https://visualstudiogallery.msdn.microsoft.com/cc1fcd27-4e58-4663-951f-fb02d9ff3653