最近寫了一個的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;
}