【发布时间】:2021-08-02 14:56:48
【问题描述】:
我正在从事一个爱好项目,主要是学习 cpp 单元测试和数据库编程。但是,对于如何编写代码以进行正确测试,我有点迷茫和困惑。我倾向于为我的 cpp 项目编写很多 void 函数。但现在我不知道应该如何测试这些功能。我已经成功地测试了非 void 函数,因为它们返回的东西可以很容易地针对一个值进行测试。
阿米我做事不专业?我是否应该尽可能避免使用 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 Test 框架
- 我的整个项目代码托管 - 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);
}
【问题讨论】:
-
函数不仅有返回值,还有副作用。了解它们是什么并测试先决条件
-
我建议您将测试重点放在您希望
Database展示的行为上,而不是其中的个别功能。测试单个功能是测试出错的一种方式。测试每个函数的方法可以使封装看起来像一个问题,而重构是可以避免的。有两件事显然不正确。 -
基本上你的代码依赖于
sqlite3(外部代码)。Database::createDb的功能是处理sqlite3API 的调用。因此,要正确测试这一点,您必须提供依赖注入。这意味着您必须用可以转换为sqlite3API 的内容替换对sqlite3APi 的调用。使用 googletest 有 gmock 工具可以帮助进行测试。 -
在生产代码之后编写测试也更难,当你以相反的方式进行时。当您首先编写测试时,您将专注于假设要测试而不是当前实现的行为。
-
别人说的,不要执着于返回值,在某种意义上这就是实现细节。您无需测试返回例如
int的函数是否真的返回int;),但您想测试行为
标签: c++ unit-testing testing googletest void