Use QSignalSpy with Microsoft::VisualStudio::CppUnitTestFramework

49 views Asked by At

I want to test whether a Qt Class correctly emits a signal upon function call using QSignalSpy. I use MS Visual Studio and use the Microsoft::VisualStudio::CppUnitTestFramework. Executing unit tests generally works fine, but instantiating a QSignalSpy yields a quite generic Failed to set up the execution context to run the test error which prevents all unit tests from executing. Compilation works fine, though.

This is the (simplified) class I want to test:

// simcam.h
#include <QtCore>

class SimCam {
    Q_OBJECT

public:
    SimCam() {};
    ~SimCam();

public slots:
    void connect() {
        emit(s_connected());
    };

signals:
    void s_connected();
};

and the unit test:

#include "CppUnitTest.h"

#include "simcam.h"

#include <QSignalSpy>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace devices_cameras_simcam_UnitTests {
    TEST_CLASS(ConnectionTests) {
public:

    TEST_METHOD(connectTest) {
        auto simcam = SimCam();

        // Problematic line
        QSignalSpy spy(&simcam, &SimCam::s_connected);

        simcam.connect();
        spy.wait();

        Assert::AreEqual(1, (int)spy.count());
    }
    };
}

I am a bit lost, how to get it to work or debug it. I didn't find any hint how to use QSignalSpy in combination with Visual Studio.

1

There are 1 answers

4
Marek R On

Basically with invocation of spy.wait(); (also other functionalities of QSignalSpy as you found out by testing) you are requesting run of event loop this means QApplication is needed.

In other test frameworks this means to provide own main function and instantiate there QApplication or QCoreApplication.

Problem is that CppUnitTestFramework uses dynamic libraries as tests suites which are loaded by some fixed tool, so you do now have access to main function.

The only choice is use initialization of module (whole test dll). I would try this (didn't test that, but should resolve issue):

#include "CppUnitTest.h"
#include <QCoreApplication>
#include <memory>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

static std::unique_ptr<QCoreApplication> myTestApplicationInstance;

TEST_MODULE_INITIALIZE(ModuleInitialize)
{
    static int argc = 1;
    static char testName[64] = "testSuiteName";
    static char *argv[2] = { testName, nullptr };

    myTestApplicationInstance = std::make_unique<QCoreApplication>(argc, argv);
}

TEST_MODULE_CLEANUP(ModuleCleanup)
{
    myTestApplicationInstance.reset();
}

Documentation of Microsoft.VisualStudio.TestTools.CppUnitTestFramework API

Test modules

TEST_MODULE_INITIALIZE(methodName)
{
    // module initialization code
}

Defines the method methodName that runs when a module is loaded. TEST_MODULE_INITIALIZE can only be defined once in a test module and must be declared at namespace scope.

TEST_MODULE_CLEANUP(methodName)

Defines the method methodName that runs when a module is unloaded. TEST_MODULE_CLEANUP can only be defined once in a test module and must be declared at namespace scope.