1. 背景
工程中涉及基础接口的设计,为了保证接口的质量,所以需要进行单元测试:
单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。
单元测试需要构建测试代码(开源软件中一般都提供了tests目录),测试代码需要制造测试数据,对case进行覆盖,并统计case的成功率。所以说测试框架的功能比较繁琐,一般使用第三方框架来实现代码的unit-test。
本节对google的开源框架进行实践,并对libevent源码进行一个ut的编写测试。
(gtest相关知识章节比较多,本节仅对最常使用的断言部分进行列举)
2. gtest 断言
GTest使用最多的就是断言了,与系统assert不同,到了断言部分并不会导致整个程序退出,并且能够统计相关信息。
GTest中断言都是成对出现的。即分为两个系列:
- ASSERT_*系列;
- EXPECT_*系列;
EXPECT_*系列是比较常用的。在一个测试Case中,如果局部测试使用了EXPECT_*系列函数,它将保证本次局部测试结果不会影响之后的流程。但是ASSERT_*系列在出错的情况下,当前测试Case中剩下的流程就不走了。
2.1 布尔值判断
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_TRUE(condition); | EXPECT_TRUE(condition); | condition is true |
ASSERT_FALSE(condition); | EXPECT_FALSE(condition); | condition is false |
2.2 二进制比较
Fatal assertion | Nonfatal assertion | Verifies | Note |
---|---|---|---|
ASSERT_EQ(val1,val2); | EXPECT_EQ(val1,val2); | val1 == val2 | equal |
ASSERT_NE(val1,val2); | EXPECT_NE(val1,val2); | val1 != val2 | not equal |
ASSERT_LT(val1,val2); | EXPECT_LT(val1,val2); | val1 < val2 | less than |
ASSERT_LE(val1,val2); | EXPECT_LE(val1,val2); | val1 <= val2 | less equal |
ASSERT_GT(val1,val2); | EXPECT_GT(val1,val2); | val1 > val2 | greater than |
ASSERT_GE(val1,val2); | EXPECT_GE(val1,val2); | val1 >= val2 | greater equal |
2.3 字符串比较
字符串主要用于string、char * 类型:
Fatal assertion | Nonfatal assertion | Verifies | Note |
---|---|---|---|
ASSERT_STREQ(str1,str2); | EXPECT_STREQ(str1,_str_2); | the two C strings have the same content string | equal |
ASSERT_STRNE(str1,str2); | EXPECT_STRNE(str1,str2); | the two C strings have different content string | not equal |
ASSERT_STRCASEEQ(str1,str2); | EXPECT_STRCASEEQ(str1,str2); | the two C strings have the same content, ignoring case | string (ignoring) case equal |
ASSERT_STRCASENE(str1,str2); | EXPECT_STRCASENE(str1,str2); | the two C strings have different content, ignoring case | string (ignoring) case not euqal |
2.4 浮点数比较
浮点数比较,默认的是是指两者的差值在4ULP之内(Units in the Last Place)。
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_FLOAT_EQ(val1, val2); | EXPECT_FLOAT_EQ(val1, val2); | the two float values are almost equal |
ASSERT_DOUBLE_EQ(val1, val2); | EXPECT_DOUBLE_EQ(val1, val2); | the two double values are almost equal |
我们还可以自己制定精度:
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_NEAR(val1, val2, abs_error); | EXPECT_NEAR(val1, val2, abs_error); | the difference between val1 and val2 doesn’t exceed the given absolute error |
3. 实践
本小节针对 libevent中 evbuffer接口进行一个单元测试,根据源码 test/regress_buffer.c
进行一个修改
3.1 框架使用
main函数比较简单,对gtest整体实例进行一个初始化:
int main(int argc, char *argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
在测试过程中,我们需要在每个Case中使用一个随机字符串,用于测试输入输出使用,
该字符串生命周期为一个Case,借助于gtest,我们可以在每个Case自带的实例,在构造函数进行完成我们的功能:
#include <gtest/gtest.h>
#include <openssl/rand.h>
class sdk_buffer :
public testing::Test,
public ::testing::WithParamInterface<int>
{
public:
virtual void TearDown()
{
}
sdk_buffer