Google TestExtending Google Test by Handling Test Events
Google測試提供了一個事件偵聽器API,讓您接收有關測試程序進度和測試失敗的通知。 可以監聽的事件包括測試程序的開始和結束,測試用例或測試方法等。 您可以使用此API來擴充或替換標准控制台輸出,替換XML輸出,或提供完全不同的輸出形式,例如GUI或數據庫。 例如,您還可以使用測試事件作為檢查點來實現資源泄漏檢查器。
一、定義事件偵聽器
要定義一個事件監聽器,你需要繼承testing :: TestEventListener或testing :: EmptyTestEventListener。前者是一個(抽象)接口,其中每個純虛方法
可以重寫以處理測試事件(例如,當測試開始時,將調用OnTestStart()方法。)。后者提供了接口中所有方法的空實現,使得子類只需要覆蓋它關心的方法。
當一個事件觸發時,它的上下文作為參數傳遞給處理函數。使用以下參數類型:
- UnitTest反映整個測試程序的狀態,
- TestCase包含關於一個測試用例的信息,它可以包含一個或多個測試,
- TestInfo包含測試的狀態,和
- TestPartResult表示測試斷言的結果。
事件處理函數可以檢查它接收的參數,以找到關於事件和測試程序狀態的有趣信息。這里有一個例子:
class MinimalistPrinter : public ::testing::EmptyTestEventListener { // Called before a test starts. virtual void OnTestStart(const ::testing::TestInfo& test_info) { printf("*** Test %s.%s starting.\n", test_info.test_case_name(), test_info.name()); } // Called after a failed assertion or a SUCCEED() invocation. virtual void OnTestPartResult( const ::testing::TestPartResult& test_part_result) { printf("%s in %s:%d\n%s\n", test_part_result.failed() ? "*** Failure" : "Success", test_part_result.file_name(), test_part_result.line_number(), test_part_result.summary()); } // Called after a test ends. virtual void OnTestEnd(const ::testing::TestInfo& test_info) { printf("*** Test %s.%s ending.\n", test_info.test_case_name(), test_info.name()); } };
二、使用事件監聽器
要使用您定義的事件偵聽器,請將其實例添加到Google Test事件偵聽器列表中(由TestEventListeners類表示)
- note the "s" at the end of the name) in your
main()
function, before callingRUN_ALL_TESTS()
:
int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); // Gets hold of the event listener list. ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners(); // Adds a listener to the end. Google Test takes the ownership. listeners.Append(new MinimalistPrinter); return RUN_ALL_TESTS(); }
只有一個問題:默認測試結果打印機仍然有效,因此其輸出將與您的簡約打印機的輸出混合。 要禁止默認打印機,只需從事件偵聽器列表中釋放它並刪除它。 您可以添加一行:
... delete listeners.Release(listeners.default_result_printer()); listeners.Append(new MinimalistPrinter); return RUN_ALL_TESTS();
現在,坐下來享受與你的測試完全不同的輸出。 有關更多詳細信息,您可以閱讀此示例 sample(sample9_unittest)。
您可以向列表附加多個偵聽器。 當On * Start()或OnTestPartResult()事件觸發時,監聽器將按它們在列表中顯示的順序接收它(因為新的監聽器添加到列表的末尾,默認文本打印機和默認XML生成器 將第一時間接收事件)。 An On * End()事件將由偵聽器以相反的順序接收。 這允許稍后添加的偵聽器的輸出由之前添加的偵聽器的輸出構成。
三、Generating Failures in Listeners
在處理事件時,可以使用故障提升宏(EXPECT _ *(),ASSERT _ *(),FAIL()等)。 有一些限制:
- 你不能在OnTestPartResult()中產生任何失敗(否則會導致OnTestPartResult()被遞歸調用)。
- 處理OnTestPartResult()的偵聽器不允許生成任何失敗。
當您向偵聽器列表添加偵聽器時,應該在可能生成失敗的偵聽器之前放置處理OnTestPartResult()的偵聽器。 這確保由后者產生的故障歸因於前者的正確測試。
我們在這里有一個失敗監聽器的示例here(sample10_unittest)。
四、TestEventListener接口
// The interface for tracing execution of tests. The methods are organized in // the order the corresponding events are fired. class TestEventListener { public: virtual ~TestEventListener() {} // Fired before any test activity starts. virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; // Fired before each iteration of tests starts. There may be more than // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration // index, starting from 0. virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration) = 0; // Fired before environment set-up for each iteration of tests starts. virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; // Fired after environment set-up for each iteration of tests ends. virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; // Fired before the test case starts. virtual void OnTestCaseStart(const TestCase& test_case) = 0; // Fired before the test starts. virtual void OnTestStart(const TestInfo& test_info) = 0; // Fired after a failed assertion or a SUCCEED() invocation. virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; // Fired after the test ends. virtual void OnTestEnd(const TestInfo& test_info) = 0; // Fired after the test case ends. virtual void OnTestCaseEnd(const TestCase& test_case) = 0; // Fired before environment tear-down for each iteration of tests starts. virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; // Fired after environment tear-down for each iteration of tests ends. virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; // Fired after each iteration of tests finishes. virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) = 0; // Fired after all test activities have ended. virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; }; // The convenience class for users who need to override just one or two // methods and are not concerned that a possible change to a signature of // the methods they override will not be caught during the build. For // comments about each method please see the definition of TestEventListener // above.一個空實現 class EmptyTestEventListener : public TestEventListener { public: virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, int /*iteration*/) {} virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} virtual void OnTestStart(const TestInfo& /*test_info*/) {} virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} virtual void OnTestEnd(const TestInfo& /*test_info*/) {} virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, int /*iteration*/) {} virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} };
五、官方例子
就是samples文件夾下的sample10_unittest.cpp
// This sample shows how to use Google Test listener API to implement // a primitive leak checker. #include "stdafx.h" using ::testing::EmptyTestEventListener; using ::testing::InitGoogleTest; using ::testing::Test; using ::testing::TestCase; using ::testing::TestEventListeners; using ::testing::TestInfo; using ::testing::TestPartResult; using ::testing::UnitTest; namespace { // We will track memory used by this class. class Water { public: // Normal Water declarations go here. // operator new and operator delete help us control water allocation. void* operator new(size_t allocation_size) { allocated_++; return malloc(allocation_size); } void operator delete(void* block, size_t /* allocation_size */) { allocated_--; free(block); } static int allocated() { return allocated_; } private: static int allocated_; }; int Water::allocated_ = 0; // This event listener monitors how many Water objects are created and // destroyed by each test, and reports a failure if a test leaks some Water // objects. It does this by comparing the number of live Water objects at // the beginning of a test and at the end of a test. class LeakChecker : public EmptyTestEventListener { private: // Called before a test starts. virtual void OnTestStart(const TestInfo& /* test_info */) { initially_allocated_ = Water::allocated(); } // Called after a test ends. virtual void OnTestEnd(const TestInfo& /* test_info */) { int difference = Water::allocated() - initially_allocated_; // You can generate a failure in any event handler except // OnTestPartResult. Just use an appropriate Google Test assertion to do // it. EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!"; } int initially_allocated_; }; TEST(ListenersTest, DoesNotLeak) { Water* water = new Water; delete water; } // This should fail when the --check_for_leaks command line flag is // specified. TEST(ListenersTest, LeaksWater) { Water* water = new Water; EXPECT_TRUE(water != NULL); } } // namespace int main(int argc, char **argv) { InitGoogleTest(&argc, argv); bool check_for_leaks = false; if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0) check_for_leaks = true; else printf("%s\n", "Run this program with --check_for_leaks to enable " "custom leak checking in the tests."); // If we are given the --check_for_leaks command line flag, installs the // leak checker. if (check_for_leaks) { TestEventListeners& listeners = UnitTest::GetInstance()->listeners(); // Adds the leak checker to the end of the test event listener list, // after the default text output printer and the default XML report // generator. // // The order is important - it ensures that failures generated in the // leak checker's OnTestEnd() method are processed by the text and XML // printers *before* their OnTestEnd() methods are called, such that // they are attributed to the right test. Remember that a listener // receives an OnXyzStart event *after* listeners preceding it in the // list received that event, and receives an OnXyzEnd event *before* // listeners preceding it. // // We don't need to worry about deleting the new listener later, as // Google Test will do it. listeners.Append(new LeakChecker); } return RUN_ALL_TESTS(); }