1. 简介
1.1 什么是好的测试?
- 独立可重复
- 精心组织并反映测试代码结构
- 测试可移植和重用,即可跨平台
- 测试通过失败时能提供尽可能多的信息
- 测试框架应该将程序员从杂活中解放出来,而只关注测试的具体内容
- 测试足够快
1.2 基本概念
assertion: 判断条件是是否正确
assertion 结果: success、nonfatal failure、fatal failure
test: 一个或多个assertion
test suite: 一个或多个test
1.3 Assertion
ASSERT_ *失败是FATAL FAILURE
EXPECT_*失败产生NONFATAL FAILURE
使用样例
ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
for (int i = 0; i < x.size(); ++i) {
EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}
1.4 简单测试
用法
TEST(TestSuiteName, TestName) {
... test body ...
}
样例
int Factorial(int n);
// Tests factorial of 0.
TEST(FactorialTest, HandlesZeroInput) {
EXPECT_EQ(Factorial(0), 1);
}
// Tests factorial of positive numbers.
TEST(FactorialTest, HandlesPositiveInput) {
EXPECT_EQ(Factorial(1), 1);
EXPECT_EQ(Factorial(2), 2);
EXPECT_EQ(Factorial(3), 6);
EXPECT_EQ(Factorial(8), 40320);
}
1.5 test fixture
对多个测试设置的同一个数据对象
创建步骤
- 继承testing::Test, 从protected标识写
- 定义要用的对象
- 写*SetUp()和TearDown()*函数
样例
class QueueTest : public testing::Test {
protected:
QueueTest() {
// q0_ remains empty
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
}
// ~QueueTest() override = default;
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
};
TEST_F(QueueTest, IsEmptyInitially) {
EXPECT_EQ(q0_.size(), 0);
}
TEST_F(QueueTest, DequeueWorks) {
int* n = q0_.Dequeue();
EXPECT_EQ(n, nullptr);
n = q1_.Dequeue();
ASSERT_NE(n, nullptr);
EXPECT_EQ(*n, 1);
EXPECT_EQ(q1_.size(), 0);
delete n;
n = q2_.Dequeue();
ASSERT_NE(n, nullptr);
EXPECT_EQ(*n, 2);
EXPECT_EQ(q2_.size(), 1);
delete n;
}
2. 构建环境
git clone https://github.com/google/googletest.git
cd dir_to_googletest
mkdir build && cd build
cmake .. -DBUILD_SHARED_LIB=ON
make && make install
cmake 中包含头文件和库路径
include(GoogleTest)
target_link_directories(prj_name PUBLIC /usr/local/lib)
3. 使用
FileHelper.h
#ifndef FILE_HELPER_H
#define FILE_HELPER_H
#include <cstdint>
#include <string>
#include <sys/stat.h>
class FileHelper
{
public:
FileHelper();
~FileHelper();
bool open(const char *file, const char *mode);
void close();
std::size_t get_file_sz();
std::string get_file_type();
int put_one_char();
void reset();
// void *ptr, size_t size, size_t nmemb, FILE *stream
void read(void *ptr, size_t sz, size_t nmemb, size_t offset);
void read_next_one(void *ptr, size_t sz);
void append(void *ptr, size_t sz, size_t nmemb);
void append_one(void *ptr, size_t sz);
void write(void *ptr, size_t sz, size_t nmemb, size_t offset);
void modify(void *ptr, size_t sz, size_t nmemb, size_t offset);
friend class BitBufferWriter;
friend class BitBufferReader;
private:
std::string cur_file_name;
FILE *fp;
struct stat file_status;
};
#endif
FileHelper_unittest.cpp
#include "FileHelper.h"
#include <gtest/gtest.h>
#include <endian.h>
TEST(fHelper, openFile) {
FileHelper s;
EXPECT_EQ(s.open("hello", "r"), false) << "open regular file";
EXPECT_EQ(s.open("list.txt","r"), true) << "open a not exist file";
}
TEST(fHelper, readFile) {
FileHelper s;
s.open("list.txt", "r");
EXPECT_EQ(s.get_file_sz(), 26) << "get file size";
EXPECT_STREQ(s.get_file_type().c_str(), "regular file\n") << "get file type string";
}
TEST(fHelper, writeFile) {
FileHelper s;
s.open("list.txt", "rw+");
int sz_0 = s.get_file_sz();
int wval = 0x01020304;
s.append_one(&wval, sizeof(sz_0));
s.close();
s.open("list.txt", "r");
uint8_t val;
s.read(&val, sizeof(uint8_t), 1, 26);
EXPECT_EQ(val, 4);
}
参考
[googletest](GoogleTest User’s Guide | GoogleTest)
[set_up_googletest](Setting up GoogleTest as a Shared Library in Linux | Baeldung on Linux)