• Google C++单元测试框架(Gtest)系列教程之六——FAQ节选


    这一节,我们来看Gtest的FAQ(Frequently-Asked Questions)。


    为什么测试用例和测试实例命名中不应包含下划线

    在C++中,对于以下情况,相应的标识可能会被编译器或标准库使用:

    1. 以下划线开始并紧接一个大写字母的标识
    2. 包含连续两个下划线的标识

    为避免标识符冲突,用户代码中不应自定义以上两种情况的标识。使用TEST()或TEST_F()时,滥用下划线,将有可能产生标志符命名冲突。

    当我们定义以下测试实例并执行测试程序时,Gtest会为我们生成一个名为TestCaseName_TestName_Test的类。

    TEST(TestCaseName, TestName)

    如果TestCaseName或TestName中包含下划线,情况会怎样呢?

    • TestCaseName以"_"开头(例如_Foo),我们得到_Foo_TestName_Test
    • TestCaseName以"_"结尾(例如Foo_),我们得到Foo__TestName_Test
    • TestName以"_"开头(例如_bar),我们得到TestCaseName__bar_Test
    • TestName以"_"结尾(例如bar_),我们得到TestCaseName_bar__Test

    以上命名方式都有可能产生命名冲突,因而TestCaseName和TestName以“_"开头或结尾均不可取。

    如果TestCaseName或TestName命名中包含下划线,情况又会怎样呢?

    TEST(Time, Flies_Like_An_Arrow) { ... }
    TEST(Time_Flies, Like_An_Arrow) { ... }

    假设我们同时定义了两个测试实例,Oops! 这时Gtest将产生同一个类:Time_Flies_Like_An_Arrow。

    因而为避免命名冲突的情况发生(不管是与系统标志冲突或自定义的标志间冲突),我们的测试用例或测试实例的命名最好不包含下划线。当然,这是建议而不是必须的。

    在测试固件类中,为什么要用set-up/tear-down函数,而不使用构造函数/析构函数

    还记得测试固件的作用吗?通过测试固件,Gtest为每一个测试实例生成一个测试固件对象,该对象为每个测试实例提供独立的数据配置,通过编写SetUp()/TearDown()函数,我们可以对数据进行初始化和销毁操作。

    对于一个类而言,构造函数和析构函数不是同样有初始化数据/销毁数据的作用吗?Gtest提供SetUp()和TearDown()岂不是多此一举?No,no,no, 对于以下情况,还非得用SetUp()/TearDown()不可:

    对于销毁操作中包含异常抛出调用的,由于在C++的析构函数中不能抛出异常,这时候需使用TearDown()调用(关于C++析构函数抛出异常的介绍,请看这里)。

    为什么当我调用RUN_ALL_TESTS()函数时,编译器抛出"ignoring return value"警告

    一些Gtest使用者忽略了RUN_ALL_TESTS()的返回值,理应这样调用:

    return RUN_ALL_TESTS();

    而不是这样:

    RUN_ALL_TESTS();

    测试程序根据RUN_ALL_TESTS()的返回值判断其所包含的测试实例是否通过。如果在main()函数中忽略其返回值,即使是某个测试实例检测失败,整个测试程序也会被认为是无检测失败地成功执行。

    为避免误用RUN_ALL_TESTS(),对于不作为main()返回值的调用,gcc将对此抛出警告,为消除该警告,将RUN_ALL_TESTS()作为main()函数的返回值即可。

    如何为一个测试固件定义多个测试用例

    我想编写多个测试实例,它们对应于同一个测试固件,对此,是否要为每一个测试实例编写新的测试固件类?就像这样:

    class FooTest : public BaseTest {};

    TEST_F(FooTest, Abc) { ... }
    TEST_F(FooTest, Def) { ... }

    class BarTest : public BaseTest {};

    TEST_F(BarTest, Abc) { ... }
    TEST_F(BarTest, Def) { ... }

    这里类FooTest和类BarTest什么都不做,我们这样定义只是为了产生两个不同的测试用例名。

    其实使用typedef能更便捷地达到目的:

    typedef BaseTest FooTest;

    TEST_F(FooTest, Abc) { ... }
    TEST_F(FooTest, Def) { ... }

    typedef BaseTest BarTest;

    TEST_F(BarTest, Abc) { ... }
    TEST_F(BarTest, Def) { ... }


    关于Gtest的更多FAQ,请参看这里

  • 相关阅读:
    解决javaScript在不同时区new Date()显示值不同问题
    页面返回上一页浏览位置
    如何disabled禁用所有表单input输入框元素
    js根据json数组多个字段排序
    No identifier specified for entity
    Android resource compilation failed
    android 系统dialog的应用
    android消息处理源码分析
    Linux下常用命令
    ContentProvider和ContentResolver的使用
  • 原文地址:https://www.cnblogs.com/bangerlee/p/2218392.html
Copyright © 2020-2023  润新知