1. 程式人生 > 其它 >Visual Studio測試工具整合GoogleTest和Qt

Visual Studio測試工具整合GoogleTest和Qt

Visual Studio 的測試管理工具雖然集成了 Google Test 測試框架,但缺少 QtTest 測試框架的支援,所以需要在 Google Test 整合 Qt 框架完成單元測試。

背景介紹

因為程式碼中不免需要編寫單元測試,而且可能一個 VC 專案中帶有若干個測試用例,這時難免有執行除錯其中一個測試用例。
雖然 Visual Studio 本身有測試管理工具(Test Explorer),但目前官方維護和支援的測試框架[1]只有 Google Test 、Boost Test 和 MS CppUnit Test Framework。
所以,採用簡單的解決方案是在 Google Test 測試框架基礎上,使其支援 Qt 框架。

問題描述

  1. 如何讓 Google Test 執行在 Qt 的事件迴圈中?
  2. 如何使 Visual Studio 的測試管理工具(環境變數)能正常執行?

測試環境

  • Visual Studio 2019 Community
  • Test Adapter for Google Test[2]
  • Qt VS Tools[3]
  • Qt 5.15.2 ( msvc2019_64 )

建立專案

建立“Qt Core Application”專案,在 Qt Modules 中選擇 CoreTest

完成專案建立後,右鍵 Manage NuGet Packages...,搜尋並引入 GoogleTest 測試框架,NuGet 包名 是 Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn

右鍵專案“Properties > Referenced Packages > Google Test”,設定 Use Google Test's main FunctionNo。因為我們需要手動編寫 main 函式,以便 Google Test 能夠正常啟動 Qt 事件迴圈。

建立簡單的測試啟動類

修改 main.cpp,使 Google Test 執行在事件迴圈中。

int main(int argc, char* argv[])
{
	QCoreApplication a(argc, argv);

	::testing::InitGoogleTest(&argc, argv);
	QTimer::singleShot(0, []() { QCoreApplication::exit(RUN_ALL_TESTS()); });

	return a.exec();
}

編寫測試單元

結合 QtTest [4]簡單寫了 QString::toUpper 方法的單元測試。

namespace QStringTests
{
	TEST(toUpper, AllLower)
	{
		QString string = "hello";
		EXPECT_EQ("HELLO", string.toUpper());
	}

	TEST(toUpper, Mixed)
	{
		QString string = "Hello";
		EXPECT_EQ("HELLO", string.toUpper());
	}

	TEST(toUpper, AllUpper)
	{
		QString string = "HELLO";
		EXPECT_EQ("HELLo", string.toUpper()); // failed
	}
}

編譯執行後,可以看到類似的執行結果。

[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from toUpper
[ RUN      ] toUpper.AllLower
[       OK ] toUpper.AllLower (0 ms)
[ RUN      ] toUpper.Mixed
[       OK ] toUpper.Mixed (0 ms)
[ RUN      ] toUpper.AllUpper
D:\repos\TestQString\TestQString.cpp(21): error: Expected equality of these values:
  "HELLo"
    Which is: 00007FF6978C7A58
  string.toUpper()
    Which is: { 2-byte object <48-00>, 2-byte object <45-00>, 2-byte object <4C-00>, 2-byte object <4C-00>, 2-byte object <4F-00> }
[  FAILED  ] toUpper.AllUpper (2 ms)
[----------] 3 tests from toUpper (5 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (8 ms total)
[  PASSED  ] 2 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] toUpper.AllUpper

 1 FAILED TEST

D:\repos\TestQString\x64\Debug\TestQString.exe (process 6740) exited with code 1.

掃描測試用例

開啟選單“View > Test Explorer”,會多出測定管理工具,但是執行掃描不出意外會出現錯誤,因為掃描程式執行其實沒有設定 Qt 的環境變數。

設定單元測試執行環境

Visual Sutdio 測試工具按照專案配置執行環境[5]

在當前專案目錄下建立檔案 Qt.x64.runsettings

<!--?xml version="1.0" encoding="utf-8"?-->
<runsettings>
  <runconfiguration>
    <environmentvariables>
      <path>%PATH%;C:/Qt/5.15.2/msvc2019_64/bin</path>
    </environmentvariables>
  </runconfiguration>
</runsettings>

解除安裝專案(Unload),並編輯專案,新增屬性(PropertyGroup)。

<propertygroup>
    <runsettingsfilepath>$(MSBuildProjectDirectory)\Qt.$(Platform).runsettings</runsettingsfilepath>
</propertygroup>

重新開啟專案,並且 Rebuild 後,可以在 Test Explorer 視窗中看到剛才宣告的單元測試列表,並且可以針對若干個特定單元進行執行測試。

配置T4模板檔案

通過建立 T4 模板檔案[6] 來解決 *.runsettings 的 Qt 固定路徑寫法存在問題,以此方便不同 Qt 環境切換。

重新命名 Qt.x64.runsettingsQt.runsettings.tt,並修改檔案內容。

<#@ template language="c#" hostspecific="true" #>
<#@ output extension=".runsettings" #>
<#@ parameter type="System.String" name="QtDllPath" #>
<!--?xml version="1.0" encoding="utf-8"?-->
<runsettings>
  <runconfiguration>
    <environmentvariables>
      <path>%PATH%;<#= QtDllPath #></path>
    </environmentvariables>
  </runconfiguration>
</runsettings>

解除安裝專案配置 T4 模板構建任務,編輯專案檔案內容。

-   <none include="Qt.runsettings.tt">
  
+ <itemgroup>
+   <none include="Qt.runsettings.tt">
+     <generator>TextTemplatingFileGenerator</generator>
+     <outputfilename>$(MSBuildProjectDirectory)\Qt.$(Platform).runsettings</outputfilename>
+   </none>
+   <t4parametervalues include="QtDllPath">
+     <value>$(QtDllPath)</value>
+   </t4parametervalues>
+ </itemgroup>
  <propertygroup>
    <runsettingsfilepath>$(MSBuildProjectDirectory)\Qt.$(Platform).runsettings</runsettingsfilepath>
+   <transformonbuild>true</transformonbuild>
  </propertygroup>
+ <import project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TextTemplating\Microsoft.TextTemplating.targets">

開啟專案,執行 Rebuild,如果看到如下編譯輸出,並且當前專案出現 Qt.x64.runsettings,代表生成成功。

....
1>Transforming template Qt.runsettings.tt...
....

執行截圖


  1. https://docs.microsoft.com/zh-cn/visualstudio/test/writing-unit-tests-for-c-cpp?view=vs-2019 ↩︎

  2. https://docs.microsoft.com/zh-cn/visualstudio/test/how-to-use-google-test-for-cpp?view=vs-2019 ↩︎

  3. https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019 ↩︎

  4. https://doc.qt.io/qt-5.15/qttestlib-tutorial2-example.html ↩︎

  5. https://docs.microsoft.com/zh-cn/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file?view=vs-2019 ↩︎

  6. https://docs.microsoft.com/en-us/visualstudio/modeling/writing-a-t4-text-template?view=vs-2019 ↩︎