GoogleC++TestingFramework(簡稱gtest,http://code。google。com/p/googletest/)是Google公司發布的一個開源C/C++單元測試框架,已被應用于多個開源項目及Google內部項目中,知名的例子包括ChromeWeb瀏覽器、LLVM編譯器架構、ProtocolBuffers數據交換格式及工具等。
優秀的C/C++單元測試框架并不算少,相比之下gtest仍具有明顯優勢。與CppUnit比,gtest需要使用的頭文件和函數宏更集中,并支持測試用例的自動注冊。與CxxUnit比,gtest不要求Python等外部工具的存在。與Boost。Test比,gtest更簡潔容易上手,實用性也并不遜色。Wikipedia給出了各種編程語言的單元測試框架列表(http://en。wikipedia。org/wiki/List_of_unit_testing_frameworks)。
一、基本用法
gtest當前的版本是1。5。0,如果使用VisualC++編譯,要求編譯器版本不低于7。1(VisualC++2003)。如下圖所示,它的msvc文件夾包含VisualC++工程和項目文件,samples文件夾包含10個使用范例。
一般情況下,我們的單元測試代碼只需要包含頭文件gtest。h。gtest中常用的所有結構體、類、函數、常量等,都通過命名空間testing訪問,不過gtest已經把最簡單常用的單元測試功能包裝成了一些帶參數宏,因此在簡單的測試中常??梢院雎悦臻g的存在。
按照gtest的叫法,宏TEST為特定的測試用例(TestCase)定義了一個可執行的測試(Test)。它接受用戶指定的測試用例名(一般取被測對象名)和測試名作為參數,并劃出了一個作用域供填充測試宏語句和普通的C++代碼。一系列TEST的集合就構成一個簡單的測試程序。
常用的測試宏如下表所示。以ASSERT_開頭和以EXPECT_開頭的宏的區別是,前者在測試失敗時會給出報告并立即終止測試程序,后者在報告后繼續執行測試程序。
寫個簡單的測試試一下。假設我們實現了一個加法函數:
對應的單元測試程序可以這樣寫:
代碼中,測試用例Add包含兩個測試,正數和負數(這里利用了VisualC++2005以上允許標識符包含Unicode字符的特性)。編譯運行效果如下:
在控制臺界面中,通過的測試用綠色表示,失敗的測試用紅色表示。雙橫線分隔了不同的測試用例,其中包含的每個測試的啟動與結果用單橫線和RUN。。。OK或RUN。。。FAILED標出。失敗的測試會打印出代碼行和原因,測試程序最后為所有用例和測試顯示統計結果。建議讀者試一下換成ASSERT_宏的不同之處。
每個測試宏還可以使用<<運算符在測試失敗時輸出自定義信息,如:
編譯命令行中,gtest_mt。lib和gtest_main_mt。lib就是前面使用VC項目文件生成的靜態庫。有意思的是,測試代碼不需要注冊測試用例,也不需要定義main函數,這是gtest通過后一個靜態庫自動完成的,它的實現代碼如下:
其中,函數InitGoogleTest負責注冊需要運行的所有測試用例,宏RUN_ALL_TEST負責執行所有測試,如果全部成功則返回0,否則返回1。當然,我們也可以僅鏈接gtest_mt。lib,自己提供main函數。
二、測試固件
很多時候,我們想在不同的測試執行前創建相同的配置環境,在測試執行結束后執行相應的清理工作,測試固件(TestFixture)為這種需求提供了方便。“Fixture”是一個漢語中不易直接對應的詞,《美國傳統詞典》對它的解釋是“(作為附屬物的)固定裝置;被固定的狀態”。在單元測試中,Fixture的作用是為測試創建輔助性的上下文環境,實現測試的初始化和終結與測試過程本身的分離,便于不同測試使用相同代碼來搭建固定的配置環境。用體操比賽的說法,測試過程體現了特定測試的自選動作,測試固件則體現了對一系列測試(在開始和結束時)的規定動作。有些講單元測試的書籍直接把測試固件稱為Scaffolding(腳手架)。
使用測試固件比單純調用TEST宏稍微麻煩一些:
1、從gtest的testing::Test類派生一個類,用public或protected定義以下所有成員。
2、(可選)建立環境:使用默認構造函數,或定義一個虛成員函數virtualvoidSetUp()。
3、(可選)銷毀環境:使用析構函數,或定義一個虛成員函數virtualvoidTearDown()。
4、用TEST_F定義測試,寫法與TEST相同,但測試用例名必須為上面定義的類名。
每個帶固件的測試的執行順序是:
1、調用默認構造函數創建一個新的帶固件對象。
2、立即調用SetUp函數。
3、運行TEST_F體。
4、立即調用TearDown函數。
5、調用析構函數銷毀類對象。
從gtest的實現代碼可以看到,TEST_F又從用戶定義的類自動派生了一個類,因此要求public或protected的訪問權限;大括號里的內容被擴展成一個名為TestBody的虛成員函數的函數體,因此可以在其中直接訪問成員變量和成員函數。其實TEST也采用了相同的實現機制,只是它直接從gtest的testing::Test自動派生類,所以可以指定任意用例名。testing::Test類的SetUp和TearDown都是空函數,所以它只執行測試步驟,沒有環境的創建和銷毀。
原文轉自:http://www.anti-gravitydesign.com