Testing qt4 applicationswith slots and signals
A few days ago someone said something1 that reminded me about my audio player, which I had abandoned for more than a year already. The reason was mostly that the two Phonon backends, VLC and gstreamer, for some reason or other couldn't play the files I had without any gaps between songs.
To be honest, the first bug end up being me not properly encoding the filenames.
If you first URL-encoded the filename and then built a Q/KURL with that, then
it's all fine. It took me more than 12 months and a few rereads of the thread
to realize it. Fixes apart, it seems that the bug still exists for other
instances of gstreamer errors, so we're not out of the woods. In any case, I
switched to the VLC backend and it seems that now is able to fire the
aboutToFinnish()
signal properly, so for the moment I'm using that.
All that is fine, but that's not what I wanted to talk about in this post. Given
that this project largely precedes my interest on testing, it has no testing at
all. Most of the project is straightforward enough to almost no need any, but
there's a critic part that would not suffer at all if it had any, namely the
Collection
s handling, including passing files from one to another and
automatically updating new/removed Song
s2.
So after fixing the bug mentioned above I tried to figure out the current state
of affaires regarding Collection
s, and boy, they're in bad shape. The code was
locally modified, never commited, deactivating any notifications of filesystem
changes (new or removed files), and other code I can't really understand the
purpose of.
Because if this last detail is that I decided to start testing three classes:
Collection
, which handles a set a Song
s with a common root directory;
CollectionAggregator
, which handles a set of collections and should coordinate
moving a Song
from one Collection
to another; and CollectionIndexer
, which scans
from a Collection
's root dir to find Song
s.
All went fine while I tested the first class, Collection. There was a tricky
part where I had to setup a QApplication
in order to make signals work. The
problems began when I started testing CollectionIndexer
. Tests started blocking
endlessly, signals stopped being either emited or firing the connected slots,
life was bad.
I tried to search the available documentation and mailing lists for a hint about the problem, but besides a quite complex example that didn't seem to properly converge to anything useful, I was mostly on my own.
This morning I got my eureka moment: I noticed that if I executed each test class
by itself, it worked, but both at the same time blocked and never finished. Then
I remembered something said in
QApplication
's documentation:
For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.
That was it: I was creating the application, first in the setUp()
method, then
as a class attribute, but I had one test class per class to test, each in its
own file. Somehow this last fact lead me to think that somehow they were executed
in separate processes, which is not true. Luckily, even with this limitation, there's
none on the amount of times you can exec_()
and quit()
the same instance, so
that's what I did: I created only one instance and reused it everywhere. I was
already doing that for each test method, but again, somehow having several files
mislead me to think they were isolated from each other.
So now all my unit tests work without mysteriously blocking forever. Now I just
hope I can keep riding the success wave and bring satyr
into good shape. A new
release wouldn't hurt.