• gtest的安装和使用


    Linux x86环境下

    一,gtest安装

    下载gtest源码包:gtest-1.7.0.zip

    解压后进入gtest-1.7.0目录

    cmake CMakeLists.txt

    make 后生成两个静态库:libgtest.a libgtest_main.a

    sudo cp libgtest*.a  /usr/lib 

    sudo cp –a include/gtest /usr/include

    下面是进入到sample目录下编译用例

    cd sample

    g++ sample1.cc sample1_unittest.cc -lgtest -lgtest_main -lpthread -o test1

    g++ sample1.cc sample3-inl.h sample5_unittest.cc -lgtest -lgtest_main -lpthread -o test5

    由于sample1.cc和sample1_unittest.cc文件中没有编写main函数,这里需要链接libgtest_main.a库

    二,gtest使用

    http://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html

    gtest 即 Google C++单元测试框架

    单元测试一般由编码人员自己完成,它的目的是隔离程序部件,并证明这些单个部件满足预期的功能。

    它提供了丰富的断言、致命和非致命失败判断,能进行值参数化测试、类型参数化测试、“死亡测试”

    1,断言

    ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)

    EXPECT_* 系列的断言,当检查点失败时,继续往下执行。

    <1>布尔类型检查

    ASSERT_TRUE(condition)  ASSERT_FALSE(condition)

    <2>数值类型检查

    ASSERT_EQ(expected, actual);

    ASSERT_NE(val1, val2);

    ASSERT_LT(val1, val2);

    ASSERT_LE(val1, val2);

    ASSERT_GT(val1, val2);

    ASSERT_GE(val1, val2);

    <3>字符串检查

    ASSERT_STREQ(expected_str, actual_str);

    ASSERT_STRNE(str1, str2);

    ASSERT_STRCASEEQ(expected_str, actual_str);

    ASSERT_STRCASENE(str1, str2);

    一个简单的测试案例,可以参考sample/sample1.cc 和sample1_unittest.cc

    另外sample2 是对类的接口函数的测试。

    首先是一个求最大公约数的函数

    int Foo(int a, int b)
    {
        if (a == 0 || b == 0)
        {
            throw "don't do that";
        }
        int c = a % b;
        if (c == 0)
            return b;
        return Foo(b, c);
    }

    下面是对这个函数写一个简单的测试样例

    #include <gtest/gtest.h>

    TEST(FooTest, HandleNoneZeroInput)
    {
        EXPECT_EQ(2, Foo(4, 10));
        EXPECT_EQ(6, Foo(30, 18));
    }

    每个案例(TEST或TEST_F)应该是相互独立,互不影响的。

    TEST宏有两个参数,第一个是TestSuiteName,第二个是TestCaseName

    然后在main中添加如下代码让我们的案例运行起来。

    int _tmain(int argc, _TCHAR* argv[])
    {
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }

    也可以不写main函数,直接在编译的时候链接libgtest_main.a库

    2,gtest提供了多种事件机制,非常方便我们在案例之前或之后做一些操作。总结一下gtest的事件一共有3种:

    <1>全局的,所有案例执行前后。

    <2>TestSuite级别的,在某一批案例中第一个案例前,最后一个案例执行后。

    <3> TestCase级别的,每个TestCase前后。

    这里主要介绍TestCase事件

    TestCase事件是挂在每个案例执行前后的,不过需要实现的是SetUp方法和TearDown方法:

    1. SetUp()方法在每个TestCase之前执行

    2. TearDown()方法在每个TestCase之后执行

    要写一个类,这个类继承 testing::Test类。

    class FooCalcTest:public testing::Test
    {
    protected:
        virtual void SetUp()
        {
            m_foo.Init();
        }
        virtual void TearDown()
        {
            m_foo.Finalize();
        }

        FooCalc m_foo;
    };

    TEST_F(FooCalcTest, HandleNoneZeroInput)
    {
        EXPECT_EQ(4, m_foo.Calc(12, 16));
    }

    TEST_F(FooCalcTest, HandleNoneZeroInput_Error)
    {
        EXPECT_EQ(5, m_foo.Calc(12, 16));
    }

    写测试案例时,使用TEST_F则开始测试前调用SetUp,结束案例后调用TearDown。也可以在这个类中定义其他的测试函数,供TEST_F调用。TEST_F的第一个参数类的名字,第二个参数是测试案例名。

    gtest源码中的sample3也用的是TestCase事件。这个例子中定义了一个Queue模板,在QueueTest类中定义了SetUp函数和一个用来测试Map的MapTester函数。

    3,参数化测试(mytest2)

    首先必须添加一个类,继承testing::TestWithParam<T>,其中T就是你需要参数化的参数类型,这里是int。

    然后使用TEST_P定义参数化案例。在TEST_P宏里,使用GetParam()获取当前的参数的具体值。

    最后 使用INSTANTIATE_TEST_CASE_P这宏来告诉gtest你要测试的参数范围

    #include <gtest/gtest.h>

    class IsPrimeParamTest : public::testing::TestWithParam<int>
    {

    };

    // 不使用参数化测试,就需要像这样写五次
    TEST(IsPrimeTest, HandleTrueReturn1)
    {
        EXPECT_TRUE(IsPrime(3));
        EXPECT_TRUE(IsPrime(5));
        EXPECT_TRUE(IsPrime(11));
        EXPECT_TRUE(IsPrime(23));
        EXPECT_TRUE(IsPrime(17));
    }

    // 使用参数化测试,只需要:
    TEST_P(IsPrimeParamTest, HandleTrueReturn2)
    {
        int n =  GetParam();
        EXPECT_TRUE(IsPrime(n));
    }

    // 定义参数
    INSTANTIATE_TEST_CASE_P(TrueReturn, IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17));

    INSTANTIATE_TEST_CASE_P宏的三个参数:

    第一个参数是测试案例的前缀,可以任意取。

    第二个参数是测试案例的名称,需要和之前定义的参数化的类的名称相同,如:IsPrimeParamTest

    第三个参数是可以理解为参数生成器,上面的例子使用test::Values表示使用括号内的参数。Google提供了一系列的参数生成的函数:

    Range(begin, end[, step])

    范围在begin~end之间,步长为step,不包括end

    Values(v1, v2, ..., vN)

    v1,v2到vN的值

    ValuesIn(container) and ValuesIn(begin, end)

    从一个C类型的数组或是STL容器,或是迭代器中取值

    Bool()

    取false 和 true 两个值

    Combine(g1, g2, ..., gN)

    这个比较强悍,它将g1,g2,...gN进行排列组合,g1,g2,...gN本身是一个参数生成器,每次分别从g1,g2,..gN中各取出一个值,组合成一个元组(Tuple)作为一个参数。

    说明:这个功能只在提供了<tr1/tuple>头的系统中有效。gtest会自动去判断是否支持tr/tuple,如果你的系统确实支持,而gtest判断错误的话,你可以重新定义宏GTEST_HAS_TR1_TUPLE=1。

    4,命令行参数

    --gtest_output=xml:dir:foo.xml

    指定输出到dirfoo.xml,不指定则输出到当前目录。也可以由系统变量GTEST_OUTPUT指定

    --gtest_list_tests

    使用这个参数时,将不会执行里面的测试案例,而是输出一个案例的列表。

    --gtest_filter

    对执行的测试案例进行过滤,支持通配符

    好的单元测试具备以下特点:

    1,  独立:即该测试用例的测试结果不受其他测试的影响

    2,  有效的组织架构,清晰的命名:各个测试用例针对不同的测试对象,而对单个测试对象而言,又可能有多个测试用例对应该对象的多个功能。好的习惯是把这些用例以层次结构的形式组织起来,并使用清晰的命名,使得我们通过阅读用例名称即可明了该用例的功能

    3,  可移植、可复用

    4,  当用例失败时,提供尽可能多的有效信息

  • 相关阅读:
    【BZOJ3218】 a+b Problem
    【BZOJ3993】 星际战争
    【BZOJ3991】 寻宝游戏
    【BZOJ2959】长跑 (LCT+并查集)
    NOIP2017记
    【CF 678F】Lena and Queries
    【Learning】多项式乘法与快速傅里叶变换(FFT)
    Subsequence Count (线段树)
    【留言板】
    【bzoj 4173】数学
  • 原文地址:https://www.cnblogs.com/zhoutian220/p/5046693.html
Copyright © 2020-2023  润新知