當 Qt 碰上 Google Test

Qt 原本就已經提供了 QTest 可以用來開發單元測試,但整體感覺還是沒有 google test 完整,因此實務上我們還是使用 google test 來進行單元測試。

Google test 搭配 Qt 一般來說有二點要處理:
1. Qt Signal
2. Event Loop

Qt Signal

因為你的 slots 沒辦法用 MOCK_METHOD 製造出來,或著說QObject::connect 無法連結到 MOCK_METHOD 做出來的偽slot ([苦主](https://groups.google.com/forum/#!topic/googlemock/RTgynKPa6ew))
因此,最好的方式仍舊是搭配 QTestLib 裡頭的 QSignalSpy 使用([前輩已經說過了](http://stackoverflow.com/questions/22390208/google-test-mock-with-qt-signals))。
QSignalSpy 可以幫助你檢查某個 signal 被 emitted 的次數,以及它每次 emit 所帶回的參數是什麼,算是蠻方便的:

QCheckBox *box = new QCheckBox(0);
QSignalSpy spy(box, SIGNAL(clicked(bool)));
box->animateClick();
EXPECT_EQ(1, spy.count())
QList<QVariant> arguments = spy.takeFirst();
EXPECT_TRUE(arguments.at(0).toBool());

不過,在用QSignalSpy的時侯要想一下,你有 event loop 嗎?不是每個unit test都像範例這麼單純的,如果你串起來不會動,就想想 event loop 吧 :)

Event Loop
因為許多功能都必需有 Qt 的 event loop 才能運作,因此勢必要呼叫 QCoreApplication::exec() 才能跑。那麼這個原本都是放在main()裡頭的 QCoreApplication::exec() 現在要放在那裡呢?當然就是放在每個 test case 之中了。

這邊的範例是我會呼叫 trackEvent() 功能,並等待 signal TrackEventFinished 回來時再離開 event loop:

TEST_F(PluginMixPanelFixture, Send_1_Event_With_Extra_Properties)
{
**int argc = 0;
QCoreApplication app(argc, NULL);**
auto conn = std::make_shared<QMetaObject::Connection>();
*conn = QObject::connect(pTestingPlugin, &PluginMixPanelClient::TrackEventFinished, [ = ]()
{
QCoreApplication::quit();
});

QString event = "[test] login function with extra properties";
static QVariantMap property;
property.insert("prop_size", 1000);
property.insert("prop_alias", "diro");
pTestingPlugin->TrackEvent(event, property);
**app.exec();**
QObject::disconnect(*conn);
}

Previous
Next Post »