Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Mixing QT with Google Test
Forum Updated to NodeBB v4.3 + New Features

Mixing QT with Google Test

Scheduled Pinned Locked Moved Unsolved General and Desktop
3 Posts 3 Posters 2.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JuliusCaesar
    wrote on last edited by
    #1

    Hey guys,
    I'm using QT with google test.
    Some of my functions to test involve signals and slots (like Bluetooth in my case).
    However teese do no seam to work in GTEST

    The basic setup

    My class QT_BT_ExampleScan should perform a scan for available bluetooth devices in the background => that's why it's running in it's own thread.

    class QT_BT_ExampleScan : public QThread
    {
    Q_OBJECT
    public:
    QT_BT_ExampleScan ();
    
     private:
      std::unique_ptr<QBluetoothDeviceDiscoveryAgent> m_pDeviceDiscoveryAgent;
    
      void run() override;
       public slots:
       void addDevice(const QBluetoothDeviceInfo&);
    };
    
    QT_BT_ExampleScan ::QT_BT_ExampleScan ();
    {
       m_pDeviceDiscoveryAgent = std::make_unique<QBluetoothDeviceDiscoveryAgent>();
        if (!connect(m_pDeviceDiscoveryAgent.get(), SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
          this, SLOT(addDevice(QBluetoothDeviceInfo))))
        {
          qWarning() << "Failed to connect";
        }
    }
    
    void QT_BT_ExampleScan ::run()
      {
         startDeviceDiscovery();
          int iRes = exec();
          qDebug() << "Thread " << currentThreadId() << " finnished with result " << iRes;
      }
    
     void QT_BT_ExampleScan::addDevice(const QBluetoothDeviceInfo& info)
      {
        qDebug() << "Adding device " << info.name();
        QBluetoothLocalDevice::Pairing pairingStatus = m_pLocalBluetoothDevice->pairingStatus(info.address());
        if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired)
        {
          qDebug() << "Device with address" << info.address() << "already paired";
        }
        else
        {
          qDebug() << "Device with address " << info.address() << "not yet paired";
        }
      }
    
    

    1) In the GTest case it is called via

    int main(int argc, char* argv[])
    {
    
      ::testing::InitGoogleTest(&argc, argv);
      QGuiApplication app(argc, argv);
    
      int res = RUN_ALL_TESTS();
      return  res;
    
    }
    
    

    with fixture

    class TestBluetooth : public ::testing::Test
    {
    public:
    
    };
    
    TEST_F(TestBluetooth, BT_QT_Example)
    {
      auto pThread = std::make_unique<QT_BT_ExampleScan>();
      pThread->start();
      const auto sleepTime = 20s;
      std::this_thread::sleep_for(sleepTime);
    }
    

    However in this case, no QT events are fired/received.

    2) Modification of the main()

    int main(int argc, char* argv[])
    {
    
      ::testing::InitGoogleTest(&argc, argv);
    
      QGuiApplication app(argc, argv);
      QT_BT_ExampleScan test;
      test.start();
      return app.exec();
    }
    
    

    This here fires up events nicely. However Gtest is not running any longer.

    Problem assumption for 1) case

    =>for signals/slots the eventloop must be running. This only seams to be triggers by

    QGuiApplication app(argc, argv);
    app.exec()
    

    =>My Idea how to solve this:

    => Keep calling app.exec() but move GTest to a separate thread.

    int main(int argc, char* argv[])
    {
    ::testing::InitGoogleTest(&argc, argv);
    QGuiApplication app(argc, argv);
      auto pGTestThread = std::make_unique<GTestThread>();
      return app.exec();
    }
    
    class GTestThread : protected QThread
    {
    public:
      explicit GTestThread();
    
      ~GTestThread();
    
    private:
      void run() override;
    };
    
    GTestThread::GTestThread()
    {
      start();
    }
    
    GTestThread::~GTestThread()
    {
      if (isRunning())
      {
        exit(0);
        wait();
      }
    }
    
    void GTestThread::run()
    {
      RUN_ALL_TESTS();
    }
    
    

    However this does not work either. GTest is running but no signals/slots are working again.
    Do you know why? The eventloop should be up by the end of main(). Why are no events fired?

    could you help me out here?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Ccyros
      wrote on last edited by Ccyros
      #2

      I got that running with the following :

      // Test fixture for setting up Qt event loop
      class QtTest : public ::testing::Test {
      protected:
          void SetUp() override {
              int argc = 0;
              char **argv = nullptr;
              app = new QCoreApplication(argc, argv);
          }
      
          void TearDown() override {
              delete app;
          }
      
          QCoreApplication *app;
      };
      
      
      TEST_F(QtTest, SignalSlotTest) {
          MyClass sender;
          MyClass receiver;
      
          QObject::connect(&sender, &MyClass::mySignal, &receiver, &MyClass::mySlot);
      
          int testValue = 42;
          emit sender.mySignal(testValue);
      
          // Process Qt events to ensure signal delivery
          QCoreApplication::processEvents();
      
          EXPECT_EQ(receiver.lastValue(), testValue);
      }
      

      with test class MyClass.h :

      class MyClass : public QObject
      {
          Q_OBJECT
      
      public:
          explicit MyClass(QObject *parent = nullptr);
      
      signals:
          void mySignal(int value);
      
      public slots:
          void mySlot(int value);
      
          int lastValue() const;
      
      private:
          int m_lastValue;
      };
      

      MyClass.cpp :

      MyClass::MyClass(QObject *parent) : QObject(parent), m_lastValue(0)
      {
      }
      
      void MyClass::mySlot(int value)
      {
          m_lastValue = value;
      }
      
      int MyClass::lastValue() const
      {
          return m_lastValue;
      }
      
      1 Reply Last reply
      0
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Or simply use qWait/qWaitFor() instead QCoreApplication::processEvents()

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved