偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

使用 GoogleTest 和 CTest 進(jìn)行單元測(cè)試

開發(fā)
本文我將介紹如何通過 GoogleTest 和 CTest 將單元測(cè)試集成到這個(gè)構(gòu)建系統(tǒng)中。

進(jìn)行單元測(cè)試可以提高代碼質(zhì)量,并且它不會(huì)打斷你的工作流。

本文是 使用 CMake 和 VSCodium 設(shè)置一個(gè)構(gòu)建系統(tǒng) 的后續(xù)文章。

在上一篇文章中我介紹了基于 VSCodium 和 CMake 配置構(gòu)建系統(tǒng)。本文我將介紹如何通過 GoogleTest 和 CTest 將單元測(cè)試集成到這個(gè)構(gòu)建系統(tǒng)中。

首先克隆 這個(gè)倉(cāng)庫(kù),用 VSCodium 打開,切換到 devops_2 標(biāo)簽。你可以通過點(diǎn)擊 main 分支符號(hào)(紅框處),然后選擇 devops_2 標(biāo)簽(黃框處)來(lái)進(jìn)行切換:

VSCodium tagVSCodium tag

或者你可以通過命令行來(lái)切換:

$ git checkout tags/devops_2

GoogleTest

GoogleTest 是一個(gè)平臺(tái)無(wú)關(guān)的開源 C++ 測(cè)試框架。單元測(cè)試是用來(lái)驗(yàn)證單個(gè)邏輯單元的行為的。盡管 GoogleTest 并不是專門用于單元測(cè)試的,我將用它對(duì) Generator 庫(kù)進(jìn)行單元測(cè)試。

在 GoogleTest 中,測(cè)試用例是通過斷言宏來(lái)定義的。斷言可能產(chǎn)生以下結(jié)果:

  • 成功: 測(cè)試通過。
  • 非致命失敗: 測(cè)試失敗,但測(cè)試?yán)^續(xù)。
  • 致命失敗: 測(cè)試失敗,且測(cè)試終止。

致命斷言和非致命斷言通過不同的宏來(lái)區(qū)分:

  • ASSERT_*: 致命斷言,失敗時(shí)終止。
  • EXPECT_*: 非致命斷言,失敗時(shí)不終止。

谷歌推薦使用 EXPECT_* 宏,因?yàn)楫?dāng)測(cè)試中包含多個(gè)的斷言時(shí),它允許繼續(xù)執(zhí)行。斷言有兩個(gè)參數(shù):第一個(gè)參數(shù)是測(cè)試分組的名稱,第二個(gè)參數(shù)是測(cè)試自己的名稱。Generator 只定義了 generate(...) 函數(shù),所以本文中所有的測(cè)試都屬于同一個(gè)測(cè)試組:GeneratorTest。

針對(duì) generate(...) 函數(shù)的測(cè)試可以從 GeneratorTest.cpp 中找到。

引用一致性檢查

generate(...) 函數(shù)有一個(gè) std::stringstream 的引用作為輸入?yún)?shù),并且它也將這個(gè)引用作為返回值。第一個(gè)測(cè)試就是檢查輸入的引用和返回的引用是否一致。

TEST(GeneratorTest, ReferenceCheck){
    const int NumberOfElements = 10;
    std::stringstream buffer;
    EXPECT_EQ(
        std::addressof(buffer),
        std::addressof(Generator::generate(buffer, NumberOfElements))
    );
}

在這個(gè)測(cè)試中我使用 std::addressof 來(lái)獲取對(duì)象的地址,并用 EXPECT_EQ 來(lái)比較輸入對(duì)象和返回對(duì)象是否是同一個(gè)。

檢查元素個(gè)數(shù)

本測(cè)試檢查作為輸入的 std::stringstream 引用中的元素個(gè)數(shù)與輸入?yún)?shù)中指定的個(gè)數(shù)是否相同。

TEST(GeneratorTest, NumberOfElements){
    const int NumberOfElements = 50;
    int nCalcNoElements = 0;
    std::stringstream buffer;
    Generator::generate(buffer, NumberOfElements);
    std::string s_no;
    while(std::getline(buffer, s_no, ' ')) {
        nCalcNoElements++;
    }
    EXPECT_EQ(nCalcNoElements, NumberOfElements);
}

亂序重排

本測(cè)試檢查隨機(jī)化引擎是否工作正常。如果連續(xù)調(diào)用兩次 generate 函數(shù),應(yīng)該得到的是兩個(gè)不同的結(jié)果。

TEST(GeneratorTest, Shuffle){
    const int NumberOfElements = 50;
    std::stringstream buffer_A;
    std::stringstream buffer_B;
    Generator::generate(buffer_A, NumberOfElements);
    Generator::generate(buffer_B, NumberOfElements);
    EXPECT_NE(buffer_A.str(), buffer_B.str());
}

求和校驗(yàn)

與前面的測(cè)試相比,這是一個(gè)大體量的測(cè)試。它檢查 1 到 n 的數(shù)值序列的和與亂序重排后的序列的和是否相等。 generate(...) 函數(shù)應(yīng)該生成一個(gè) 1 到 n 的亂序的序列,這個(gè)序列的和應(yīng)當(dāng)是不變的。

TEST(GeneratorTest, CheckSum){
    const int NumberOfElements = 50;
    int nChecksum_in = 0;
    int nChecksum_out = 0;
    std::vector<int> vNumbersRef(NumberOfElements); // Input vector
    std::iota(vNumbersRef.begin(), vNumbersRef.end(), 1); // Populate vector
    // Calculate reference checksum
    for(const int n : vNumbersRef){
        nChecksum_in += n;
    }
    std::stringstream buffer;
    Generator::generate(buffer, NumberOfElements);
    std::vector<int> vNumbersGen; // Output vector
    std::string s_no;
    // Read the buffer back back to the output vector
    while(std::getline(buffer, s_no, ' ')) {
        vNumbersGen.push_back(std::stoi(s_no));
    }
    // Calculate output checksum
    for(const int n : vNumbersGen){
        nChecksum_out += n;
    }
    EXPECT_EQ(nChecksum_in, nChecksum_out);
}

你可以像對(duì)一般 C++ 程序一樣調(diào)試這些測(cè)試。

CTest

除了嵌入到代碼中的測(cè)試之外,CTest 提供了可執(zhí)行程序的測(cè)試方式。簡(jiǎn)而言之就是通過給可執(zhí)行程序傳入特定的參數(shù),然后用 正則表達(dá)式 對(duì)它的輸出進(jìn)行匹配檢查。通過這種方式可以很容易檢查程序?qū)τ诓徽_的命令行參數(shù)的反應(yīng)。這些測(cè)試定義在頂層的 CMakeLists.txt 文件中。下面我詳細(xì)介紹 3 個(gè)測(cè)試用例:

參數(shù)正常

如果輸入?yún)?shù)是一個(gè)正整數(shù),程序應(yīng)該輸出應(yīng)該是一個(gè)數(shù)列:

add_test(NAME RegularUsage COMMAND Producer 10)
set_tests_properties(RegularUsage
    PROPERTIES PASS_REGULAR_EXPRESSION "^[0-9 ]+"
)

沒有提供參數(shù)

如果沒有傳入?yún)?shù),程序應(yīng)該立即退出并提示錯(cuò)誤原因:

add_test(NAME NoArg COMMAND Producer)
set_tests_properties(NoArg
    PROPERTIES PASS_REGULAR_EXPRESSION "^Enter the number of elements as argument"
)

參數(shù)錯(cuò)誤

當(dāng)傳入的參數(shù)不是整數(shù)時(shí),程序應(yīng)該退出并報(bào)錯(cuò)。比如給 Producer 傳入?yún)?shù) ABC

add_test(NAME WrongArg COMMAND Producer ABC)
set_tests_properties(WrongArg
    PROPERTIES PASS_REGULAR_EXPRESSION "^Error: Cannot parse"
)

執(zhí)行測(cè)試

可以使用 ctest -R Usage -VV 命令來(lái)執(zhí)行測(cè)試。這里給 ctest 的命令行參數(shù):

  • -R <測(cè)試名稱> : 執(zhí)行單個(gè)測(cè)試
  • -VV:打印詳細(xì)輸出

測(cè)試執(zhí)行結(jié)果如下:

$ ctest -R Usage -VV
UpdatecTest Configuration from :/home/stephan/Documents/cpp_testing sample/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/stephan/Documents/cpp_testing sample/build/DartConfiguration.tcl
Test project /home/stephan/Documents/cpp_testing sample/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end

在這里我執(zhí)行了名為 Usage 的測(cè)試。

它以無(wú)參數(shù)的方式調(diào)用 Producer

test 3
    Start 3: Usage
3: Test command: /home/stephan/Documents/cpp testing sample/build/Producer

輸出不匹配 [^[0-9]+] 的正則模式,測(cè)試未通過。

3: Enter the number of elements as argument
1/1 test #3. Usage ................
Failed Required regular expression not found.
Regex=[^[0-9]+]
0.00 sec round.
0% tests passed, 1 tests failed out of 1
Total Test time (real) =
0.00 sec
The following tests FAILED:
3 - Usage (Failed)
Errors while running CTest
$

如果想要執(zhí)行所有測(cè)試(包括那些用 GoogleTest 生成的),切換到 build 目錄中,然后運(yùn)行 ctest 即可:

CTest runCTest run

在 VSCodium 中可以通過點(diǎn)擊信息欄的黃框處來(lái)調(diào)用 CTest。如果所有測(cè)試都通過了,你會(huì)看到如下輸出:

VSCodiumVSCodium

使用 Git 鉤子進(jìn)行自動(dòng)化測(cè)試

目前為止,運(yùn)行測(cè)試是開發(fā)者需要額外執(zhí)行的步驟,那些不能通過測(cè)試的代碼仍然可能被提交和推送到代碼倉(cāng)庫(kù)中。利用 Git 鉤子 可以自動(dòng)執(zhí)行測(cè)試,從而防止有瑕疵的代碼被提交。

切換到 .git/hooks 目錄,創(chuàng)建 pre-commit 文件,復(fù)制粘貼下面的代碼:

#!/usr/bin/sh
(cd build; ctest --output-on-failure -j6)

然后,給文件增加可執(zhí)行權(quán)限:

$ chmod +x pre-commit

這個(gè)腳本會(huì)在提交之前調(diào)用 CTest 進(jìn)行測(cè)試。如果有測(cè)試未通過,提交過程就會(huì)被終止:

Commit failedCommit failed

只有所有測(cè)試都通過了,提交過程才會(huì)完成:

Commit succeededCommit succeeded

這個(gè)機(jī)制也有一個(gè)漏洞:可以通過 git commit --no-verify 命令繞過測(cè)試。解決辦法是配置構(gòu)建服務(wù)器,這能保證只有正常工作的代碼才能被提交,但這又是另一個(gè)話題了。

總結(jié)

本文提到的技術(shù)實(shí)施簡(jiǎn)單,并且能夠幫你快速發(fā)現(xiàn)代碼中的問題。做單元測(cè)試可以提高代碼質(zhì)量,同時(shí)也不會(huì)打斷你的工作流。GoogleTest 框架提供了豐富的特性以應(yīng)對(duì)各種測(cè)試場(chǎng)景,文中我所提到的只是一小部分而已。如果你想進(jìn)一步了解 GoogleTest,我推薦你閱讀 GoogleTest Primer。

責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
相關(guān)推薦

2013-06-04 09:49:04

Spring單元測(cè)試軟件測(cè)試

2017-01-16 12:12:29

單元測(cè)試JUnit

2017-01-14 23:26:17

單元測(cè)試JUnit測(cè)試

2017-03-23 16:02:10

Mock技術(shù)單元測(cè)試

2021-03-28 23:03:50

Python程序員編碼

2017-01-14 23:42:49

單元測(cè)試框架軟件測(cè)試

2023-10-07 08:49:56

測(cè)試驅(qū)動(dòng)開發(fā)Xunit 框架

2011-07-27 13:39:28

iOS GH-Unit 單元測(cè)試

2009-08-19 09:00:48

單元測(cè)試框架自動(dòng)化測(cè)試

2023-07-26 08:58:45

Golang單元測(cè)試

2012-05-17 09:09:05

Titanium單元測(cè)試

2017-02-23 15:59:53

測(cè)試MockSetup

2021-03-24 09:30:02

Jupyter not單元測(cè)試代碼

2012-11-01 11:32:23

IBMdw

2012-11-01 11:37:05

JavaScript單元測(cè)試測(cè)試工具

2023-10-13 18:02:57

JUnitMockito關(guān)系

2024-10-16 16:09:32

2011-06-20 17:25:02

單元測(cè)試

2010-03-04 15:40:14

Python單元測(cè)試

2009-06-08 19:59:09

EclipseJUnit單元測(cè)試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)