zoukankan      html  css  js  c++  java
  • 使用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用法

    更多参考

  • 相关阅读:
    关于lockkeyword
    关于多层for循环迭代的效率优化问题
    Android 面试精华题目总结
    Linux基础回想(1)——Linux系统概述
    linux源代码编译安装OpenCV
    校赛热身 Problem C. Sometimes Naive (状压dp)
    校赛热身 Problem C. Sometimes Naive (状压dp)
    校赛热身 Problem B. Matrix Fast Power
    校赛热身 Problem B. Matrix Fast Power
    集合的划分(递推)
  • 原文地址:https://www.cnblogs.com/Stultz-Lee/p/10001209.html
Copyright © 2011-2022 走看看