GTest学习笔记(五)

官网文档: Googletest Primer | GoogleTest

摘要:本文整体上是一篇读书笔记(末尾有一个自己的实例),主要介绍了TEST()函数、TEST_F()函数、Test Fixture、RUN_ALL_TESTS(),并在运行实例中比较TEST()TEST_F()的差别。

1 Simple Tests

创建一个test函数:

  • 通过TEST()宏来定义一个test函数。这个是一个没有返回值的普通的C++函数
  • 在这个函数中,可以使用任何你想要包括的C++语句并通过GTest提供的各种各样的断言来校验值
  • test的结果由断言决定:有任何一个断言失败或程序死机,整个test就是失败的;除此以外,这个test就是成功的
TEST(TestSuiteName, TestName) {
  ... test body ...
}

TEST() 的参数从一般到具体。第一个参数TestSuiteName是测试套件的名字,第二个参数TestName是这个test在测试套件里的名字。这两个参数都要遵循C++的命名规则并且不应该包含任何下划线。一个test的全名由TestSuiteName+TestName构成。

GTest按照测试套件对test结果进行分组,所以逻辑上相关的test应该放在同一个测试套件里(即TEST()里的第一个参数TestSuiteName应该一致)。

2 Test Fixtures: Using the Same Data Configuration for Multiple Tests

如果你发现自己两个或以上的test作用于相似的数据,你可以使用一个测试固件。测试固件允许你在不同的test中重复使用相同的对象配置

创建一个固件:

  • 从 ::testing::Test继承一个类,用protected:来开始这个类(类中声明的所有成员都是受保护的),因为我们后续会希望在子类中访问fixture成员
  • 在这个类里面,声明任何想要使用的对象
  • 如有必要,写一个默认的构造函数或SetUp()函数来为每一个test准备对象
  • 如有必要,写一个析构函数或TearDown()函数来释放在SetUp()或构造函数中分配的资源
  • 如有需要,编写子函数使其可被test共享

当使用fixture时,使用TEST_F 代替TEST(),TEST_F()可以让你访问fixture中的对象和子程序

TEST_F(TestFixtureName, TestName) {
  ... test body ...
}

对于每个用TEST_F()定义的test,在运行时,GTest会创建一个全新的fixture,通过SetUp()初始化它,然后运行test,最后用TearDown清理它。请注意在同一个test suite中的不同的test拥有不同的fixture对象,并且GTest会在创建下一个新的fixture对象前删除一个fixture对象。对于多个test,GTest并不会重用fixture对象。因而任何在test中对fixture做出的改变并不会影响到其它的test。

3 Invoking the Tests

TEST()TEST_F()通过GTest隐式的注册了test,因此,使用时并不需要像很多其他的C++测试框架一样,再把test重新罗列一遍来达到执行test的目的。

在定义完test后,通过RUN_ALL_TESTS()就可以执行定义的test,若所有的test执行成功返回0,反之返回1。 注意,RUN_ALL_TESTS()运行链接单元中的所有test——它们可以来自不同的测试套件,甚至可以来自不同的源文件。

当调用RUN_ALL_TESTS()时,会进行如下步骤:

  • 保存所有GTest标志的状态
  • 为第一个test创建一个test fixture
  • 通过SetUp()初始化test fixture
  • 在这个fixture对象上执行此test
  • 通过TearDown()清理这个fixture
  • 删除这个fixture
  • 恢复所有GTest标志的状态
  • 下一个test重复上述步骤,直到所有的test执行完成

如果执行过程中发生致命故障,会跳过后续步骤

4 Writing the main() Function

直接把官网给的模板示例复制到cpp文件中,添上自己的test即可

5 TEST()和TEST_F()的区别

使用TEST_F()的源码:

#include "user.h"
#include "stdio.h"

#include "gtest/gtest.h"

namespace my {
    namespace project {
        namespace {

            // The fixture for testing class Foo.
            class UserTest : public ::testing::Test {
            protected:
                // You can remove any or all of the following functions if their bodies would
                // be empty.

                static void SetUpTestSuite() {
                    // Avoid reallocating static objects if called in subclasses of FooTest.
                    printf("UserTest类TestSuite级别SetUp函数执行!\n");
                }

                // Per-test-suite tear-down.
                // Called after the last test in this test suite.
                // Can be omitted if not needed.
                static void TearDownTestSuite() {
                    printf("UserTest类TestSuite级别TearDown函数执行!\n");
                    
                }



                UserTest() {
                    // You can do set-up work for each test here.
                    printf("UserTest类构造函数执行!\n");
                }

                ~UserTest() override {
                    // You can do clean-up work that doesn't throw exceptions here.
                    printf("UserTest类析构函数执行!\n");
                }

                // If the constructor and destructor are not enough for setting up
                // and cleaning up each test, you can define the following methods:

                void SetUp() override {
                    // Code here will be called immediately after the constructor (right
                    // before each test).
                    printf("UserTest类TestCase级别SetUp函数执行!\n");
                }

                void TearDown() override {
                    // Code here will be called immediately after each test (right
                    // before the destructor).
                    printf("UserTest类TestCase级别TearDown函数执行!\n");
                }

                // Class members declared here can be used by all tests in the test suite
                // for Foo.
            };

            // Tests that the Foo::Bar() method does Abc.
            TEST_F(UserTest, TestSetUserName) {
                User user;
                char name[26];
                strcpy_s(name, "wei");
                user.setusername(name);
                EXPECT_EQ(strcmp(user.getusername(),name), 0);
            }

            // Tests that Foo does Xyz.
            TEST_F(UserTest, TestSetCode) {
                // Exercises the Xyz feature of Foo.
                User user1;
                char code[26];
                strcpy_s(code, "wei");
                user1.setcode(code);
                int result;
                result = strcmp(user1.getcode(), code);
                EXPECT_EQ(result, 0);
            }
            TEST_F(UserTest, TestInt) {
                // Exercises the Xyz feature of Foo.
                int a, b;
                a = 1;
                b = 2;
                EXPECT_EQ(a+1,b);
            }

        }  // namespace
    }  // namespace project
}  // namespace my

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

执行结果:
在这里插入图片描述

使用TEST()的源码,只是把上面源码中的TEST_F()改成了TEST(),其它没有任何变化:

#include "user.h"
#include "stdio.h"

#include "gtest/gtest.h"

namespace my {
    namespace project {
        namespace {

            // The fixture for testing class Foo.
            class UserTest : public ::testing::Test {
            protected:
                // You can remove any or all of the following functions if their bodies would
                // be empty.

                static void SetUpTestSuite() {
                    // Avoid reallocating static objects if called in subclasses of FooTest.
                    printf("UserTest类TestSuite级别SetUp函数执行!\n");
                }

                // Per-test-suite tear-down.
                // Called after the last test in this test suite.
                // Can be omitted if not needed.
                static void TearDownTestSuite() {
                    printf("UserTest类TestSuite级别TearDown函数执行!\n");
                    
                }



                UserTest() {
                    // You can do set-up work for each test here.
                    printf("UserTest类构造函数执行!\n");
                }

                ~UserTest() override {
                    // You can do clean-up work that doesn't throw exceptions here.
                    printf("UserTest类析构函数执行!\n");
                }

                // If the constructor and destructor are not enough for setting up
                // and cleaning up each test, you can define the following methods:

                void SetUp() override {
                    // Code here will be called immediately after the constructor (right
                    // before each test).
                    printf("UserTest类TestCase级别SetUp函数执行!\n");
                }

                void TearDown() override {
                    // Code here will be called immediately after each test (right
                    // before the destructor).
                    printf("UserTest类TestCase级别TearDown函数执行!\n");
                }

                // Class members declared here can be used by all tests in the test suite
                // for Foo.
            };

            // Tests that the Foo::Bar() method does Abc.
            TEST(UserTest, TestSetUserName) {
                User user;
                char name[26];
                strcpy_s(name, "wei");
                user.setusername(name);
                EXPECT_EQ(strcmp(user.getusername(),name), 0);
            }

            // Tests that Foo does Xyz.
            TEST(UserTest, TestSetCode) {
                // Exercises the Xyz feature of Foo.
                User user1;
                char code[26];
                strcpy_s(code, "wei");
                user1.setcode(code);
                int result;
                result = strcmp(user1.getcode(), code);
                EXPECT_EQ(result, 0);
            }
            TEST(UserTest, TestInt) {
                // Exercises the Xyz feature of Foo.
                int a, b;
                a = 1;
                b = 2;
                EXPECT_EQ(a+1,b);
            }

        }  // namespace
    }  // namespace project
}  // namespace my

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

执行结果:

在这里插入图片描述

个人理解,从运行结果看TEST()函数不会去调用测试类里的SetUp()TearDown()类型的函数,但TEST_F()会。
要注意在同一个测试类中,TEST()TEST_F()不能混用,不然会报错。
此例子中还涉及了GTest的事件机制,会在下一篇中介绍。

内容如有错误,敬请指正!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值