Automatic Qt gui testing with Hooq – getting it to compile and work

I need to write some automatic tests of a Qt program I have written.

I stumbled upon the Hooq system to script these things. For some reason the images are missing in my end. If you look through the discussion at the end, you will se that a lot of people have trouble gettuing hooq to record anything on their applications. I did to, this post describes how I got it to work.

I downloaded the source using:

git clone https://git.gitorious.org/hooq/hooq.git.

I am running Kubuntu 11.4, and I needed to apply the following patch, heavily inspired by the source here, to make it work:

diff --git a/hooqInjector/GdbInjector.cpp b/hooqInjector/GdbInjector.cpp
index a390601..9668926 100644
--- a/hooqInjector/GdbInjector.cpp
+++ b/hooqInjector/GdbInjector.cpp
@@ -92,27 +92,28 @@ void GdbInjector::startProcess()
Q_ASSERT(m_gdb->state() == QProcess::Running);
Q_ASSERT(m_gdb->isWritable());
m_gdbStream.setDevice(m_gdb);
-       m_gdbStream << "set auto-solib-add off" << endl; // avoid loading symbols for shared libraries
-                                                        // that we do not need to interact with from GDB
-       m_gdbStream << "break _start" << endl; // C entry point - after main libraries have been loaded
-       m_gdbStream << "set args" << argumentsString << endl;
-       m_gdbStream << "run" << endl; // run until we hit it, and therefore Qt shared libraries are loaded
-       m_gdbStream << "sharedlibrary libdl" << endl; // load the libdl library so that we can call __dlopen()
-       m_gdbStream << "sharedlibrary libc" << endl;  // load the libc library so that we can call __dlopen()
-       m_gdbStream << "sharedlibrary libQtCore" << endl; // load QtCore for breaking on QCoreApplication::exec()
-       m_gdbStream << "break QCoreApplication::exec()" << endl; // now, we can set this breakpoint...
-       m_gdbStream << "continue" << endl;
-
-       // Newer systems
-       m_gdbStream << QString("call dlopen(\"%1\", %2)").arg(libraryPath()).arg(QString::number(RTLD_NOW)) << endl; // load our library
-       // Older systems
-       m_gdbStream << QString("call __dlopen(\"%1\", %2)").arg(libraryPath()).arg(QString::number(RTLD_NOW)) << endl; // load our library
-
-       m_gdbStream << "sharedlibrary injectedHooq" << endl; // load the hooq injector library so that we can call startHooq()
-       m_gdbStream << "call startHooq()" << endl; // install our plugin (which required QCoreApplication setup)
-       m_gdbStream << "continue" << endl; // run the app
-       m_gdbStream << "backtrace" << endl; // just in case (use with --spam)
-       m_gdbStream << "quit" << endl; // after the application has exited, quit gdb
+        m_gdbStream << "set breakpoint pending on" << endl;
+        m_gdbStream << "set auto-solib-add off" << endl; // avoid loading symbols for shared libraries
+                                                         // that we do not need to interact with from GDB
+        m_gdbStream << "break _start" << endl; // C entry point - after main libraries have been loaded
+        m_gdbStream << "set args" << argumentsString << endl;
+        m_gdbStream << "run" << endl; // run until we hit it, and therefore Qt shared libraries are loaded
+        m_gdbStream << "sharedlibrary libdl" << endl; // load the libdl library so that we can call __dlopen()
+        m_gdbStream << "sharedlibrary libc" << endl;  // load the libc library so that we can call __dlopen()
+        //m_gdbStream << QString("call dlopen(\"/usr/lib64/libQtCore.so.4\",%1)").arg(QString::number(RTLD_NOW)) << endl;
+        // Newer systems
+        m_gdbStream << QString("call dlopen(\"%1\", %2)").arg(libraryPath()).arg(QString::number(RTLD_NOW)) << endl; // load our library
+        // Older systems
+        m_gdbStream << QString("call __dlopen(\"%1\", %2)").arg(libraryPath()).arg(QString::number(RTLD_NOW)) << endl; // load our library
+        m_gdbStream << "sharedlibrary libQtCore" << endl; // load QtCore for breaking on QCoreApplication::exec()
+        m_gdbStream << "sharedlibrary libQtGui" << endl; // load QtCore for breaking on QCoreApplication::exec()
+        m_gdbStream << "break QCoreApplication::exec" << endl; // now, we can set this breakpoint...
+        m_gdbStream << "continue" << endl;
+        m_gdbStream << "sharedlibrary injectedHooq" << endl; // load the hooq injector library so that we can call startHooq()
+        m_gdbStream << "call startHooq()" << endl; // install our plugin (which required QCoreApplication setup)
+        m_gdbStream << "continue" << endl; // run the app
+        m_gdbStream << "backtrace" << endl; // just in case (use with --spam)
+        m_gdbStream << "quit" << endl; // after the application has exited, quit gdb
}

void GdbInjector::attach(Q_PID processId)

Now, you also make *sure* that your have the Qt library debug symbols installed on your system. I had to do:

sudo apt-get install libqt4-dbg

and then recompile both my app and hooq for it to work.

Then it just worked, and hooq recorded events, and so on. Whether this system works to my full satisfaction remains to be seen.

Advertisement

About madsdyd
Software developer, linux guy, hacker, all that.

2 Responses to Automatic Qt gui testing with Hooq – getting it to compile and work

  1. Shiqi Yang says:

    Hey there, glad my post is helpful to you!

    Shiqi

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.