最近写了一个的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 <iostream>
#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;
}