程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)下

Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)下

編輯:關於C++

Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)下。本站提示廣大學習愛好者:(Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)下)文章只能為提供參考,不一定能成為您想要的結果。以下是Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)下正文


由於AdvancedGuide文檔太長,分上下兩局部,本文檔接googletest--AdvancedGuide(譯文)上:Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)上。

一、在子順序中運用斷言(Using Assertions in Sub-routines)

1.1 將跟蹤添加到斷言

假如從幾個中央調用測試子順序,當其中的斷言失敗時,能夠很難判別失敗來自哪個子順序的調用。 您可以運用額定的日志或自定義失敗音訊緩解這個問題,但通常會梗塞您的測試。 更好的處理方案是運用SCOPED_TRACE宏:

SCOPED_TRACE(message);

messsage可以是任何可以流入std::ostream的東西。此宏會將以後文件名、行號和給定音訊添加到每個失敗音訊中。 當控件分開以後詞法作用域時,效果將被吊銷。

For example,

 void Sub1(int n) {
   EXPECT_EQ(1, Bar(n));
   EXPECT_EQ(2, Bar(n + 1));
 }

 TEST(FooTest, Bar) {
   {
     SCOPED_TRACE("A");  // This trace point will be included in
                         // every failure in this scope.
     Sub1(1);
   }//到這SCOPED_TRACE的作用域就完畢。
   // Now it won't.
   Sub1(9);//都調用了子順序Sub1
 }

能夠會招致這樣的音訊:

path/to/foo_test.cc:11: Failure
Value of: Bar(n)
Expected: 1
  Actual: 2
   Trace:
path/to/foo_test.cc:17: A

path/to/foo_test.cc:12: Failure
Value of: Bar(n + 1)
Expected: 2
  Actual: 3

沒有跟蹤,很難知道兩個失敗辨別來自哪個Sub1()的調用。 (你可以在Sub1()中為每個斷言添加一個額定的音訊,以指示n的值,但這很有趣。)

關於運用SCOPED_TRACE的一些提示:

沒有跟蹤,很難知道兩個失敗辨別來自哪個Sub1()的調用。 (你可以在Sub1()中為每個斷言添加一個額定的音訊,以指示n的值,但這很有趣。)

關於運用SCOPED_TRACE的一些提示:

  • 運用適宜的音訊,通常足以在子例程的掃尾運用SCOPED_TRACE,而不是在每個調用站點。
  • 當調用循環內的子例程時,使循環迭代器成為SCOPED_TRACE中的音訊的一局部,以便您可以知道失敗來自哪個迭代。
  • 有時,跟蹤點的行號足以辨認子例程的特定調用。在這種狀況下,您不用為SCOPED_TRACE選擇獨一的音訊。你可以復雜地運用“”。
  • 當內部作用域中有一個SCOPED_TRACE時,可以在外部作用域中運用SCOPED_TRACE。在這種狀況下,一切活動跟蹤點將依照遇到的相反順序包括在失敗音訊中。
  • 跟蹤轉儲是可以在Emacs的編譯緩沖區中點擊 - 命中前往行號,你會被帶到源文件中的那一行!

1.2 傳達致命失敗

運用ASSERT_ *和FAIL *時的罕見圈套以為當它們失敗時,它們會中止整個測試。 例如,以下測試將會招致錯誤:

void Subroutine() {
  // Generates a fatal failure and aborts the current function.
  ASSERT_EQ(1, 2);//失敗時只是終止以後函數
  // The following won't be executed.
  ...
}

TEST(FooTest, Bar) {
  Subroutine();
  // The intended behavior is for the fatal failure
  // in Subroutine() to abort the entire test.
  // The actual behavior: the function goes on after Subroutine() returns.
  //  實踐行為:函數在Subroutine()前往後持續。
  int* p = NULL;
  *p = 3; // Segfault!發生一個錯誤
} 

由於我們不運用異常,因而在技術上不能夠在這裡完成預期的行為。 為了加重這種狀況,Google測試提供了兩種處理方案。 您可以運用(ASSERT | EXPECT)_NO_FATAL_FAILURE斷言或HasFatalFailure()函數。 它們在以下兩個大節中描繪。

1.3在子順序中的斷言(Asserting on Subroutines)

如上所示,假如你的測試調用了一個有ASSERT_ *失敗的子順序,測試將在子順序前往後持續。 這能夠不是你想要的。

通常人們希望致命的失敗傳達像異常一樣。 為此,Google測試提供以下宏:

Fatal assertionNonfatal assertionVerifies ASSERT_NO_FATAL_FAILURE(statement); EXPECT_NO_FATAL_FAILURE(statement); statement doesn't generate any new fatal failures in the current thread.

僅反省執行斷言的線程中的失敗,以確定這品種型的斷言的後果。 假如語句創立新線程,這些線程中的失敗將被疏忽。

例如:

ASSERT_NO_FATAL_FAILURE(Foo());

int i;
EXPECT_NO_FATAL_FAILURE({
  i = Bar();
}); 

1.4反省以後測試中的毛病

  :: test :: Test類中的HasFatalFailure(): 假如以後測試中的斷言遭遇致命毛病,則前往true。 這允許函數捕捉子例程中的致命毛病並及早前往。

class Test {
 public:
  ...
  static bool HasFatalFailure();
};

 典型的用法,根本上模仿拋出的異常的行為是:

TEST(FooTest, Bar) {  
    Subroutine();  // Aborts if Subroutine() had a fatal failure. 
   if (HasFatalFailure())    
     return;  
   // The following won't be executed. 
   ...
}

HasFatalFailure假如在TEST(),TEST_F()或測試夾具之外運用,則必需添加:: testing :: Test ::前綴,如: 

if (::testing::Test::HasFatalFailure())
  return;

相似的,HasNonfatalFailure():假如以後測試至多有一個非致命失敗,前往true。

HasFailure() :假如以後測試至多有一個失敗,前往true。

二、記載其他信息Logging Additional Information

在測試代碼中,可以調用RecordProperty(“key”,value)來記載附加信息,其中value可以是字符串或int。 假如指定一個鍵,則為鍵記載的最後一個值將發送到XML輸入。

例如

TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
  RecordProperty("MaximumWidgets", ComputeMaxUsage());
  RecordProperty("MinimumWidgets", ComputeMinUsage());
}

will output XML like this:

...
  <testcase name="MinAndMaxWidgets" status="run" time="6" classname="WidgetUsageTest"
            MaximumWidgets="12"
            MinimumWidgets="9" />
...

留意:

  • RecordProperty()是Test類的靜態成員。 因而,假如在TEST體和測試夾具類之外運用,則需求運用前綴:: testing :: Test ::。
  • 鍵必需是無效的XML屬性稱號,且不能與Google Test(稱號,形態,時間,類名,類型_參數和值_參數)已運用的鍵抵觸。
  • 允許在測試的生命周期之外調用RecordProperty()。 假如它在測試之外調用,但在測試用例的SetUpTestCase()和TearDownTestCase()辦法之間調用,它將被歸因於測試用例的XML元素。 假如在一切測試用例之外調用(例如在測試環境中),它將被歸因於頂級XML元素。

三、在同一測試用例中的測試之間共享資源

Google Test為每個測試創立一個新的測試夾具對象,以使測試獨立,更容易調試。 但是,有時測試運用昂貴的資源設置,使得單拷貝測試模型過於昂貴。

假如測試不更改資源,則它們在共享單個資源正本中沒有任何危害。 因而,除了每次測試的set-up/tear-down,Google測試還支持每個測試用例的set-up/tear-down。 運用它:

  • 在你的測試夾具類(比方FooTest)中,定義一些成員變量來保管共享資源。
  • 在同一個測試夾具類中,定義一個靜態void SetUpTestCase()函數(記住不要拼寫它作為一個小u的SetupTestCase)來設置共享資源和靜態void TearDownTestCase()函數來刪除它們。

OK! 在運轉FooTest測試用例中的第一個測試(即在創立第一個FooTest對象之前)之前,Google Test自動調用SetUpTestCase(),並在運轉最後一個測試之後(即刪除最後一個FooTest對象後)調用TearDownTestCase()。 在其間,測試可以運用共享資源。

記住測試順序是未定義的,所以你的代碼不能依賴於另一個之前或之後的測試。 此外,測試必需不能修正任何共享資源的形態,或許,假如它們修正形態,則它們必需在將控制傳遞給下一個測試之前將形態恢復到其原始值。

Here's an example of per-test-case set-up and tear-down:

class FooTest : public ::testing::Test {
 protected:
  // Per-test-case set-up.
  // Called before the first test in this test case.
  // Can be omitted if not needed.
  static void SetUpTestCase() {
    shared_resource_ = new ...;
  }

  // Per-test-case tear-down.
  // Called after the last test in this test case.
  // Can be omitted if not needed.
  static void TearDownTestCase() {
    delete shared_resource_;
    shared_resource_ = NULL;
  }

  // You can define per-test set-up and tear-down logic as usual.
  virtual void SetUp() { ... }
  virtual void TearDown() { ... }

  // Some expensive resource shared by all tests.
  static T* shared_resource_;
};

T* FooTest::shared_resource_ = NULL;

TEST_F(FooTest, Test1) {
  ... you can refer to shared_resource here ...
}
TEST_F(FooTest, Test2) {
  ... you can refer to shared_resource here ...
}

四、Global Set-Up and Tear-Down

正如你可以在測試級別和測試用例級別設置和拆卸,您也可以在測試順序級別執行。

首先,你要承繼:: testing :: Environment類來定義一個測試環境:

class Environment {
 public:
  virtual ~Environment() {}
  // Override this to define how to set up the environment.
  virtual void SetUp() {}
  // Override this to define how to tear down the environment.
  virtual void TearDown() {}
};

然後,經過調用:: testing :: Add Global Test Environment()函數,注冊我們的環境類的實例:

Environment* AddGlobalTestEnvironment(Environment* env);

如今,當調用RUN_ALL_TESTS()時,它首先調用環境對象的SetUp()辦法,然後假如沒有致命失敗則運轉測試,最後調用環境對象的TearDown()。

注冊多個環境對象是可以的。 在這種狀況下,他們的SetUp()將依照它們注冊的順序被調用,並且它們的TearDown()將以相反的順序被調用。

請留意,Google測試會對注冊的環境對象擁有一切權。 因而,不要自己刪除它們。

您應該在調用RUN_ALL_TESTS()之前調用AddGlobalTestEnvironment(),能夠在main()中調用。 假如你運用gtest_main,你需求在main()啟動之前調用它才干失效。 一種辦法是定義一個全局變量,如下所示:

::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment); 

但是,我們激烈建議您編寫自己的main()並調用AddGlobalTestEnvironment(),由於依賴於全局變量的初始化使代碼更難讀取,並且能夠會招致問題,當您從不同的轉換單元注冊多個環境, 它們之間的依賴性(記住編譯器不保證來自不同轉換單元的全局變量的初始化順序)。

 五、值參數化測試

//這個功用挺復雜,專門寫在一個獨自的文檔解析:

 http://www.cnblogs.com/jycboy/p/6118073.html

 六、類型測試

假定您有一個接口的多個完成,並希望確保一切這些都滿足一些罕見的要求。 或許,您能夠定義了幾個類型,它們應該契合相反的“概念”,並且您想要驗證它。 在這兩種狀況下,您都希望為不同類型反復相反的測試邏輯。 

 雖然你可以為你想測試的每個類型寫一個TEST或TEST_F(你甚至可以把測試邏輯放入你從TEST調用的函數模板),它是有趣的,不縮放:假如你想要m個測試 n類型,你最終會寫m * n TESTs。

類型測試允許您在類型列表上反復相反的測試邏輯。 你只需求寫一次測試邏輯,雖然在寫類型測試時你必需知道類型列表。 以下是您的操作辦法:

1. 定義一個fixture類模板。 它應該由一個類型參數化。 記住承繼:: testing :: Test:

template <typename T>
class FooTest : public ::testing::Test {
 public:
  ...
  typedef std::list<T> List;
  static T shared_;
  T value_;
};

2. 將類型列表與測試用例相關聯,這將針對列表中的每個類型反復:

typedef ::testing::Types<char, int, unsigned int> MyTypes;
TYPED_TEST_CASE(FooTest, MyTypes);

typedef關於TYPED_TEST_CASE宏正確解析是必要的。 否則編譯器會以為類型列表中的每個逗號引入一個新的宏參數。

3. 運用TYPED_TEST()而不是TEST_F()為此測試用例定義一個類型測試。 您可以依據需求反復此操作次數:

TYPED_TEST(FooTest, DoesBlah) {
  // Inside a test, refer to the special name TypeParam to get the type
  // parameter.  Since we are inside a derived class template, C++ requires
  // us to visit the members of FooTest via 'this'.
  TypeParam n = this->value_;

  // To visit static members of the fixture, add the 'TestFixture::'
  // prefix.
  n += TestFixture::shared_;

  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
  // prefix.  The 'typename' is required to satisfy the compiler.
  typename TestFixture::List values;
  values.push_back(n);
  ...
}

TYPED_TEST(FooTest, HasPropertyA) { ... }

You can see samples/sample6_unittest.cc for a complete example.

七、類型參數化測試

在不知道類型參數的狀況下編寫測試--- 這就是“類型參數化測試”。

類型參數化測試相似於類型測試,除了它們不需求預知類型列表。 相反,您可以首先定義測試邏輯,然後運用不同類型列表實例化它。 你甚至可以在同一個順序中屢次實例化它。

假如您正在設計一個接口或概念,則可以定義一組類型參數化測試,以驗證接口/概念的任何無效完成應具有的屬性。 然後,每個完成的作者可以運用他的類型來實例化測試套件,以驗證它契合需求,而不用反復地編寫相似的測試。 這裡有一個例子:

1. 定義一個fixture類模板,好像我們用類型測試一樣:

First, define a fixture class template, as we did with typed tests:

template <typename T>
class FooTest : public ::testing::Test {
  ...
};

2. 聲明你要定義的類型參數化測試用例:

TYPED_TEST_CASE_P(FooTest);

這個後綴P代表參數化或形式,隨你怎樣想。

3. 運用TYPED_TEST_P()來定義類型參數化測試。您可以依據需求反復屢次:

TYPED_TEST_P(FooTest, DoesBlah) {
  // Inside a test, refer to TypeParam to get the type parameter.
  TypeParam n = 0;
  ...
}

TYPED_TEST_P(FooTest, HasPropertyA) { ... }

如今順手的局部:您需求運用REGISTER_TYPED_TEST_CASE_P宏注冊一切測試形式,然後才干實例化它們。

宏的第一個參數是測試用例稱號; 其他的是在這個測試用例中的測試的稱號:

REGISTER_TYPED_TEST_CASE_P(FooTest,
                           DoesBlah, HasPropertyA);

最後,你可以用你想要的類型來實例化形式。 假如你把下面的代碼放在頭文件中,你可以在多個C ++源文件#include它,並實例化屢次。

typedef ::testing::Types<char, int, unsigned int> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);

為了區分形式的不同實例,INSTANTIATE_TYPED_TEST_CASE_P宏的第一個參數是將添加到實踐測試用例稱號中的前綴。 請記住為不同實例選擇獨一前綴。

在類型列表只包括一個類型的特殊狀況下,您可以直接編寫該類型,而不運用:: testing :: Types <...>,如下所示:

INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);

ou can see samples/sample6_unittest.cc for a complete example.

**類型測試與類型參數化的區別:

1. 類型測試是你知道一切的類型,把一切類型注冊,實例化測試。

2. 類型參數化是你是接口的定義者,知道每個接口函數的根本功用,而它的詳細完成可以在未來被   人完成,你可以提早定義好測試用例,然後把一切的測試注冊。

八、測試private修飾的代碼

假如您更改軟件的外部完成,只需用戶不能察看到這種變化,您的測試就不會中綴。 因而,依據黑盒測試准繩,大少數時分你應該經過其公共接口測試你的代碼。

假如你依然發現自己需求測試外部完成代碼,思索能否有一個更好的設計,不需求你這樣做。 假如你必需測試非公共接口代碼。 有兩種狀況需求思索:

  •  靜態函數(不同於靜態成員函數!)或未命名的命名空間
  •  公家或受維護的類成員

 1. 靜態函數

未命名的命名空間中的靜態函數和定義/聲明僅在同一轉變單元中可見。要測試它們,您可以在你的* _test.cc文件中include 要測試的整個.cc文件。 (#include .cc文件不是重用代碼的好辦法 - 你不應該在消費代碼中這樣做!)

但是,更好的辦法是將公有代碼挪動到foo :: internal命名空間中,其中foo是你項目通常運用的命名空間,並將公有聲明放在* -internal.h文件中。允許您的消費.cc文件和測試包括此外部標頭,但是您的客戶端不包括。這樣,您可以完全測試您的外部完成,而不會走漏到您的客戶端。

2. 公有類成員

公家class成員只能從班class或友元類那裡接觸。要訪問類的公有成員,可以將測試夾具聲明為類的冤家,並在夾具中定義訪問器。運用夾具的測試,可以經過夾具中的訪問器訪問您的消費類的公有成員。留意,即便你的夾具是你的消費類的冤家,你的測試不是它的友元類,由於他們技術上是定義在夾具的子類中。

另一種測試公有成員的辦法是將它們重構為一個完成類,然後在* -internal.h文件中聲明它。您的客戶端不允許包括此標題,但您的測試可以。這種稱為Pimpl(公有完成)習語。

或許,您可以經過在類主體中添加以下行,將一般測試聲明為class的友元類:

FRIEND_TEST(TestCaseName, TestName);

  For example,

// foo.h
#include "gtest/gtest_prod.h"

// Defines FRIEND_TEST.
class Foo {
  ...
 private:
  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}

當你的類在命名空間中定義時,需求特別留意,由於你應該在同一個命名空間中定義你的測試夾具和測試,假如你想他們是你的class的友元。 例如,假如要測試的代碼如下所示:

namespace my_namespace {

class Foo {
  friend class FooTest;
  FRIEND_TEST(FooTest, Bar);
  FRIEND_TEST(FooTest, Baz);
  ...
  definition of the class Foo
  ...
};

}  // namespace my_namespace

Your test code should be something like:

namespace my_namespace {
class FooTest : public ::testing::Test {
 protected:
  ...
};

TEST_F(FooTest, Bar) { ... }
TEST_F(FooTest, Baz) { ... }

}  // namespace my_namespace

九、Catching Failures

假如您要在Google測試之上構建測試適用順序,則需求測試您的適用順序。 你將運用什麼框架來測試它? Google測試,當然。

應戰是驗證您的測試適用順序能否正確報告毛病。 在框架中經過拋出異常報告失敗,您可以捕捉異常並斷言。 但是Google Test不會運用異常,那麼我們如何測試一段代碼能否會發生預期的失敗呢?

“gtest / gtest-spi.h”包括一些結構來做到這一點。 #include 它,然後可以運用

EXPECT_FATAL_FAILURE(statement, substring);​

to assert that statement generates a fatal (e.g. ASSERT_*) failure whose message contains the given substring, or use

EXPECT_NONFATAL_FAILURE(statement, substring);​

if you are expecting a non-fatal (e.g. EXPECT_*) failure.

。。。。。//需求時再看

十、Getting the Current Test's Name

   有時一個函數能夠需求知道以後運轉的測試的稱號。 例如,您可以運用測試夾具的SetUp()辦法依據正在運轉的測試設置黃金文件名。 :: testing :: TestInfo類具有以下信息:

namespace testing {

class TestInfo {
 public:
  // Returns the test case name and the test name, respectively.
  //
  // Do NOT delete or free the return value - it's managed by the
  // TestInfo class.
  const char* test_case_name() const;
  const char* name() const;
};

}  // namespace testing

To obtain a TestInfo object for the currently running test, call current_test_info() on the UnitTest singleton object:

// Gets information about the currently running test.
// Do NOT delete the returned object - it's managed by the UnitTest class.
const ::testing::TestInfo* const test_info =
  ::testing::UnitTest::GetInstance()->current_test_info();
printf("We are in test %s of test case %s.\n",
       test_info->name(), test_info->test_case_name());

假如沒有運轉測試,current_test_info()前往一個空指針。 特別是,你不能在TestCaseSetUp(),TestCaseTearDown()中找到測試用例稱號(在那裡你知道測試用例稱號),或許從它們調用的函數。

十 一、運轉測試順序:初級選項

Google Test測試順序是普通的可執行文件。 一旦構建,您可以直接運轉它們,並經過以下環境變量 或命令行標志影響其行為。 要使標志任務,您的順序必需在調用RUN_ALL_TESTS()之前調用:: testing :: InitGoogleTest()。

要檢查支持的標志及其用法的列表,請運用--help標志運轉測試順序。 您也可以運用-h, - ?或/? 簡稱。 此功用在版本1.3.0中添加。
設置標志的三種方式:以--gtest_filter 為例        1)命令行運轉順序時直接加上參數:./foo_test --gtest_filter=QueueTest.*;       2)在代碼中設置::: testing :: GTEST_FLAG(filter)= "QueueTest.*" **留意沒有前邊的--gtest_。       3)testing::FLAGS_gtest_filter = "QueueTest.*"; 假如選項由環境變量和標志指定,則後者優先。 大少數選項也可以在代碼中設置/讀取:訪問命令行標志的值--gtest_foo,write :: testing :: GTEST_FLAG(foo)。  **留意標志是:--gtest_foo ; 在代碼中調用是:: testing :: GTEST_FLAG(foo);沒有前邊的--gtest_。 一個罕見的形式是在調用:: testing :: InitGoogleTest()之前設置標志的值:
int main(int argc, char** argv) {
  // Disables elapsed time by default.
  ::testing::GTEST_FLAG(print_time) = false;

  // This allows the user to override the flag on the command line.
  ::testing::InitGoogleTest(&argc, argv);

  return RUN_ALL_TESTS();
}  

1. 選擇測試

   此局部顯示用於選擇哪些測試運轉的各種選項。

 1.1 列出測試稱號
  有時,在運轉順序之前,必需列出順序中的可用測試,以便在需求時使用過濾器。 包括標志--gtest_list_tests掩蓋一切其他標志,並列出以下格式的測試:
TestCase1.
  TestName1
  TestName2
TestCase2.
  TestName

假如提供了標志,則列出的一切測試都不會真正運轉。 此標志沒有相應的環境變量。

  1.2運轉測試的子集

默許狀況下,Google測試順序運轉用戶定義的一切測試。 有時,您只想運轉測試的一個子集(例如,用於調試或疾速驗證更改)。 假如將GTEST_FILTER環境變量或--gtest_filter標志設置為過濾器字符串,則Google Test將僅運轉其全名(以TestCaseName.TestName的方式)與過濾器婚配的測試。

過濾器的格式是通配符形式(稱為正形式)的':'分隔的列表,可選地後跟一個“ - ”和另一個“:”分隔的形式列表(稱為負形式)。 測試婚配過濾器當且僅當它與任何正形式婚配但不婚配任何負形式時。

形式能夠包括“*”(婚配任何字符串)或'?' (婚配任何單個字符)。 為了方便,過濾器'* -NegativePatterns'也可以寫為'-NegativePatterns'。

For example:

  • ./foo_test Has no flag, and thus runs all its tests.
  • ./foo_test --gtest_filter=* Also runs everything, due to the single match-everything * value.
  • ./foo_test --gtest_filter=FooTest.* Runs everything in test case FooTest.
  • ./foo_test --gtest_filter=*Null*:*Constructor* Runs any test whose full name contains either "Null" or "Constructor".
  • ./foo_test --gtest_filter=-*DeathTest.* Runs all non-death tests.
  • ./foo_test --gtest_filter=FooTest.*-FooTest.Bar Runs everything in test case FooTest except FooTest.Bar.

 1.3 暫時禁用測試

假如你有一個失敗的測試,無法立刻修復,可以在其稱號中添加DISABLED_前綴。 將掃除它執行。 這比正文掉代碼或運用#if 0更好,由於禁用的測試依然編譯(因而不會rot)。

假如你需求禁用測試用例中的一切測試,可以在每個測試稱號的後面添加DISABLED_,或許將其添加到測試用例稱號的後面。

例如,以下測試不會由Google Test運轉,即便它們依然將被編譯:

// Tests that Foo does Abc.
TEST(FooTest, DISABLED_DoesAbc) { ... }

class DISABLED_BarTest : public ::testing::Test { ... };

// Tests that Bar does Xyz.
TEST_F(DISABLED_BarTest, DoesXyz) { ... } 

留意:此功用只能用於暫時緩解。 您依然必需在當前修復已禁用的測試。 提示您,假如測試方案包括任何已停用的測試,Google測試會打印一條橫幅正告您。

提示:您可以輕松計算已運用grep禁用的測試的數量。 此數字可用作進步測試質量的目標。

1.4 暫時啟用禁用測試

要在測試執行中包括禁用的測試,只需運用--gtest_also_run_disabled_tests標志調用測試順序或將GTEST_ALSO_RUN_DISABLED_TESTS環境變量設置為0以外的值。您可以將此與--gtest_filter標志結合,以進一步選擇要運轉哪些已禁用的測試 。

代碼中設置如下:前邊加FLAGS_ (好坑啊,文檔裡也沒說,我查出來的)。

testing::FLAGS_gtest_also_run_disabled_tests = 2;

2. 反復測試

有一段時間,你會碰到一個測試,它的後果是命中或錯過。 也許它只會失敗1%的時間,使它很難重現調試器下的錯誤。 這能夠是波折的次要本源。

--gtest_repeat標志允許您在順序中反復一切(或選定的)測試辦法屢次。 希望,一個軟弱的測試最終會失敗,並給你一個時機停止調試。 以下是運用辦法:

$ foo_test --gtest_repeat=1000Repeat foo_test 1000 times and don't stop at failures. $ foo_test --gtest_repeat=-1 A negative count means repeating forever. $ foo_test --gtest_repeat=1000 --gtest_break_on_failure Repeat foo_test 1000 times, stopping at the first failure. This is especially useful when running under a debugger: when the testfails, it will drop into the debugger and you can then inspect variables and stacks. $ foo_test --gtest_repeat=1000 --gtest_filter=FooBar Repeat the tests whose name matches the filter 1000 times.

 假如您的測試順序包括運用AddGlobalTestEnvironment()注冊的全局set-up/tear-down代碼,則在每次迭代中都會反復該測試順序,由於其中能夠存在薄片。 您還可以經過設置GTEST_REPEAT環境變量來指定反復計數。

 3.Shuffling the Tests洗牌測試

您可以指定--gtest_shuffle標志(或將GTEST_SHUFFLE環境變量設置為1),以便以隨機順序在順序中運轉測試。 這有助於提醒測試之間的依賴關系。

默許狀況下,Google測試運用依據以後時間計算的隨機種子。 因而,你每次都會失掉不同的順序。 控制台輸入包括隨機種子值,以便當前可以重現與順序相關的測試失敗。 要明白指定隨機種子,請運用--gtest_random_seed = SEED標志(或設置GTEST_RANDOM_SEED環境變量),其中SEED是介於0和99999之間的整數。種子值0是特殊的:它通知Google Test執行默許行為 從以後時間計算種子。

假如將此與--gtest_repeat = N結合運用,Google測試會選擇不同的隨機種子,並在每次迭代中重新洗牌測試。

 4.控制測試輸入

 本節教誨如何調整測試後果的報告方式。

  4.1黑色終端輸入

Google測試可以在其終端輸入中運用顏色,以便更容易地發現測試之間的別離,以及測試能否經過。

您可以設置GTEST_COLOR環境變量,或將--gtest_color命令行標志設置為yes,no或auto(默許值)以啟用顏色,禁用顏色或讓Google測試決議。 當值為auto時,假如且僅當輸入發送到終端,並且(在非Windows平台上)TERM環境變量設置為xterm或xterm-color,Google Test將運用顏色。

 4.2 抑制所用時間

默許狀況下,Google測試會打印運轉每個測試所需的時間。為了抑制這種狀況,運用--gtest_print_time = 0命令行標志運轉測試順序。將GTEST_PRINT_TIME環境變量設置為0具有相反的效果。

可用性:Linux,Windows,Mac。 (在Google Test 1.3.0及更低版本中,默許行為是不打印已用時間。)

 4.3 生成XML報告

  除了正常的文本輸入之外,Google Test還可以向文件發送詳細的XML報告。報告包括每個測試的繼續時間,因而可以協助您辨認慢速測試。

要生成XML報告,請將GTEST_OUTPUT環境變量或--gtest_output標志設置為字符串“xml:_path_to_output_file_”,這將在給定地位創立文件。您也可以只運用字符串“xml”,在這種狀況下,輸入可以在以後目錄中的test_detail.xml文件中找到。

  假如指定目錄(例如,Linux上的“xml:output / directory /”或Windows上的“xml:output \ directory \”),Google Test將在該目錄中創立一個XML文件(測試順序foo_test或foo_test.exe的foo_test.xml)。假如文件已存在(能夠是上次運轉時遺留的文件),Google測試會選擇不同的稱號(例如foo_test_1.xml),以防止掩蓋它。

報告運用此處描繪的格式。它基於junitreport Ant義務,可以經過盛行的延續構建零碎(如Hudson)停止解析。由於該格式最初是用於Java,需求稍作解釋才干將其使用於Google Test測試,如下所示:

<testsuites name="AllTests" ...>
  <testsuite name="test_case_name" ...>
    <testcase name="test_name" ...>
      <failure message="..."/>
      <failure message="..."/>
      <failure message="..."/>
    </testcase>
  </testsuite>
</testsuites>
  • <testsuites>根元素對應於整個測試順序。
  • <testsuite> 元素對應與test case.
  • <testcase> 元素對應於Google Test測試函數。

For instance, the following program

TEST(MathTest, Addition) { ... }
TEST(MathTest, Subtraction) { ... }
TEST(LogicTest, NonContradiction) { ... }

could generate this report:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="3" failures="1" errors="0" time="35" name="AllTests">
  <testsuite name="MathTest" tests="2" failures="1" errors="0" time="15">
    <testcase name="Addition" status="run" time="7" classname="">
      <failure message="Value of: add(1, 1)
 Actual: 3
Expected: 2" type=""/>
      <failure message="Value of: add(1, -1)
 Actual: 1
Expected: 0" type=""/>
    </testcase>
    <testcase name="Subtraction" status="run" time="5" classname="">
    </testcase>
  </testsuite>
  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="5">
    <testcase name="NonContradiction" status="run" time="5" classname="">
    </testcase>
  </testsuite>
</testsuites>

留意事項:

  •  <testuites>元素的tests屬性包括多少個測試,而failures屬性通知它們有多少個失敗。
     <testcase>元素的屬性:該測試用例中包括多少個測試;
  •  time屬性以毫秒表示測試、測試用例或整個測試順序的繼續時間。
  •  每個<failure>元素對應於單個失敗的Google Test斷言。
  • 某些JUnit概念不適用於Google測試,但我們必需契合DTD。 因而,您將在報告中看到一些虛擬元素和屬性。 您可以平安地疏忽這些局部。

5.控制如何報告失敗

 5.1 將斷言失敗轉換為斷點

  當在調試器下運轉測試順序時,假如調試器可以捕捉斷言毛病並自動進入交互形式,則十分方便。 Google測試的break-on-failure 形式支持此行為。

  要啟用它,請將GTEST_BREAK_ON_FAILURE環境變量設置為0以外的值。或許,您可以運用--gtest_break_on_failure命令行標志。

可用性:Linux,Windows,Mac。

 5.2 禁用捕捉測試 - 拋出異常Disabling Catching Test-Thrown Exceptions

   Google測試可以在啟用或不啟用exception的狀況下運用。假如測試拋出C ++異常或(在Windows上)構造化異常(SEH),默許狀況下Google測試會捕捉它,將其報告為測試失敗,並持續執行下一個測試辦法。這將最大化測試運轉的掩蓋率。此外,在Windows上,未捕捉的異常將招致彈出窗口,因而捕捉異常允許您自動運轉測試。

  但是,當調試測試失敗時,您能夠希望異常由調試器處置,以便您可以在拋出異常時反省調用堆棧。要完成此目的,請在運轉測試時將GTEST_CATCH_EXCEPTIONS環境變量設置為0,或運用--gtest_catch_exceptions = 0標志。

 5.3 讓另一個測試框架驅動

    假如您運用的項目曾經運用了另一個測試框架,但尚未預備好完全切換到Google測試,則可以經過在現有測試中運用其斷言來取得Google測試的許多優勢。 只是改動你的main()函數看起來像:

#include "gtest/gtest.h"

int main(int argc, char** argv) {
  ::testing::GTEST_FLAG(throw_on_failure) = true;
  // Important: Google Test must be initialized.
  ::testing::InitGoogleTest(&argc, argv);

  ... whatever your existing testing framework requires ...
}

 這樣,除了你的框架提供的斷言之外,您還可以運用Google Test斷言,例如:

void TestFooDoesBar() {
  Foo foo;
  EXPECT_LE(foo.Bar(1), 100);     // A Google Test assertion.
  CPPUNIT_ASSERT(foo.IsEmpty());  // A native assertion.
}

。。。。。後邊的省略了,這個應該需求不到

6. 將測試功用分發到多台機器

假如您有多個機器可以用來運轉測試順序,您能夠希望並行運轉測試功用並更快地取得後果。我們稱之為技術分片,其中每台機器被稱為分片。

Google測試與測試分片兼容。要應用此功用,您的測試運轉器(不是Google測試的一局部)需求執行以下操作:

  1. 分配多個計算機(分片)以運轉測試。
  2. 在每個分片上,將GTEST_TOTAL_SHARDS環境變量設置為分片的總數。它對一切分片必需相反。
  3. 在每個分片上,將GTEST_SHARD_INDEX環境變量設置為分片的索引。不同的分片必需分配不同的索引,這些索引必需在[0,GTEST_TOTAL_SHARDS - 1]的范圍內。
  4. 在一切分片上運轉相反的測試順序。當Google測試看到上述兩個環境變量時,它將選擇要運轉的測試函數的子集。在一切分片中,順序中的每個測試函數將只運轉一次。
  5. 等候一切分片完成,然後搜集並報告後果。

您的項目能夠有沒有Google Test的測試,因而不理解此協議。為了讓測試運轉器確定哪個測試支持分片,它可以將環境變量GTEST_SHARD_STATUS_FILE設置為不存在的文件途徑。假如測試順序支持分片,它將創立此文件以確認現實(文件的實踐內容此時不重要;雖然我們未來能夠會在其中粘貼一些有用的信息。否則它不會創立它。

這裡有一個例子來闡明。假定您有一個包括以下5個測試函數的測試順序foo_test:

TEST(A, V)
TEST(A, W)
TEST(B, X)
TEST(B, Y)
TEST(B, Z)

你有3台機器在您的處置。 要並行運轉測試功用,您需求在一切機器上將GTEST_TOTAL_SHARDS設置為3,並將GTEST_SHARD_INDEX辨別設置為0,1和2。 然後你將在每台機器上運轉相反的foo_test。

Google測試有權更改任務在分片上的散布狀況,但這裡有一種能夠的狀況:

  • Machine #0 runs A.V and B.X.
  • Machine #1 runs A.W and B.Y.
  • Machine #2 runs B.Z.

十二、交融Google測試源文件

  Google測試的完成包括〜30個文件(不包括自己的測試)。 有時你能夠希望它們被打包在兩個文件(.h和.cc),以便你可以輕松地將它們復制到一個新的機器,並開端黑客。 為此,我們在scripts /目錄中提供了一個實驗性Python腳本fuse_gtest_files.py(自1.3.0版本開端)。 假定你在你的機器上裝置了Python 2.4或更高版本,只需去那個目錄並運轉

   python fuse_gtest_files.py OUTPUT_DIR
  並且您應該看到一個OUTPUT_DIR目錄正在創立文件gtest / gtest.h和gtest / gtest-all.cc。 這些文件包括您運用Google測試所需的一切。 只需將它們復制就任何你想要的,你預備好寫測試。 您可以運用scripts / test / Makefile文件作為如何編譯針對它們的測試的示例。

 

上篇博文地址:Google C++單元測試框架GoogleTest---AdvancedGuide(譯文)上

轉載請注明出處:http://www.cnblogs.com/jycboy/p/AdvancedGuide2.html

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved