如何在 C++ 中对 void 函数进行单元测试
How to unit test a void function in C++
我在做一个业余项目,主要是学习cpp单元测试和数据库编程。但是,对于如何编写代码以进行适当的测试,我有点迷茫和困惑。我倾向于为我的 cpp 项目编写很多 void 函数。但是现在我不知道应该如何测试这些功能。我已经成功地测试了非 void 函数,因为它们 return 可以很容易地针对一个值进行测试的东西。
阿米我做事不专业?我是否应该尽可能避免 void 函数,以便我可以测试这些函数?或者我错过了什么?例如,我将如何测试此功能 -
database.cpp
#include "database.hpp"
#include <sqlite3.h>
#include <iostream>
#include "spdlog/sinks/basic_file_sink.h"
// Creating the logging object
auto logger = spdlog::basic_logger_mt("appnotex", "../data/appnotexlog");
void Database::createDb(const char *dbname) {
// Creating the database file
sqlite3 *datadb;
int status = sqlite3_open(dbname, &datadb);
// checking for errors
if (status == SQLITE_OK) {
logger->info("------------ New Session ----------");
logger->info("Connected to Database Successfully");
} else {
std::string errorMessage = sqlite3_errmsg(datadb);
logger->info("Error: " + errorMessage);
}
如果需要
- 我正在使用Google测试框架
- 我托管了整个项目代码 - here
更新
这个我试过了,这个方法测试上面的方法是否正确?
databaseTest.cpp
TEST(DatabaseTest, createDbTest) {
const char *dbfilename = "../data/test/data.db";
const char *tbname = "DataTest";
Database *db = new Database();
std::ifstream dbfile("../data/test/data.db");
bool ok = false;
if (!dbfile.is_open())
ok = false;
else
ok = true;
EXPECT_TRUE(ok);
}
问题不在于函数 returning void
。考虑它如何发出错误信号并确保所有情况(成功和失败)都经过测试,就这么简单。
但是,除了记录它之外,我在那里根本看不到任何错误信号。根据经验,日志记录只能用于 post-mortem 研究等。因此,如果日志记录完全失败,您的程序仍然可以 运行 正确。这意味着,内部没有任何东西依赖于它并且它不是一个合适的错误 handling/signalling 机制。
现在,基本上有三种方式来指示错误:
- Return 值。通常用于 C 代码,有时也用于 C++。对于
void
return,这不是一个选项,这可能是您问题的来源。
- 例外情况。您可以
throw std::runtime_error("DB connect failed");
并将其处理委托给调用代码。
- 副作用。您可以将连接状态存储在
Database
实例中。为了完整起见,也可以使用全局 errno
,但不可取。
无论如何,这三种方式都可以在单元测试中得到锻炼和验证。
我在做一个业余项目,主要是学习cpp单元测试和数据库编程。但是,对于如何编写代码以进行适当的测试,我有点迷茫和困惑。我倾向于为我的 cpp 项目编写很多 void 函数。但是现在我不知道应该如何测试这些功能。我已经成功地测试了非 void 函数,因为它们 return 可以很容易地针对一个值进行测试的东西。
阿米我做事不专业?我是否应该尽可能避免 void 函数,以便我可以测试这些函数?或者我错过了什么?例如,我将如何测试此功能 -
database.cpp
#include "database.hpp"
#include <sqlite3.h>
#include <iostream>
#include "spdlog/sinks/basic_file_sink.h"
// Creating the logging object
auto logger = spdlog::basic_logger_mt("appnotex", "../data/appnotexlog");
void Database::createDb(const char *dbname) {
// Creating the database file
sqlite3 *datadb;
int status = sqlite3_open(dbname, &datadb);
// checking for errors
if (status == SQLITE_OK) {
logger->info("------------ New Session ----------");
logger->info("Connected to Database Successfully");
} else {
std::string errorMessage = sqlite3_errmsg(datadb);
logger->info("Error: " + errorMessage);
}
如果需要
- 我正在使用Google测试框架
- 我托管了整个项目代码 - here
更新
这个我试过了,这个方法测试上面的方法是否正确?
databaseTest.cpp
TEST(DatabaseTest, createDbTest) {
const char *dbfilename = "../data/test/data.db";
const char *tbname = "DataTest";
Database *db = new Database();
std::ifstream dbfile("../data/test/data.db");
bool ok = false;
if (!dbfile.is_open())
ok = false;
else
ok = true;
EXPECT_TRUE(ok);
}
问题不在于函数 returning void
。考虑它如何发出错误信号并确保所有情况(成功和失败)都经过测试,就这么简单。
但是,除了记录它之外,我在那里根本看不到任何错误信号。根据经验,日志记录只能用于 post-mortem 研究等。因此,如果日志记录完全失败,您的程序仍然可以 运行 正确。这意味着,内部没有任何东西依赖于它并且它不是一个合适的错误 handling/signalling 机制。
现在,基本上有三种方式来指示错误:
- Return 值。通常用于 C 代码,有时也用于 C++。对于
void
return,这不是一个选项,这可能是您问题的来源。 - 例外情况。您可以
throw std::runtime_error("DB connect failed");
并将其处理委托给调用代码。 - 副作用。您可以将连接状态存储在
Database
实例中。为了完整起见,也可以使用全局errno
,但不可取。
无论如何,这三种方式都可以在单元测试中得到锻炼和验证。