新写了一个简单的单元测试框架,测试用例抽象为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
#include
#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& test_case_vec);
#endif
test_case.cpp
#include "test_case.h"
#include
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& 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
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
#include
using namespace std;
int main()
{
std::vector test_case_vec;
test_case_vec.push_back(test_login::TestLogin());
return exec_cases(test_case_vec);
}