• 使用gmock白盒测试


    提起白盒测试,很多程序员可能觉得就是个书上的概念,很多人写完代码根本没有具体的测试方案,自己觉得可行就提交了,其实这是个很危险的事情,毕竟出了bug,最后要加班的人还是你 ,因此做好白盒测试,100%的覆盖是很重要的.
    事实上,VS中已经集成了单元测试框架.可是,要达到更广泛的测试目的,需要借助下外援了.
    本文希望通过介绍由Google出品的Gmock和Gtest框架,帮助程序员完成单元测试.也是自己的学习记录

    网上给的地址都在墙外,这里给个可以用的下载地址,1.7.0点这里
    另外 附上1.8.0的Github,不得不说,自从有了github,码农的日子好了不少,特别是中国的码农.

    整个框架并不大,只有几个文件.是的,如果测试框架都那么大,让真实的待测代码情何以堪.

    • 编译lib文件
      下载完成后,使用VS2008编译,在debug模式下编译的文件 ,主要使用的是gtest.lib和gmock.lib

    这两个文件不是一起生成的,一个在Gmock的msvc下,另一个在gtest的msvc下,分别编译生成.

    gtest

    • demo1构建

    在VS2008中新建控制台程序,将gmock的include文件夹和gtest的include文件夹拷贝出来,放在一起,留在头文件库中使用.将生成的lib文件放入lib文件夹使用,这里可以自行放置.配置VS时定位到具体的位置即可;
    需要特别主要的是,一定要将运行库设置为 多线程调试(MTd),因为文主是使用默认工程编译的gmock和gtest,其运行库就是MTd方式编译的.
    然后在main函数的文件中 添加为如下代码:

    #include <gtest/gtest.h>
    int _tmain(int argc, _TCHAR* argv[])
    {
    	testing::InitGoogleTest(&argc, argv);
    	return RUN_ALL_TESTS();
    	return 0;
    }
    

    接下来,我们来试试水
    新建一个cpp文件
    测试代码

    int funcForTest1(int i)
    {
    	return i;
    }
    
    TEST(FooTestCase1, Demo1Failed)
    {
    	EXPECT_EQ(4, funcForTest1(6));
    }
    
    TEST(FooTestCase2, Demo1Success)
    {
    	EXPECT_EQ(6, funcForTest1(6));
    }
    

    这里故意做了一些区分,TEST宏的参数 含义为 [TestCaseName,TestName],EXPECT_EQ则标识相等的预期,以下是运行结果

    [==========] Running 2 tests from 2 test cases.
    [----------] Global test environment set-up.
    [----------] 1 test from FooTestCase1
    [ RUN      ] FooTestCase1.Demo1Failed
    e:godertimepracticezoneunittestgogogodemo1demo1dd1.cpp(11): error: Value of: funcForTest1(6)
      Actual: 6
    Expected: 4
    [  FAILED  ] FooTestCase1.Demo1Failed (2 ms)
    [----------] 1 test from FooTestCase1 (5 ms total)
    
    [----------] 1 test from FooTestCase2
    [ RUN      ] FooTestCase2.Demo1Success
    [       OK ] FooTestCase2.Demo1Success (0 ms)
    [----------] 1 test from FooTestCase2 (2 ms total)
    
    [----------] Global test environment tear-down
    [==========] 2 tests from 2 test cases ran. (19 ms total)
    [  PASSED  ] 1 test.
    [  FAILED  ] 1 test, listed below:
    [  FAILED  ] FooTestCase1.Demo1Failed
    
     1 FAILED TEST
    
    

    成功和失败是有颜色区分的.

    测试结果表明,我们有一个测试失败了.而且标出了测试失败的位置.

    • 宏断言

    一类是ASSERT系列,一类是EXPECT系列。一个直观的解释就是:

    1. ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)。
      常用: ASSERT_TRUE、 ASSERT_EQ、 ASSERT_STREQ
    2. EXPECT_* 系列的断言,当检查点失败时,继续往下执行。
      常用: EXPECT_FALSE、 EXPECT_NE、 EXPECT_STRNE

    更多直接参考这里

    这篇博文很全面介绍了gtest

    gmock

    测试一个模块的时候,可能涉及到和其他模块交互,可以将模块之间的接口mock起来,模拟交互过程。其作用就类似白盒测试中的打桩的概念。

    gmock与gtest相辅相成,gtest测试真实的代码,而gmock则模拟真实的代码.在gtest测试时加入gmock代码也是受到google推荐的.
    参考代码

    class Cdd2
    {
    public:
    	Cdd2() {}
    	virtual ~Cdd2() {}
    	virtual std::string getAttrString() = 0;
    	virtual int getPosition(int parm) = 0;
    
    };
    
    class MockCdd2:public Cdd2
    {
    public:
    	//0和1代表了参数的个数
    	MOCK_METHOD0(getAttrString,std::string());
    	MOCK_METHOD1(getPosition,int(int));
    
    };
    
    
    TEST(MockTestCase, Demo1)
    {
    	int n = 100;
        std::string value = "Hello World!";
        MockCdd2 mockFoo;
    
        //期待运行1次,且返回值为value的字符串
        EXPECT_CALL(mockFoo, getAttrString())
            .Times(1)
            .WillOnce(testing::Return(value));
        std::string returnValue = mockFoo.getAttrString();
        std::cout << "Returned Value: " << returnValue << std::endl;
    
        //期待运行两次,返回值分别为335 和 455
        EXPECT_CALL(mockFoo, getPosition(testing::_))
            .Times(2)
            .WillOnce(testing::Return(335))
            .WillOnce(testing::Return(455));
    
        int val = mockFoo.getPosition(0);  //355
        int val2 = mockFoo.getPosition(1);  //455
        std::cout << "Returned Value: " << val <<" "<< val2 << std::endl;
    }
    

    运行结果:

    [==========] Running 1 test from 1 test case.
    [----------] Global test environment set-up.
    [----------] 1 test from MockTestCase
    [ RUN      ] MockTestCase.Demo1
    Returned Value: Hello World!
    Returned Value: 335 455
    [       OK ] MockTestCase.Demo1 (17 ms)
    [----------] 1 test from MockTestCase (19 ms total)
    
    [----------] Global test environment tear-down
    [==========] 1 test from 1 test case ran. (28 ms total)
    [  PASSED  ] 1 test.
    

    说明:虽然MockCdd2 继承于 Cdd2,但是其实并没有执行Cdd2的相关函数,而是MockCdd2的期望返回值,我们通过手动设置返回值的方式,达到了测试打桩的目的.

    该文章中有项目中较为成熟的mock用法

    更多参考

  • 相关阅读:
    python的模块future用法实例解析
    strcmp函数和memcmp函数的用法区别及联系
    esp8266 smartconfig-智能配网分析和使用及注意事项
    ubuntu 18.04 安装并配置adb
    Markdown的常用方法总结
    mac下使用minicom几个注意事项
    最强Linux shell工具Oh My Zsh 指南
    ESP8266源码分析--打印的基本用法
    atom 在Ubuntu 18.04 上安装及基本使用
    ubuntu 查看端口被占用并删除端口
  • 原文地址:https://www.cnblogs.com/Stultz-Lee/p/10001209.html
Copyright © 2020-2023  润新知