【Bash百宝箱】快速使用gcov&lcov构建程序的单元测试

在软件开发过程中,为了验证代码块功能的完备及健壮性,我们常常会做一些单元测试,验证函数的调用符合预期,再加上gcov、lcov这样的工具,可以生成HTML格式的单元测试结果,极大地提供了可读性。下面以一个动态库的单元测试为例,简述gcov、lcov的用法。

1、代码准备

在“/home/demo”目录下,包括测试代码test.c和被测试代码demo.h、demo.c,如下:

这里写图片描述

// demo.h
#ifndef DEMO_H
#define DEMO_H

void demo_foo();
void demo_foo2(int i);

#endif /* DEMO_H */

// demo.c
#include <stdio.h>
#include "demo.h"

void demo_foo()
{
    printf("%s\n", __func__);
}

void demo_foo2(int i)
{
    if (i > 0) {
        printf("%s pos\n", __func__);
        if (0 == i % 2) {
            printf("%s even\n", __func__);
        }
        else {
            printf("%s odd\n", __func__);
        }
    }
    else if (i < 0) {
        printf("%s neg\n", __func__);
    }
    else {
        printf("%s zero\n", __func__);
    }
}

// test.c
#include <stdio.h>
#include "demo.h"

int main(int argc, char* argv[])
{
    printf("%s unit test begin\n", __func__);

    demo_foo();
    demo_foo2(2);
    demo_foo2(1);
    demo_foo2(0);
    demo_foo2(-1);

    printf("%s unit test end\n", __func__);

    return 0;
}

demo.c中定义了两个函数,test.c中分别调用了这两个函数进行测试,其中demo_foo2()函数传入了不同的参数以满足100%条件覆盖,这是一个很简单的例子。

2、生成可执行文件

我们的例子测试的是一个动态库,所以先把demo.h/demo.c编译成一个动态库libdemo.so:

gcc -shared -fpic -o libdemo.so demo.h demo.c

然后编译test.c并链接libdemo.so为可执行文件test:

gcc -o test test.c -L. -ldemo

这一步操作生成了libdemo.so和test两个文件:

这里写图片描述

我们先来运行一下test这个可执行文件,看它能否正确执行。

LD_LIBRARY_PATH=. ./test

main unit test begin
demo_foo
demo_foo2 pos
demo_foo2 even
demo_foo2 pos
demo_foo2 odd
demo_foo2 zero
demo_foo2 neg
main unit test end

从上面的log可以看出,我们的可执行文件test是没有问题的。

3、重新编译动态库

对一个动态库进行单体测试,为了能够生成HTML形式的测试结果,我们使用gcc编译时,还需要添加两个编译参数,“-fprofile-arcs”和“-ftest-coverage”,前者用来生成对应的”.gcda”后缀的数据,后者用来生成对应的”.gcno”后缀的数据,这两种数据是必须的。因为我们要测试的是动态库,所以需要重新编译这个动态库,而没有必要重新编译其它文件,这一点需要注意。

gcc -fprofile-arcs -ftest-coverage -shared -fpic -o libdemo.so demo.h demo.c

这一步重新编译了libdemo.so,并且产生了对应的demo.gcno数据:

这里写图片描述

4、运行可执行文件

LD_LIBRARY_PATH=. ./test

main unit test begin
demo_foo
demo_foo2 pos
demo_foo2 even
demo_foo2 pos
demo_foo2 odd
demo_foo2 zero
demo_foo2 neg
main unit test end

这一步生成了demo.gcda数据:

这里写图片描述

5、使用gcov生成.gcov数据

命令:gcov demo.c
生成文件:demo.c.gcov

这里写图片描述

我们来看看demo.c.gcov文件有什么内容:

cat demo.c.gcov

        -:    0:Source:demo.c
        -:    0:Graph:demo.gcno
        -:    0:Data:demo.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:#include "demo.h"
        -:    3:
        1:    4:void demo_foo()
        -:    5:{
        1:    6:    printf("%s\n", __func__);
        1:    7:}
        -:    8:
        4:    9:void demo_foo2(int i)
        -:   10:{
        4:   11:    if (i > 0) {
        2:   12:        printf("%s pos\n", __func__);
        2:   13:        if (0 == i % 2) {
        1:   14:            printf("%s even\n", __func__);
        -:   15:        }
        -:   16:        else {
        1:   17:            printf("%s odd\n", __func__);
        -:   18:        }
        -:   19:    }
        2:   20:    else if (i < 0) {
        1:   21:        printf("%s neg\n", __func__);
        -:   22:    }
        -:   23:    else {
        1:   24:        printf("%s zero\n", __func__);
        -:   25:    }
        4:   26:}

6、使用lcov生成.info数据

lcov -c -d . -o demo.info

Capturing coverage data from .
Found gcov version: 4.8.4
Scanning . for .gcda files ...
Found 1 data files in .
Processing demo.gcda
Finished .info-file creation

-c用来抓取覆盖率数据,-d指定覆盖率数据所在的目录,-o指定生成的目标文件,后缀为.info。这一步生成了demo.info,不过demo.c.gcov文件被自动清理了。

这里写图片描述

7、最后一步

使用genhtml命令生成html。

genhtml demo.info -o out

Reading data file demo.info
Found 1 entries.
Found common filename prefix "/home"
Writing .css and .png files.
Generating output.
Processing file demo/demo.c
Writing directory view page.
Overall coverage rate:
  lines......: 100.0% (13 of 13 lines)
  functions..: 100.0% (2 of 2 functions)
  branches...: 100.0% (6 of 6 branches)

-o指定html文件存放位置,这里我们把它放置在当前目录的out文件夹中:

这里写图片描述

打开out目录下的index.html查看结果如下:

这里写图片描述

点击“demo”目录:

这里写图片描述

点击“demo.c”文件:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值