Using a QT window as part of a C++ unit test - c++

I have some code which uses WinAPI to get the title and classname of a window from it's handle using GetWindowTextW and GetClassNameW. I would like to create a unit test for this code using Qt to create a temporary window, run my code against it, and then close the window. However I'm unsure how to go about doing this in a simple way. For example, I could create the window as follows:
#include "QtWidgets\qapplication.h"
#include "QtWidgets\qtextedit.h"
int argc = 1;
char* argv[1];
QApplication app(argc, &argv[0]);
QTextEdit textEdit;
textEdit.show();
app.exec(;)
// Rest of my unit test here
However at that point the QApplication object enters it's event loop and assumes control of my unit test until I close the window. What is the best way to allow my unit test to continue operating on the window? Should I create a separate thread for the window? Being a unit test, I would like to keep it as simple as possible.
This question is intended to be unit test framework independent, but in case it matters, I'm using UnitTest++.

You won't be able to create a separate thread, since all Qt gui objects have to be in the main thread, you can only use signals/slot mechanism to interact with gui objects from other threads.
I think the simplest would be to subclass QTextEdit, implement public slot UnitTest(), and modify your test as follows:
#include "QtWidgets\qapplication.h"
#include "QtWidgets\qtextedit.h"
#include "MyTextEdit.h"
#include <QTimer>
int argc = 1;
char* argv[1];
QApplication app(argc, &argv[0]);
my_QTextEdit textEdit;
textEdit.show();
QTimer::singleShot(&my_QTextEdit,SLOT(UnitTest()),0);
app.exec();
This gives you an entry point to my_QTextEdit::UnitTest() after QApplication is properly instantiated and event loop is running. Or, you can implement your own class inherited from QObject, create public slot, create that object prior to running app.exec() (passing to it pointer to QTextEdit if necessary) ; and connect to the slot the same way - whatever suits your needs better.

In my automated Qt tests, I generally skip the use of QApplication::exec in favour of using QCoreApplication::hasPendingEvents and QCoreApplication::processEvents - this lets you do some prep work, flush the event queue (so Qt gets a chance to actually show your window), do some more work, let Qt handle any additional events that this has thrown up, etc; it's a very handy approach for achieving the fine-grained control you need when you want to exercise small pieces of logic.

reasonably working example code for doing this is in this related question's answer: Qt event loop and unit testing?

Related

How to wrap a command line tool into an app and properly quit it?

I have a multi-threaded command-line program in C++. When launched from the terminal, I can properly quit with q <RET>, which will call a series of clean_up routines which will eventually release all resources. Note that if q <RET> is never pressed the program just loops forever. Note also that the program launches some GUI Windows on its own.
I need to wrap this tool as an app - nothing really fancy, just a nice icon with all the necessary assets inside it so that simple users can launch it simply by double-clicking. I've used Platypus with success to make such an app in the past.
However I can't find a way to properly quit the program. There is no way to std::cin in my program from there and I reckon that on quit (from the menu or cmd-Q) platypus just sends a SIGTERM or something similar to my program (I can't really use this to properly clean my application - I need to end the infinite loop on main and have all destructors called implicitly when leaving main).
Isn't there any other easy way to wrap my program as an .app, but in a way that I can call a particular function on quit? I thought of creating a dummy app with Cocoa/Swift, make my program a static lib and call it from there, but there has to be a simpler way.
I'd wrap it with an application that uses the Qt Framework, which also uses C++.
Using QProcess to launch the program, the documentation states: -
The QProcess class is used to start external programs and to communicate with them
Here's a simple example of what you can do...
#include <QApplication>
int main(int argc, char *argv[])
{
// Main application class
// Use QCoreApplication instead, if this is not a GUI app
QApplication app(argc, argv);
// launch the process with the given arguments
QProcess *myProcess = new QProcess(parent);
myProcess->start(program, arguments);
if (!myProcess.waitForStarted())
return -1;
// quit the app as soon as it has started, but
// just for demonstration purposes
myProcess.write("q");
return app.exec(); // starts the event loop
}
You can build a handler for SIGTERM in your app.
Here's a program I wrote that does this, but in C it's a common practice to bind signals to handlers with the "signal" function. Given that you're using C++, you can use C with it directly, or find the equivalent thing in C++ (of which there surely is an identical construct). The key thing is to use the signal function to bind signal with handler.
https://github.com/jpnorair/otter/blob/master/main/main.c

Boost unit test Qt signal

Using Boost Unit Test framework to perform unit test on C++\Qt code.
We are basically using BOOST_FIXTURE_TEST_CASE macro as shown in documentation. For each test we create an instance of QApplication to setup the event loop and enable the test code to use signals and slots.
Now we need to test whether a signal is emitted or not. Does anyone have any experience with this issue?
The BOOST_FIXTURE_TEST_CASE generated class does not inlucde Q_OBJECT and does not derived from QObject which I guess would be a problem. Appreciate some input on this issue.
I'm working on a similar issue, but using gtest rather than the Boost Unit Test framework. While I don't have the answer yet I am making progress, here is what I know so far.
First of all, Qt does not like it when QApplication or QCoreApplication are generated outside of main. Also, QApplication applies to GUI classes of Qt, while QCoreApplication can be used for console only classes (like QTcpSocket which is what I am trying to test now). GUI stuff is not really testable, so anything you are testing should be written into a separate class. This will allow you to unit test your code without dealing with the GUI, and also let you use QCoreApplication.
The next step is to use QThread to spin up a thread that hosts the object you are trying to test. QThread has its own event loop that can be run by calling its exec() function.
Write your test cases to pull from QThread and you'll have an event loop that you can use for the signals and slots, which should make it much easier to determine if a signal was emitted. Without the event loop the signal will just sit there and do nothing, so there is no way to test if it was sent!

Render off screen widget in a separate thread Qt

The application I'm working on is made of many C threads communicating together via messages (0mq). One of these threads is handling the display and should render off screen a widget in order to communicate its "screenshot" to other threads of the application.
The thing is that in order to paint a widget, you need to place it in a QApplication and call the exec() method of the QApplication, which is essentially a loop. So my thread is then completely stuck and can't communicate with the outside world anymore since it's in the exec() method.
Is there a way I can launch the QApplication in a separate thread and communicate with it so my display thread doesn't get stuck?
Or is there at least a way to do what I want to do with Qt?
Thanks a lot !
Edit: This application will eventually be a Qt Embedded Application
Update Basically, my question is : how to start a QApplication in a separate thread from my C code and communicate with it?
I ended up creating a separate thread for the QApplication main event loop (exec()) and used 0mq sockets to communicate with it from the rest of my application.
I don't understand what do you mean by "paint a widget". But be aware: QWidget is a part of GUI and GUI parts should be touched by Main(UI) thread only. It is a rule you can't change. Moreover QApplication works on Main thread only since QApplication is the main part of the GUI itself.
You can post messages to QAppplication by using global qApp object(you need to include QApplication for it) and sendEvent() or postEvent() methods.
Also I'd suggest you to generate QImage with whatever data you have and propagate it via aforementioned event mechanism to the widget you need. But, obviously, I don't know what you really need.

Qt - How to detect closed window in custom event loop without using slots

I'm working on an OpenGL-based game using QGLWidget as a front-end. But due to all of the unnecessary overhead (plus having to distribute the heavy QT libraries!) I plan to migrate to GLUT, and am in the process of replacing 'Qt-stuff' with more standard alternatives before the big leap.
To replace the QTimers that control the framerate and fps timer, I'm trying to wedge those functions into a simple loop that replaces the app.exec() call, as follows:
//main.cpp
#include <QApplication>
#include <windows.h>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow mainWin;//only contains a glwidget
mainWin.show();
do {
app.processEvents();
//call draw functions/fps based on system tick count
//...
Sleep(10);
} while (!app.closingDown()); //<-- this doesn't terminate
return 0;
}
So far it works fine during runtime, however once you try to close the window (via the system 'X' button), the window goes away but the program hangs in the background. The problem is that I can't find a static flag or query function that indicates that exit() or close() has been called. bool closingDown() always seems to be false, and I've tried toggling a static flag in the ~MainWindow destructor and detecting that, but that doesn't work either since that isn't called until main ends. I know I could probably do it by tying into QApps' aboutToQuit() signal, or maybe making a derived class from Qapp, and intercepting it, but that kind of defeats the purpose of moving away from signals/slots. Is there a simple way to tell if a QApplication has been ordered to shut down, from outside of the class?
You can reimplement
void QWidget::closeEvent ( QCloseEvent * event )
method to set your static flag. That method invokes for close events from window.
I recommend adding app.sendPostedEvents(); before that QApplication::processEvents() call. It may actually fix your problem, but if not, you can at least use event handlers as mentioned by #dzhon.
Nitpick: Qt is generally not formatted in all-caps. Saying 'QT' makes it appear as if you are talking about QuickTime!

How to force my application to open one exe only? qt, linux

I want my application to open only one process, i.e. if the one process is already opened and the user want to open the exe again - it won't open another process.
how can I do it in Qt - linux?
10x!
What you're looking for is QtSingleApplication.
If you start another instance of your application, the first one will even get notified about it (you can pass whatever data structure you want).
I used it to bring the existing application to the front whenever another instance is started.
Use the following code in the main.cpp to prevent to run more than one instance of your application. I tested this code under Linux (in QtCreator) and it works (works for Windows too). I find this solution simple and easy to implement. The example is for a console application. The code remain the same for a GUI application, check the comments in the code.
//main.cpp
#include <QCoreApplication> //Console application
//#include <QApplication> //GUI application
#include <QSharedMemory>
#include <QDebug>
//Your QMainWindow derivated class goes here :
//#include "MainWindow.h"
int main(int argc, char *argv[])
{
QCoreApplication app( argc, argv );
app.processEvents();
//---- Check for another instance code snippet ----
//GUID : Generated once for your application
// you could get one GUID here: http://www.guidgenerator.com/online-guid-generator.aspx
QSharedMemory shared("62d60669-bb94-4a94-88bb-b964890a7e04");
if( !shared.create( 512, QSharedMemory::ReadWrite) )
{
// For a GUI application, replace this by :
// QMessageBox msgBox;
//msgBox.setText( QObject::tr("Can't start more than one instance of the application.") );
//msgBox.setIcon( QMessageBox::Critical );
//msgBox.exec();
qWarning() << "Can't start more than one instance of the application.";
exit(0);
}
else {
qDebug() << "Application started successfully.";
}
//---- END OF Check for another instance code snippet ----
// Only one instance is running, declare MainWindow
//MainWindow myMainWindow;
//myMainWindow.show();
//We enter the Qt Event loop here, we don't leave until the MainWindow is closed
//or the console application is terminated.
return app.exec();
}
This may not concern you, but I thought it would be useful to bring it up. I'm using QtSingleApplication myself and experienced some odd behavior a few days ago. QtSingleApplication doesn't seem to work under all circumstances. I made this expierence in windows, but depending on wether this is a windows specific bug or intended by the design of QtSingleApplication, it may also apply to linux.
Depending on the way you start your application multiple instances are possible. I made this experience when I did a testdrive of my application using my installer. The installer automatically starts the application after finishing. When I then started my application using the desktop link, I had two instances running. So the functionality of QtSingleApplication seems to depend on the way how (and by which user?) the application is started. The documentation is unclear about this. But I think usually one would expect this to work under all circumstances, if not stated otherwise.
So, if you don't need the extra functionality added by QtSingleApplication, QSystemSemaphore or QSharedMemory seems to be the better way to go.
Your application could check if a certain file in the user's home directory is present. If it is present, the application exits. If it is not there, the application creates it and continues. Of course, you might get a race condition if the user starts the application several times at once. But for most cases this simple solution should be sufficient.