使用 google test 进行数据驱动的单元测试

2024-05-03

我目前正在使用以下方法为嵌入式应用程序编写单元测试谷歌单元测试框架 https://github.com/google/googletest。现在,我的老板对我测试的数据(即我调用被测类的方法的值)在测试中是硬连接的感到不安。他请求从文件中读入该数据。他的论点是,因此为之前被遗忘的极端情况添加另一个测试会更容易。我对单元测试没有那么丰富的经验,但到目前为止我并不是这样做的。所以我试图找出最好的方法——即使这样做是个好主意。我很快就发现了 DDT(数据驱动测试)方法。

谷歌单元测试框架有一个功能,他们称之为“值参数化测试 https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#value-parameterized-tests“。这样我的测试装置就变成了一个模板类,我可以传入参数。但是,我发现了一些问题:

  • 我目前每个班级都有一个正在测试的固定装置。但我需要为每个被测方法提供一个固定装置,因为每个方法都需要一组不同的参数。这将是很多额外的工作。
  • 据我所知,我只能传入一个参数。由于我需要几个测试(我的方法的所有参数加上预期结果),这将需要我传递矢量或地图之类的东西。同样,这种构建和检索听起来工作量很大。

我本来可以想象像谷歌测试框架一样成熟的东西可以让它变得更容易。然而,他们写

当您想要通过各种输入测试代码(也称为数据驱动测试)时,值参数化测试会很方便。此功能很容易被滥用,因此请在使用时发挥你的判断力!

另外还有这篇博文TotT:数据驱动陷阱 https://testing.googleblog.com/2008/09/tott-data-driven-traps.html,还警告我(滥用)数据驱动的单元测试。

所以我的问题归结为:

  • 进行数据驱动的单元测试是个好主意吗?
  • 如何使用谷歌测试框架进行数据驱动的单元测试

不过,我并没有真正受限于 googletest,并且基本上可以自由选择我想要的任何框架。

EDIT

我在googletest常见问题解答的FAQ条目中发现了以下声明

一般来说,Google Test 还没有对数据驱动测试提供良好的支持。我们希望能够尽快在这方面做出改进。


GTest 支持它 - 但也许他们不知道......

Use testing::ValuesIn- 就像这个简化的例子一样:

class SomeTests : public TestWithParam<int>
{
public:

};

TEST_P(SomeTests, shouldBePositive)
{
    ASSERT_GT(GetParam(), 0);
}

并且 - 如何从输入流获取值的方式:

std::ifstream inputValuesFromFile("input.txt");
INSTANTIATE_TEST_CASE_P(FromFileStream,
                        SomeTests,
                        ValuesIn(std::istream_iterator<int>(inputValuesFromFile), 
                                 std::istream_iterator<int>()));

要使用比“int”更复杂的类型,您需要为其编写一个运算符 >> - 例如:

struct A
{
    int a;
    std::vector<int> b;
}
std::istream& operator >> (std::istream& is, A& out)
{
     std::size_t bSize;
     if ((is >> A.a) && (is >> bSize))
     {
         out.b.reserve(bSize);
         while (bSize-- > 0)
         {
             int b;
             if (!(is >> b))
                break;
             out.b.push_back(b);   
         }
     }
     return is;
}

当然 - 在更复杂的情况下 - 考虑使用类似 XMl(json?)的格式和一些比std::istream_iterator<T>.


对于类似 XML 的格式,您可能会考虑这样的方案(这是非常假设的代码 - 我心中没有任何这样的库):

SomeLib::File xmlData("input.xml");

class S1BasedTests : public TestWithParam<S1>
{};

TEST_P(S1BasedTests , shouldXxxx)
{
    const S1& s1 = GetParam();
    ...
}
auto s1Entities = file.filterBy<S1>("S1");
INSTANTIATE_TEST_CASE_P(S1,
                        S1BasedTests,
                        ValuesIn(s1Entities.begin(), s1Entities .end()));

// 等等你想要的任何类型 S1


如果市场上没有这样的 C++ 类型友好的库(我搜索了 2 分钟但没有找到) - 那么可能是这样的:

SomeLib::File xmlFile("input.xml");

struct S1BasedTests : public TestWithParam<SomeLib::Node*>
{
   struct S1 // xml=<S1 a="1" b="2"/>
   {
       int a;
       int b;
   };
   S1 readNode()
   {
        S1 s1{};
        s1.a = GetParam()->getNode("a").getValue<int>();
        s1.b = GetParam()->getNode("b").getValue<float>();
        return s1;
   }
};

TEST_P(S1BasedTests , shouldXxxx)
{
    const S1& s1 = readNode();
    ...
}
INSTANTIATE_TEST_CASE_P(S1,
                        S1BasedTests ,
                        ValuesIn(xmlFile.getNode("S1").getChildren()));
                        // xml=<S1s> <S1.../> <S1.../> </S1>

// 等等对于任何节点类型,如 S1

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 google test 进行数据驱动的单元测试 的相关文章

随机推荐

  • AutoCAD 插件开发示例

    我对开发 AutoCAD 插件感兴趣 并试图了解几种不同类型的 AutoCAD 插件文件之间的关系 随 AutoCAD 插件一起提供的托管 DLL ARX 文件 https fileinfo com extension arx附带 Auto
  • 如何在 SQLite 中插入换行符(“\n”)?

    在尝试插入类似以下内容时 Hello nWorld SQLite 抛出类似以下的错误 消息 无法识别的令牌 Hello 还有一些其他错误 即使我将上面的字符串转换为 Hello nWorld or Hello n World 这些转义字符序
  • 退格事件麻烦

    我在第 1 页有一个事件侦听器 window addEventListener keydown 这给我带来了问题 即第 1 页对话框中的另一个事件侦听器 keydown 与窗口事件侦听器发生冲突 有两个事件监听器 对话框事件监听器 页面事件
  • 使用畸变从图像平面计算相机矢量

    我正在尝试使用相机模型来重建可以使用某些相机及其 外部 内部 参数拍摄的图像 这一点我没有任何问题 现在我想添加扭曲 正如它们中所描述的那样OpenCV https docs opencv org 4 x dc dbb tutorial p
  • React TypeScript - 将动态泛型类型传递到forwardRef组件中

    我的问题的核心 const FinalComponent
  • 机器和管道(或其他类似的库)之间的概念区别是什么?

    我想学习这个概念 以便我能够理解和使用诸如machines http hackage haskell org package machines 我试着跟随R nar Bjarnason 关于机器的演讲 https dl dropbox co
  • 授予对视图的 SELECT 权限,但不授予对基础对象的 SELECT 权限

    我经常读到 视图的目的之一是安全性 允许某些用户访问基础表 而其他用户仅访问派生视图 考虑到这一点 我设计了几个向外部用户提供受限数据集的视图 一切都很好 但在实践中这是行不通的 我授予后SELECT对视图的权限 除非我授予 否则用户无法访
  • XPath 直到下一个标签

    与之前在这里问过的其他人类似的问题 但由于我不知道如何应用这些建议 所以我需要一些帮助 我想找到一个 html 文档的节点 其结构如下 摘录 可能有所不同 h2 My title 1 h2 h3 Sub heading h3 p span
  • Laravel Schema onDelete 设置为 null

    无法弄清楚如何在 Laravel 中的表上设置正确的 onDelete 约束 我正在使用 SqLite table gt gt onDelete cascade works table gt gt onDelete null set nul
  • .Net 如何创建一个在进程的所有AppDomain之间共享的自定义ThreadPool?

    我制作了一个针对我的特定需求进行优化的自定义线程池 但是 当进程中有多个 AppDomain 时 CLR ThreadPool 能够在所有 AppDomain 之间共享 我希望能够重现这种行为 这可以使用 MarshalByRefObjec
  • 集合划分比差分获得更好的结果

    分区问题 https en wikipedia org wiki Partition problem已知是 NP 困难的 根据问题的特定实例 我们可以尝试动态规划或一些启发式方法 例如差分法 也称为 Karmarkar Karp 算法 后者
  • 使用 selenium web 驱动程序时如何在测试执行后保持浏览器打开

    我的脚本在浏览器的不同选项卡中搜索不同的字符串 有没有办法在测试执行结束后保持浏览器打开 以便稍后检查结果 目前 即使我没有使用 driver quit 浏览器也会在 5 分钟后自动关闭 Selenium 2 33 Win 7 FF 和 C
  • Python:比较字符串与重音字符不起作用

    我对 python 很陌生 我正在尝试从另一个列表中删除一个列表中出现的文件 这些列表是通过在 mac 和 windows 上重定向 ll R 生成的 但自从使用其他 python 脚本进行了一些处理 合并 排序等 某些文件名带有重音符号和
  • 预取双类成员需要转换为 char*?

    我有一个正在使用的课程 mm prefetch 预先请求包含 double 类型的类成员的缓存行 class MyClass double getDouble return dbl other members double dbl othe
  • Facebook 登录中未定义 FB

    我有以下代码 但 FB login 给出了 FB 未定义 javascript 错误 我缺少什么 div div
  • React Native:.matchAll 不是函数

    运行我的 React Native 应用程序时出现奇怪的错误 一些示例代码 const url
  • 重置表单的最简洁方法

    在 Angular 2 最新版本中重置表单的最简洁方法是什么 我想在添加帖子后重置输入文本框 Component selector post div template h2 Posts h2
  • SQL Server 上的 pyodbc - 如何执行插入并取回行 ID?

    我将 pyodbc 与 SQL Server 2000 一起使用 我希望能够插入一行并获取自动递增的行 id 值 有任何想法吗 这是我到目前为止所拥有的 cursor execute insert into products id name
  • CSS“混合混合模式”的测试

    我想使用CSS的属性 mix blend mode soft light 我将通过 Modernizr 测试后备 bla bla Tested Modernizr mixblendmode undefined Modernizr testP
  • 使用 google test 进行数据驱动的单元测试

    我目前正在使用以下方法为嵌入式应用程序编写单元测试谷歌单元测试框架 https github com google googletest 现在 我的老板对我测试的数据 即我调用被测类的方法的值 在测试中是硬连接的感到不安 他请求从文件中读入