C++简单单元测试类
程序员文章站
2022-06-01 16:53:03
...
参考自LEVELDB中的单元测试类
头文件(testharness.h):
#ifndef TEST_HARNESS_H_
#define TEST_HARNESS_H_
#include <sstream>
namespace simpleut {
namespace test {
//执行所有的单元测试
extern int RunAllTest();
class Tester {
private:
bool ok_;
const char* fname_;
int line_;
std::stringstream ss_;
public:
Tester(const char* f, int l):
ok_(true), fname_(f), line_(l) {}
~Tester() {
if (!ok_) {
fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str());
exit(1);
}
}
Tester& Is(bool b, const char* msg) {
if (!b) {
ss_ << " Assertion failed " << msg;
ok_ = false;
}
return *this;
}
#define BINARY_OP(name, op) \
template<class X, class Y> \
Tester& name(const X& x, const Y& y) { \
if (!(x op y)) { \
ss_ << " failed: " << x << (" " #op " ") << y; \
ok_ = false; \
}; \
return *this; \
}
BINARY_OP(IsEq, ==)
BINARY_OP(IsNe, !=)
BINARY_OP(IsGe, >=)
BINARY_OP(IsGt, >)
BINARY_OP(IsLe, <=)
BINARY_OP(IsLt, <)
#undef BINARY_OP
template<class V>
Tester& operator<<(const V& value) {
ss_ << " " << value;
return *this;
}
}; //Tester
#define ASSERT_TRUE(c) ::simpleut::test::Tester(__FILE__, __LINE__).Is((c), #c)
#define ASSERT_EQ(a, b) ::simpleut::test::Tester(__FILE__, __LINE__).IsEq((a), (b))
#define ASSERT_NE(a, b) ::simpleut::test::Tester(__FILE__, __LINE__).IsNe((a), (b))
#define ASSERT_GE(a, b) ::simpleut::test::Tester(__FILE__, __LINE__).IsGe((a), (b))
#define ASSERT_GT(a, b) ::simpleut::test::Tester(__FILE__, __LINE__).IsGt((a), (b))
#define ASSERT_LE(a, b) ::simpleut::test::Tester(__FILE__, __LINE__).IsLe((a), (b))
#define ASSERT_LT(a, b) ::simpleut::test::Tester(__FILE__, __LINE__).IsLt((a), (b))
#define TCONCAT(a, b) TCONCAT1(a, b)
#define TCONCAT1(a, b) a##b
#define TEST(base, name) \
class TCONCAT(_Test_, name) : public base { \
public: \
void _Run(); \
static void _RunIt() { \
TCONCAT(_Test_, name) t; \
t._Run(); \
} \
}; \
bool TCONCAT(_Test_ignored_, name) = \
::simpleut::test::RegisterTest(#base, #name, &TCONCAT(_Test_, name)::_RunIt); \
void TCONCAT(_Test_, name)::_Run()
extern bool RegisterTest(const char* base, const char* name, void (*func)());
}
}
#endif //TEST_HARNESS_H_
CPP文件(testharness.cpp):
#include "testharness.h"
#include <vector>
namespace simpleut {
namespace test {
namespace {
struct Test {
const char* base;
const char* name;
void (*func)();
};
std::vector<Test>* tests;
}
bool RegisterTest(const char* base, const char* name, void (*func)()) {
if (tests == NULL) {
tests = new std::vector<Test>;
}
Test t;
t.base = base;
t.name = name;
t.func = func;
tests->push_back(t);
return true;
}
int RunAllTest() {
int num = 0;
if (tests != NULL) {
for (size_t i=0; i<tests->size(); ++i) {
const Test& t = (*tests)[i];
fprintf(stderr, "++++ Test %s.%s\n", t.base, t.name);
(*t.func)();
num++;
}
fprintf(stderr, "==== PASSED %d tests\n", num);
}
return 0;
}
}
}
使用代码:
#include "testharness.h"
int add(int a, int b) {
return a + b;
}
class SimpleTest {};
TEST(SimpleTest, AddTest) {
int result = add(2, 3);
ASSERT_EQ(result, 5);
}
int main(int argc, char* argv[]) {
::simpleut::test::RunAllTest();
return 0;
}