先编译出sample2,在test/src/samples/CMakeLists.txt 文件最后添加编译规则。
add_executable(sample2_unittest sample2.cc sample2_unittest.cc)
target_link_libraries(sample2_unittest PUBLIC gtest gtest_main)
sample2源码定义的方法
sample2.cc和sample2.h 定义了一个名为MyString的类,定义了一些常见的字符串操作方法。
sample2_unittest中定义的测试
sample2_unittest中展示了如何为测试一个拥有成员函数的类。
首先对MyString类的默认构造函数进行测试,TEST编写方式如上:
TEST(MyString, DefalutConstructor) {
const MyString s;
EXPECT_STREQ(nullptr, s.c_string());
EXPECT_EQ(0u, s.Length());
}
访问s.c_string()
方法会返回MyString内部的属性c_string_
,由于使用默认构造方法构造出s,因此s.c_string()
会返回nullptr
。而s.Length()
则使用c库的strlen()
方法求内部属性c_string_
的长度,因此会返回0。
接着是测试接受一个C string类型参数的构造方法:
const char KHelloString[] = "Hello, world!";
TEST(MyString, ConstructFromString) {
const MyString s(KHelloString);
EXPECT_EQ(0, strcmp(s.c_string(), KHelloString));
EXPECT_EQ(sizeof(KHelloString)/sizeof(KHelloString[0]) - 1, s.Length());
}
首先用c的strcmp()
测试了构造出的c_string_
是否与参数KHelloString
内容是否相同,而后则是判断两者长度是否相同。
接着是测试MyString的拷贝构造函数:
TEST(MyString, CopyConstructor) {
const MyString s1(kHelloString);
const MyString s2 = s1;
EXPECT_EQ(0, strcmp(s2.c_string(), kHelloString));
}
测试内容和上面的测试类似,首先使用相同的c字符串构造出一个MyString类s1
,而后使用const MyString s2 = s1;
调用MyString的拷贝构造函数拷贝出另一个内容完全相同的s2
。
接下来则是比较两者的成员c_string_
内容是否完全相同。
最后则是测试其中的Set方法,以下是内容:
TEST(MyString, Set) {
MyString s;
s.Set(kHelloString);
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
s.Set(s.c_string());
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
s.Set(nullptr);
EXPECT_STREQ(nullptr, s.c_string());
}
先说Set()
方法的作用,它接受一个C类型字符串,而后拷贝一份字符串,然后将自己的成员c_string_
析构掉,最后在将拷贝出的C类型字符串赋值给自己的成员。
总结一下:测试类的方法步骤首先在每个Test宏中构造一个要测试类的实力,而后根据类成员方法的返回值(如使用Length()
方法或c_string()
方法,根据其返回值判断其正确性)、或者其作用(如各种构造函数或Set()
根据其对成员c_string_
的修改结果判断其正确性)。
另外对C类型字符串比较使用
EXPECT_STREQ(expected, actual);
而非
EXPECT_EQ(expected, actual);
当然,也可以借助c的strcmp方法根据其返回值作测试。