欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
}

 

相关标签: c++ unit test