C語言單元測試(UT)用例編寫——gtest+stub打樁
stub工具原始碼:https://github.com/coolxv/cpp-stub/tree/master/src
這裡做下簡單的背景介紹,ut的基礎介紹:可以先去看下先去的文章:https://blog.csdn.net/anranjingsi/article/details/106084223
前面也使用過gtest+gmock框架給C/C++做單元測試,但gmock的使用有著明顯的限制:1)必需是C++的類函式詞可以被mock; 2)要求編碼時就要考慮那些函式會被mock,將其定義為虛擬函式;3)需要寫mock類,程式碼量大。
所以對於純C程式碼或者非C++類的程式碼就無法使用gmock來對函式進行mock,這裡推薦使用cpp-stub對C語言程式碼打樁做UT,可以簡單有效的解決UT測試的打樁問題。
cpp-stub的原理:
獲取被打樁函式和樁函式的函式地址,在呼叫被打樁函式時,替換成樁函式。
cpp-stub的簡單教程:
1)安裝:在安裝完gtest後,只需要將stub.h放入到include的目錄中即可;
2)使用:使用也很簡單,首先在測試用例cpp中include "stub.h",然後包含被測試的.c檔案,構建測試程式,對需要程式中出現的一些需要返回指定值的被呼叫函式做樁函式替換即可,可見以下簡單例子:
假設testStub工程有個被測試c檔案func.c:
#include "func.h" int check(int a){ return a+50; } int fun_greater100(int a){ if(check(a) <= 100){ return 0; } return 1; }
這裡我們要測試這個fun_greater100函式,這裡我們先對check函式打樁,讓check函式返回我們希望它返回的數值,以此來測試fun_greater100函式的邏輯否正確,測試工程的用例程式碼如下:
測試用例檔案test_func.cpp:
#include <gtest\gtest.h> #include <gtest\stub.h> #include "..\testStub\func.c" int check_stub1(int a){//check函式的樁函式,與check函式形式一樣 return 50; } TEST(TestSuite1, fun_greater100_1){ Stub stub;//例項化物件 stub.set(check, check_stub1);//這裡設定樁,將check函式替換為check_stub1 int ret = fun_greater100(101);//執行fun_greater100則會呼叫設定的樁函式check_stub1 EXPECT_EQ(ret, 0);//返回的結果為0,而不是1 }
這裡測試用例必定通過,即使我們設定的引數時101,但fun_greater100函式實際呼叫的就是check_stub1函式,所以測試用例通過。
這裡我們再擴充套件一下測試用例:
#include <gtest\gtest.h>
#include <gtest\stub.h>
#include "..\testStub\func.c"
int check_stub1(int a){
return 50;
}
int check_stub2(int a){
return 101;
}
TEST(TestSuite1, fun_greater100_1){
Stub stub;
stub.set(check, check_stub1);
int ret = fun_greater100(101);
EXPECT_EQ(ret, 0);
}
TEST(TestSuite1, fun_greater100_2){
Stub stub;
stub.set(check, check_stub2);
int ret = fun_greater100(50);
EXPECT_EQ(ret, 1);
}
執行結果如下:
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestSuite1
[ RUN ] TestSuite1.fun_greater100_1
[ OK ] TestSuite1.fun_greater100_1 (0 ms)
[ RUN ] TestSuite1.fun_greater100_2
[ OK ] TestSuite1.fun_greater100_2 (0 ms)
[----------] 2 tests from TestSuite1 (8 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (16 ms total)
[ PASSED ] 2 tests.
在git_hub上提供了很多的測試例子,像是C++的類成員、虛擬函式、過載函式等等的打樁都有相關的例子,讀者可自行學習,都是非常的簡單易懂。
cpp-stub的一些問題:
1)不可以對exit函式打樁;
2)不可以對純虛擬函式打樁;
3)不可以對static宣告的普通內部函式打樁。
後面我還會介紹下emock的使用,它是在mockcpp的基礎上做的進一步優化,語法與mockcpp類似,但更加的強大。