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

Google C++單元測試框架---TestFixture使用,unittest單元測試框架

編輯:C++入門知識

Google C++單元測試框架---TestFixture使用,unittest單元測試框架


一、測試夾具(Test Fixtures):對多個測試使用相同的數據配置

如果你發現自己寫了兩個或更多的測試來操作類似的數據,你可以使用測試夾具。它允許您為幾個不同的測試重復使用相同的對象配置。

要創建夾具,只需:

  1.從:: testing :: Test派生一個類。 使用protected:或public:開始它的主體,因為我們想從子類     訪問fixture成員。
  2.在類中,聲明你打算使用的任何對象。
  3.如果需要,可以編寫默認構造函數或SetUp()函數來為每個測試准備對象。 一個常見的錯誤是     拼寫SetUp()為Setup()與一個小u -- 不要讓這種情況發生在你身上。
  4.如果需要,寫一個析構函數或TearDown()函數來釋放你在SetUp()中分配的任何資源。 要     學習什麼時候應該使用構造函數/析構函數,當你應該使用SetUp()/ TearDown()時,請閱讀這個 FAQ entry.。
  5.如果需要,定義要分享的測試的子程序。

當使用夾具時,使用TEST_F()而不是TEST(),因為它允許您訪問測試夾具中的對象和子程序:

TEST_F(test_case_name, test_name) {
 ... test body ...
}​

和TEST()一樣,第一個參數是測試用例名,但是對於TEST_F()必須是測試夾具類的名稱。 你可能猜到了:_F是夾具。

不幸的是,C ++宏系統不允許我們創建一個可以處理兩種類型的測試的宏。 使用錯誤的宏會導致編譯器錯誤。

另外,在TEST_F()中使用它之前,你必須首先定義一個測試夾具類,否則將得到編譯器錯誤“virtual outside class declaration”。

對於使用TEST_F()定義的每個測試,Google Test將:

  1.在運行時創建一個新的測試夾具
  2.立即通過SetUp()初始化,
  3.運行測試
  4.通過調用TearDown()清除
  5.刪除測試夾具。 請注意,同一測試用例中的不同測試具有不同的測試夾具對象,Google測試始     終會刪除測試夾具,然後再創建下一個測試夾具。 Google測試不會為多個測試重復使用相同的       測試夾具。一個測試對夾具的任何更改不會影響其他測試

例如,讓我們為名為Queue的FIFO隊列類編寫測試,它有以下接口:

template <typename E> // E is the element type.
class Queue {
 public:
  Queue();
  void Enqueue(const E& element);
  E* Dequeue(); // Returns NULL if the queue is empty.
  size_t size() const;
  ...
}; 

 首先定義一個夾具類。按照慣例,你應該給它名稱FooTest,其中Foo是被測試的類。 

class QueueTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // virtual void TearDown() {}

  Queue<int> q0_;
  Queue<int> q1_;
  Queue<int> q2_;
}; 

在這種情況下,不需要TearDown(),因為我們不必在每次測試後清理,除了析構函數已經做了什麼。

現在我們將使用TEST_F()和這個夾具編寫測試。

TEST_F(QueueTest, IsEmptyInitially) {
  EXPECT_EQ(0, q0_.size());
}

TEST_F(QueueTest, DequeueWorks) {
  int* n = q0_.Dequeue();
  EXPECT_EQ(NULL, n);

  n = q1_.Dequeue();
  ASSERT_TRUE(n != NULL);
  EXPECT_EQ(1, *n);
  EXPECT_EQ(0, q1_.size());
  delete n;

  n = q2_.Dequeue();
  ASSERT_TRUE(n != NULL);
  EXPECT_EQ(2, *n);
  EXPECT_EQ(1, q2_.size());
  delete n;
} 

上面使用ASSERT_ *和EXPECT_ *斷言。 經驗法則( The rule of thumb )是當你希望測試在斷言失敗後繼續顯示更多錯誤時使用EXPECT_ *,或是在失敗後繼續使用ASSERT_ *沒有意義。 例如,Dequeue測試中的第二個斷言是ASSERT_TRUE(n!= NULL),因為我們需要稍後解引用指針n,這將導致n為NULL時的segfault。

當這些測試運行時,會發生以下情況:

  1.Google Test構造了一個QueueTest對象(我們稱之為t1)。 
  2.t1.SetUp()初始化t1。 
  3.第一個測試(IsEmptyInitially)在t1上運行。 
  4.t1.TearDown()在測試完成後清理。 
  5.t1被析構。 
  6.以上步驟在另一個QueueTest對象上重復,這次運行DequeueWorks測試。

 二、如何通過字夾具使多個測試用例重用一個測試夾具

  1. 當定義測試夾具時,您指定將使用此夾具的測試用例的名稱。 因此,測試夾具只能由一個測試用例使用
   有時,多個測試用例可能需要使用相同或稍微不同的測試夾具。 例如,您可能需要確保GUI庫的所有測試不會洩漏重要的系統資源,如字體和畫筆。 在Google測試中,您可以做到
  這通過將共享邏輯放在超級(如“超級類”)測試夾具中,然後讓每個測試用例使用從這個超級夾具派生的夾具。
   在這個示例中,我們希望確保每個測試在〜5秒內完成。 如果測試運行時間較長,我們認為測試失敗。

  我們把測試時間的代碼放在一個叫做“QuickTest”的測試夾具中。 QuickTest旨在作為其他夾具派生的超級夾具,因此沒有名為“QuickTest”的測試用例。

 然後,我們將從QuickTest中導出多個測試夾具。

class QuickTest : public testing::Test {
protected:
	// Remember that SetUp() is run immediately before a test starts.
	// This is a good place to record the start time.
	//這個方法在每一個test之前執行
	virtual void SetUp() {
		start_time_ = time(NULL);
	}
	// TearDown() is invoked immediately after a test finishes.  Here we
	// check if the test was too slow.
	//這個方法在每一個test之後執行
	virtual void TearDown() {
		// Gets the time when the test finishes
		const time_t end_time = time(NULL);
		// Asserts that the test took no more than ~5 seconds.  Did you
		// know that you can use assertions in SetUp() and TearDown() as
		// well?
		EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
	}

	// The UTC time (in seconds) when the test starts
	time_t start_time_;
};

2.我們定義一個IntegerFunctionTest繼承QuickTest, 使用該夾具的所有測試將自動要求快速。

class IntegerFunctionTest : public QuickTest {
	// We don't need any more logic than already in the QuickTest fixture.
	// Therefore the body is empty.
};

3.現在我們可以在Integer Function Test測試用例中寫測試了。

TEST_F(IntegerFunctionTest, Factorial) {
	// Tests factorial of negative numbers.
	EXPECT_EQ(1, Factorial(-5));
	EXPECT_EQ(1, Factorial(-1));
	EXPECT_GT(Factorial(-10), 0);

	// Tests factorial of 0.
	EXPECT_EQ(1, Factorial(0));

	// Tests factorial of positive numbers.
	EXPECT_EQ(1, Factorial(1));
	EXPECT_EQ(2, Factorial(2));
	EXPECT_EQ(6, Factorial(3));
	EXPECT_EQ(40320, Factorial(8));
}

4. 下一個測試用例(名為“QueueTest”)也需要很快,所以我們從QuickTest派生另一個夾具。
QueueTest測試夾具有一些邏輯和共享對象,除了QuickTest中已有的。 我們像往常一樣在測試夾具的主體內定義額外的東西。

class QueueTest : public QuickTest {
protected:
	virtual void SetUp() {
		// First, we need to set up the super fixture (QuickTest).
		QuickTest::SetUp();

		// Second, some additional setup for this fixture.
		q1_.Enqueue(1);
		q2_.Enqueue(2);
		q2_.Enqueue(3);
	}

	// By default, TearDown() inherits the behavior of
	// QuickTest::TearDown().  As we have no additional cleaning work
	// for QueueTest, we omit it here.
	//
	// virtual void TearDown() {
	//   QuickTest::TearDown();
	// }

	Queue<int> q0_;
	Queue<int> q1_;
	Queue<int> q2_;
};

  接下來我們就可以用QueueTest寫一些測試。

// Tests the default constructor.
TEST_F(QueueTest, DefaultConstructor) {
	EXPECT_EQ(0u, q0_.Size());
} 

  如有必要,您可以從派生的夾具本身獲得進一步的測試夾具。 例如,您可以從QueueTest派生另一個夾具。 Google測試對層次結構的深度沒有限制。 然而,在實踐中,你可能不希望它太深以至於混淆。

 

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