Embedding the server
veriCue works by embedding a small TCP server into the application under test. This page covers wiring it into your build, configuring authentication and licensing, and - importantly - keeping it out of your production binaries.
Just evaluating?
To try veriCue against an existing Qt binary without touching your build at all, use vericue-inject - it starts the server inside an unmodified app via LD_PRELOAD (Linux, evaluation only). Embedding, below, is the production path.
1. Link the library
With the veriCue SDK installed (see Installation), add to your CMakeLists.txt:
find_package(vericue REQUIRED)
target_link_libraries(my-app PRIVATE vericue::vericue-server)If CMake can't find the package, point it at the install prefix:
cmake -B build -DCMAKE_PREFIX_PATH="/usr/local;/path/to/Qt/6.7/gcc_64"2. Start the server
Create a VeriCueServer after your main window exists and start it:
#include <vericue/server.h>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
window.setObjectName("MainWindow");
// ... build your UI ...
vericue::VeriCueServer server(&window); // parented - cleaned up with the window
if (!server.start(4242)) {
qWarning("veriCue server failed to start");
}
window.show();
return app.exec();
}Notes:
start(0)lets the OS pick a free port; read it back withserver.serverPort(). Useful for parallel CI jobs - print it to stdout so the test harness can discover it (the bundled test app printsVERICUE_PORT=<port>).- The constructor takes an optional
QObject*parent. Parenting to your main window ties the server's lifetime to the UI. started()/stopped()/errorOccurred(QString)signals are available if you want to log or react to lifecycle events.- Works for QWidget and QML applications alike. For QML, use a build of the server library with Qt Quick support (auto-detected at build time).
3. Name your objects
Clients address objects by path, e.g. MainWindow/centralWidget/okButton. Path segments use QObject::objectName(), falling back to ClassName#N for unnamed objects. Unnamed-object paths break when the UI changes, so:
okButton->setObjectName("okButton");Give stable objectNames to every widget you intend to automate. In QML, set the objectName property.
4. Authentication
server.setAuthToken(qEnvironmentVariable("MYAPP_VERICUE_TOKEN"));When a token is set, clients must present it during the handshake; connections with a missing or wrong token are rejected. Read the token from the environment or a config file - don't hardcode secrets.
5. Licensing
Without any license configuration the server runs in 30-day trial mode. For licensed use, pick one:
// Organization license: RSA-signed JSON key file (from your license email / portal)
server.setLicenseFile("/etc/myapp/vericue-license.json");
// Floating: lease a session from your self-hosted LAN license server
server.setLicenseServer("licenses.internal.example.com", 5252);Licensing is fully offline - the server never phones home. Session accounting differs by mode: with an organization key file (or trial), each connected client occupies one concurrent automation session while connected; with a floating license, the application process checks out one lease from the pool at start() and holds it (with heartbeats) until it exits. When a license expires (trial or paid), the server keeps answering handshake, ping and version but refuses everything else. See Trial & paid tiers.
6. Compile it out of release builds
The veriCue server is a test-time tool. Don't ship it in production binaries: it opens a TCP port into your application's internals. The recommended pattern is a dedicated build option:
option(ENABLE_VERICUE "Embed the veriCue automation server" OFF)
if(ENABLE_VERICUE)
find_package(vericue REQUIRED)
target_link_libraries(my-app PRIVATE vericue::vericue-server)
target_compile_definitions(my-app PRIVATE MYAPP_WITH_VERICUE)
endif()#ifdef MYAPP_WITH_VERICUE
#include <vericue/server.h>
#endif
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
// ...
#ifdef MYAPP_WITH_VERICUE
vericue::VeriCueServer server(&window);
server.setAuthToken(qEnvironmentVariable("MYAPP_VERICUE_TOKEN"));
server.start(4242);
#endif
window.show();
return app.exec();
}Your QA/CI builds configure with -DENABLE_VERICUE=ON; release builds don't reference veriCue at all - no linked library, no open port, nothing to audit in the shipped artifact.
Security model
Be deliberate about where the automation port is reachable:
- The server listens on all network interfaces - there is currently no bind-address option. On a developer machine or CI runner that's usually fine; on a shared network it means anyone who can reach the port can drive your application.
- Transport is plaintext TCP (length-prefixed JSON). There is no TLS. Treat the port like a local debug interface, not a network service.
- A connected client can read widget contents, click anything, invoke methods and take screenshots - full control of the UI.
Recommendations, in order of importance:
- Only embed in test builds (compile-out pattern above). The strongest control is the port not existing.
- Always set an auth token outside single-developer machines.
- Firewall the port to localhost or the CI subnet.
- For remote debugging across machines, tunnel instead of exposing:
ssh -L 4242:localhost:4242 testrigand connect tolocalhost. - Never expose the port on an untrusted or public network.

