Google C++單元測試架構(Gtest)系列教程之五——再論測試韌體

來源:互聯網
上載者:User

引言

在《Google C++單元測試架構(Gtest)系列教程之三——測試韌體(Test fixture)》中,介紹了如何使用測試韌體為測試執行個體(Tests)進行資料配置和初始化。除了資料初始化方法,Gtest還提供了測試執行個體間共用資料的方法。

同屬一個測試案例的測試執行個體間共用資料

為實現測試執行個體間的獨立性,Gtest提供了為每個測試執行個體新產生一個測試韌體對象的方法,通過“獨享”測試對象中的資料,保證了一個測試執行個體的執行不會對其他執行個體的執行產生影響。但是,對於以下情況:

  1. 初始化資料涉及記憶體申請等操作,為每個測試執行個體構造對象將帶來較大系統開銷;
  2. 存在某資料,其在每個執行個體中均被用到,但每個執行個體都不會更改該資料的值;

我們就沒有必要將這些資料放入測試韌體對象中了,在一個C++類中,使用什麼方法能讓資料獨立於對象之外、又能被對象訪問呢?

沒錯!就是使用C++類的static成員變數,具體定義方法如下:

  1. 在測試韌體類中,將需要在測試執行個體間共用的資料聲明為static類型;
  2. 定義函數SetUpTestCase(),用於初始化共用資料;定義函數TearDownTestCase(),用於清理共用資料。這兩個函數的函數類型均為static void。

在測試程式執行時,Gtest在第一個測試執行個體運行之前調用SetUpTestCase(),在最後一個測試執行個體運行之後調用TearDownTestCase(),在此期間,測試執行個體可以使用所定義的共用資料。

我們來看一個在測試執行個體間共用資料的執行個體:

class FooTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
shared_resource_ = new ...;
}
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 ...
}

由於Gtest不一定按照我們聲明的順序執行測試執行個體,因此我們的測試執行個體仍需保持獨立,避免濫用共用資料造成的測試執行個體相互依賴的情況。在測試執行個體中,要不不改變共用資料的值,要不在改變資料值之後、執行完之前還原共用資料的值。

程式層級資料共用

正如前面介紹的,Gtest提供了測試執行個體(Tests)和測試案例(Test Case)層級的資料管理的方法,除此之外,Gtest在程式層級提供了共用資料管理方法,使得我們可以在測試案例和測試執行個體間共用資料。

為實現在程式層級共用資料,首先我們需要定義一個繼承自::testing::Environment的類,並且編寫SetUp()和TearDown()函數覆蓋父類中的相應虛函數,該類中的成員變數即可作為共用資料:

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() {}
};

其次,調用以下介面“註冊”類對象:

Environment* AddGlobalTestEnvironment(Environment* env);

其參數為“註冊”前的類對象指標,傳回值為“註冊”後的類對象指標。下面我們來看執行個體:

class FooEnvironment: public testing::Environment
{
public:
virtual void SetUp()
{
printf("Environment SetUp!\n");
a = 100;
}
virtual void TearDown()
{
printf("Environment TearDown!\n");
}
int a;     //共用資料
};
FooEnvironment* foo_env;  //對象指標聲明
TEST(firstTest, first)    //訪問共用資料並改變它的值
{
printf("in the firstTest, foo_env->p is %d\n", foo_env->a);
foo_env->a ++;
}
TEST(secondTest, second)  //訪問共用資料
{
printf("in the secondTest, foo_env->p is %d\n", foo_env->a);
}
int main(int argc, char* argv[])
{
foo_env = new FooEnvironment;
testing::AddGlobalTestEnvironment(foo_env);     //註冊
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

上面的測試案例firstTest和secondTest均訪問了共用資料,作為示範,firstTest修改了共用資料的值。該測試程式執行結果如下:

[==========] Running 2 tests from 2 test cases.
[----------] Global test environment set-up.
Environment SetUp!
[----------] 1 test from firstTest
[ RUN ] firstTest.first
in the firstTest, foo_env->p is 100
[ OK ] firstTest.first (0 ms)
[----------] 1 test from firstTest (0 ms total)

[----------] 1 test from secondTest
[ RUN ] secondTest.second
in the secondTest, foo_env->p is 101
[ OK ] secondTest.second (0 ms)
[----------] 1 test from secondTest (0 ms total)

[----------] Global test environment tear-down
Environment TearDown!
[==========] 2 tests from 2 test cases ran. (0 ms total)
[ PASSED ] 2 tests.

小結

在Gtest中,測試執行個體間共用資料的方式有兩種(除全域變數的方式外),一種是讓同屬一個測試案例的測試執行個體間共用資料,另一種是可讓程式中的所有測試執行個體共用資料。測試執行個體間進行資料共用,破壞了測試執行個體間執行的獨立性,個人認為應該盡量避免使用。

Reference: googletest project

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.