我在C++上,使用gtest作为主要框架。假设我有一个要测试的边缘检测函数,它以图像为输入并返回检测到的边缘图像。我有三个图像准备检查。
用一种自我包含的方式写它是不是更好呢?
void EdgeCheck(const std::string& input, const std::string& ans) {
cv::Mat in_img = cv::imread(input);
cv::Mat ans_img = cv::imread(ans);
// Do some checks here
}
TEST(Edge) {
EdgeCheck(std::string("path to image 1"),std::string("path to ans image 1"));
EdgeCheck(std::string("path to image 2"),std::string("path to ans image 2"));
EdgeCheck(std::string("path to image 3"),std::string("path to ans image 3"));
}
int main(int argc, char** argv) {
return UnitTest::RunAllTests();
}因此,这个测试可以通过简单的./unit-test执行,还是编写它更好呢?
TEST(Edge) {
cv::Mat in_img = cv::imread(argv[1]);
cv::Mat ans_img = cv::imread(argv[2]);
// Do some check here
}
int main(int argc, char** argv) {
return UnitTest::RunAllTests();
}但它必须由
./unit-test image1 ans_image1
./unit-test image2 ans_image2
./unit-test image3 ans_image3据我理解,根据UnitTest++命令行参数,第一种方法的优点是“编写良好的单元测试是独立的,而参数化测试意味着测试不再仅仅是测试,它现在是一个函数,而不是单元测试。”
但是,第二种方法的优点是它更灵活,因为如果我想添加image4和image5,我不需要重新编译代码,它可以在bash脚本上完成,但是这样可以使测试不自成体系。
哪种方法被认为是更好的做法?
发布于 2017-07-12 07:00:09
这是关于如何管理您的测试并将它们集成到您的整个环境中。我想你有条件
考虑到这两种解决方案,我认为通过命令行将它们参数化将使您能够更灵活地在单独运行它们与“一次性”运行它们之间进行切换,并且可以更容易地确保失败的测试不会影响其他测试。如果您有这样的需求,也许将它们集成到一个更大的测试套件中也会更容易。然而,这种灵活性并不是免费的。由于需要知道参数,所以当以错误的方式调用命令行程序时,应该会给出一个描述性消息,说明它所期望的参数类型,并且测试执行脚本应该是测试的组成部分。
因此,只要您将命令行程序与脚本一起视为一个独立的组件,只要您提供一些完整的文档,参数化方法就没有什么问题。如果这对你来说不够“自成体系”,那就把事情集成到一个程序中去,但是要接受我提到的其他需求可能需要更多的努力来解决的事实。
发布于 2017-07-12 01:08:19
自动化测试可以参数化,而不依赖于传递的参数。通常,混合方法是最有用的。
例如,如果在没有任何命令行args的情况下运行,您的测试可能会扫描一个已配置的目录,迭代该目录中的所有映像。
在这种情况下,能够覆盖目录可能是有用的,提供命令行参数或指定环境变量是常见的方法。或者,用户可以简单地在默认目录中放置其他图像来扩展测试。
编写良好的单元测试是独立的,参数化测试意味着测试不再仅仅是一个测试。它现在是一个函数,而不是一个单元测试
@Dymeng是正确的,您的测试可能实际上是一个集成测试,而不是一个单元测试,但这并不是重点。单元测试可以参数化,集成测试也可以。
自我控制的关键是很重要的。您应该能够在您的项目上运行测试,而无需指定命令行args,因为如果其他人想要运行您的测试,则需要特殊的知识才能知道要使用哪些正确的参数来运行测试。但是,这个事实不应该阻止您公开在其他数据集上运行测试的方法。
发布于 2017-07-12 07:15:07
很抱歉,但这是我今天听到的最糟糕的主意,原因有几点:
如果实际将数据放入测试中(在变量中),并且(如果可能的话)不从文件加载数据,则是单元测试的最佳选择。
https://softwareengineering.stackexchange.com/questions/352579
复制相似问题