C++單元測試框架

新寫了一個簡單的單元測試框架,測試用例抽象爲TestCase對象,包含兩個接口:bool exec_case();與void report_result();

調用exec_case時,執行測試用例的單元測試函數(由具體的測試用例給出),將測試結果和相關信息記錄下來;

調用report_result時,將測試結果與相關信息輸出。

 

test_case.h

#ifndef __h_test_case_h__
#define __h_test_case_h__
#include <string>
#include <vector>
#include "test_common.h"

typedef bool (*TestFunc)(std::string& error_msg);

class TestCase
{
public:
	TestCase(const std::string& suite_name, const std::string& case_name, TestFunc test_func);
	~TestCase();

	bool exec_case();

	void report_result();

private:
	std::string m_suite_name;
	std::string m_case_name;
	bool m_result;
	std::string m_result_msg;
	TestFunc m_test_func;
};

int exec_cases(std::vector<TestCase>& test_case_vec);


#endif

test_case.cpp

#include "test_case.h"
#include <iostream>

using namespace std;

TestCase::TestCase(const std::string& suite_name, const std::string& case_name, TestFunc test_func)
{
	m_suite_name = suite_name;
	m_case_name = case_name;
	m_test_func = test_func;
}

TestCase::~TestCase()
{
}

bool TestCase::exec_case()
{
	cout << "ExecCase:[" << m_suite_name << "]\t\t[" << m_case_name << "]" << endl;

	try
	{
		m_result = (*m_test_func)(m_result_msg);
	}
	catch (exception e)
	{
		m_result = false;
		m_result_msg = e.what();
	}
	return m_result;
}

void TestCase::report_result()
{
	cout << endl;
	cout << "TestSuite:\t" << m_suite_name << endl;
	cout << "TestCase:\t" << m_case_name << endl;
	cout << "TestResult:\t " << (m_result ? "Success" : "Fail") << endl;
	cout << "ResultMessage:\t" << m_result_msg << endl << endl;
}


int exec_cases(std::vector<TestCase>& test_case_vec)
{
	int passed_count = 0;
	int failed_count = 0;
	cout << endl << "-------------------Exec Cases-------------------" << endl;
	for (auto it = test_case_vec.begin(); it != test_case_vec.end(); it++)
	{
		if (it->exec_case())
		{
			passed_count++;
		}
		else
		{
			failed_count++;
		}
	}

	cout << endl << "-------------------Report Result-------------------" << endl;
	for (auto it = test_case_vec.begin(); it != test_case_vec.end(); it++)
	{
		it->report_result();
	}

	cout << "Exec " << test_case_vec.size() << " cases, " << passed_count << " passed, " << failed_count << " failed." << endl;

	return failed_count;
}

test_common中定義了幾個斷言宏,在測試用例中用於檢查變量值與預期是否符合。

test_common.h

#ifndef __h_test_common_h__
#define __h_test_common_h__

extern char message_buffer[4096];

void throw_exception(const char* msg);

#define ASSERT_NOT_EQUAL(value1, value2)	\
	if ((value1) == (value2)){				\
		::memset(message_buffer, 0, sizeof(message_buffer));	\
		sprintf(message_buffer, "%s(%d), (%s) == (%s)\n", __FILE__, __LINE__, #value1, #value2);\
		throw_exception(message_buffer);	\
	}

#define ASSERT_EQUAL(value1, value2)		\
	if ((value1) != (value2)){				\
		::memset(message_buffer, 0, sizeof(message_buffer));	\
		sprintf(message_buffer, "%s(%d), (%s) != (%s)\n", __FILE__, __LINE__, #value1, #value2);\
		throw_exception(message_buffer);	\
	}

#define ASSERT_LESS(value1, value2)			\
	if ((value1) >= (value2)){				\
		::memset(message_buffer, 0, sizeof(message_buffer));	\
		sprintf(message_buffer, "%s(%d), (%s) >= (%s)\n", __FILE__, __LINE__, #value1, #value2);\
		throw_exception(message_buffer);	\
	}

#define ASSERT_LESS_EQUAL(value1, value2)	\
	if ((value1) > (value2)){				\
		::memset(message_buffer, 0, sizeof(message_buffer));	\
		sprintf(message_buffer, "%s(%d), (%s) > (%s)\n", __FILE__, __LINE__, #value1, #value2);	\
		throw_exception(message_buffer);	\
	}

#define ASSERT_GREAT(value1, value2)		\
	if ((value1) <= (value2)){				\
		::memset(message_buffer, 0, sizeof(message_buffer));	\
		sprintf(message_buffer, "%s(%d), (%s) <= (%s)\n", __FILE__, __LINE__, #value1, #value2);\
		throw_exception(message_buffer);	\
	}

#define ASSERT_GREAT_EQUAL(value1, value2)	\
	if ((value1) < (value2)){				\
		::memset(message_buffer, 0, sizeof(message_buffer));	\
		sprintf(message_buffer, "%s(%d), (%s) < (%s)\n", __FILE__, __LINE__, #value1, #value2);	\
		throw_exception(message_buffer);	\
	}


#endif

test_common.cpp

#include "test_common.h"
#include <exception>

char message_buffer[4096];


void throw_exception(const char* msg)
{
	std::exception e(msg);
	throw e;
}

test_login中寫了一個簡單的測試用例

test_login.h

#ifndef __h_test_login_h__
#define __h_test_login_h__

#include "test_case.h"


namespace test_login
{
	bool test_login(std::string& error_msg)
	{
		int i = 0;
		ASSERT_GREAT_EQUAL(i, 0);
		return true;
	}

	struct TestLogin : public TestCase
	{
	public:
		TestLogin(const std::string& suite_name = "MDLL_SWSSL_Step_test", const std::string& case_name = "test_login", TestFunc test_func = test_login)
			:TestCase(suite_name, case_name, test_func)
		{

		}
	};
}
#endif

測試入口,main函數所在

test.cpp

#include "test_case.h"
#include "test_login/test_login.h"
#include <iostream>
#include <vector>

using namespace std;
int main()
{
	std::vector<TestCase> test_case_vec;
	test_case_vec.push_back(test_login::TestLogin());

	return exec_cases(test_case_vec);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章