C++单元测试

最近写了一个的C++单元测试工具,在这里分享一下对测试用例(TestCase)的定义。

其中用到的MDB是用C++写的内存数据库,ExpectMDB则是一个仅用set容器实现的简化版的数据库。

测试用例的执行函数是一个返回值为bool类型的无参函数,测试用例执行完后的数据在MDB中,对执行结果的期望数据,通过CSV文件导入到ExpectMDB中,通过check_mdb_tables对两者中每个表的数据逐一核对。

test_case.h

#ifndef __h_test_case_h__
#define __h_test_case_h__

#include "expect_mdb.h"
#include "mdb.h"

typedef bool (*TestFunc)();

struct CaseBase
{
	CaseBase(const string& suite_name, const string& case_name, TestFunc test_func)
	{
		m_suite_name = suite_name;
		m_case_name = case_name;
		m_test_func = test_func;
	}
	string m_suite_name;
	string m_case_name;
	TestFunc m_test_func;
};

class TestCase
{
public:
	TestCase(MDB* mdb, const string& suite_name, const string& case_name, const string& init_file_path, const string& expect_file_path, const string& result_file_path, TestFunc test_func);
	TestCase(const TestCase&) = delete;
	TestCase& operator=(const TestCase&) = delete;
	TestCase(TestCase&&);
	TestCase& operator=(TestCase&&);
	~TestCase();

	bool exec_case();

	void report_result();

private:
	void load_case();

	bool check_expect();

	string m_suite_name;
	string m_case_name;
	string m_init_file_path;
	string m_expect_file_path;
	string m_result_file_path;
	bool m_result;
	char m_result_msg[4096];
	MDB* m_mdb;
	ExpectMDB* m_expect_mdb;
	TestFunc m_test_func;
};

TestCase get_case(const CaseBase& case_base);


#endif

test_case.cpp

#include "test_case.h"
#include 
#include "init.h"
#include "load_init_md.h"
#include "load_init_tables.h"
#include "load_expect_tables.h"
#include "check_mdb_tables.h"
#include "kernel_global.h"

using namespace std;

TestCase::TestCase(MDB* mdb, const string& suite_name, const string& case_name, const string& init_file_path, const string& expect_file_path, const string& result_file_path, TestFunc test_func)
{
	m_mdb = mdb;
	m_expect_mdb = new ExpectMDB();
	m_suite_name = suite_name;
	m_case_name = case_name;
	m_init_file_path = init_file_path;
	m_expect_file_path = expect_file_path;
	m_result_file_path = result_file_path;
	m_test_func = test_func;
}

TestCase::TestCase(TestCase&& test_case)
{
	m_mdb = test_case.m_mdb;
	m_expect_mdb = test_case.m_expect_mdb;
	test_case.m_expect_mdb = nullptr;

	m_suite_name = test_case.m_suite_name;
	m_case_name = test_case.m_case_name;
	m_init_file_path = test_case.m_init_file_path;
	m_expect_file_path = test_case.m_expect_file_path;
	m_result_file_path = test_case.m_result_file_path;
	m_test_func = test_case.m_test_func;
}
TestCase& TestCase::operator=(TestCase&& test_case)
{
	m_mdb = test_case.m_mdb;
	m_expect_mdb = test_case.m_expect_mdb;
	test_case.m_expect_mdb = nullptr;

	m_suite_name = test_case.m_suite_name;
	m_case_name = test_case.m_case_name;
	m_init_file_path = test_case.m_init_file_path;
	m_expect_file_path = test_case.m_expect_file_path;
	m_result_file_path = test_case.m_result_file_path;
	m_test_func = test_case.m_test_func;
	return *this;
}

TestCase::~TestCase()
{
	if (m_expect_mdb)
		delete m_expect_mdb;
}

void TestCase::load_case()
{
	load_init_tables(m_mdb, m_init_file_path.c_str());
	load_init_md(m_init_file_path.c_str());

	load_expect_tables(m_expect_mdb, m_expect_file_path.c_str());
}

bool TestCase::exec_case()
{
	cout << "ExecCase:" << m_case_name << endl;
	load_case();

	m_result = (*m_test_func)();
	m_mdb->dump(m_result_file_path.c_str());
	if (m_result)
	{
		check_expect();
	}
	else
	{
		sprintf(m_result_msg, "Exec Case [%s] failed.", m_case_name.c_str());
	}

	return m_result;
}

bool TestCase::check_expect()
{
	m_result = check_mdb_tables(m_mdb, m_expect_mdb, m_result_msg);
	if (m_result)
		sprintf(m_result_msg, "Exec Case [%s] success.", m_case_name.c_str());
	return m_result;
}

void TestCase::report_result()
{
	cout << endl;
	cout << "TestSuite:" << m_suite_name << endl;
	cout << "TestCase:" << m_case_name << endl;
	cout << "TestResult: " << (m_result ? "Successful" : "Failed") << endl;
	cout << "ResultMessage:" << m_result_msg << endl << endl;
}

TestCase get_case(const CaseBase& case_base)
{
	string init_dir = "../cases/" + case_base.m_suite_name + "/" + case_base.m_case_name + "/init";
	string expect_dir = "../cases/" + case_base.m_suite_name + "/" + case_base.m_case_name + "/expect";
	string result_dir = "../cases/" + case_base.m_suite_name + "/" + case_base.m_case_name + "/result";
	TestCase test_case(g_mdb, case_base.m_suite_name, case_base.m_case_name, init_dir, expect_dir, result_dir, case_base.m_test_func);
	return test_case;
}

 

你可能感兴趣的:(C++,UnitTest,紫云的程序人生)