QT unit test code coverage

时间:2022-11-06 00:06:50

准备环境:

qt-creator5.2.1 , gcov(gcc 默认安装),lcov(gcov 的图形化显示界面),qt_testlib

各环境介绍:

1.gcov

 

gcov

是一个可用于C/C++的代码覆盖工具,是gcc的内建工具。下面介绍一下如何利用gcov来收集代码覆盖信息。

想要用gcov收集代码覆盖信息,需要在gcc编译代码的时候加上这2个选项:

“-fprofile-arcs -ftest-coverage”,把这个简单的程序编译一下

gcc -fprofile-arcs -ftest-coverage hello.c -o hello

编译后会得到一个可执行文件hello和hello.gcno文件,当用gcc编译文件的时候,如果带有“-ftest-coverage”参数,就会生成这个.gcno文件,它包含了程序块和行号等信息

接下来可以运行这个hello的程序

./hello 5

./hello 12

运行结束以后会生成一个hello.gcda文件,如果一个可执行文件带有“-fprofile-arcs”参数编译出来,并且运行过至少一次,就会生成。

这个文件包含了程序基本块跳转的信息。接下来可以用gcov生成代码覆盖信息:

gcov hello.c 运行结束以后会生成2个文件hello.c.gcov和myfunc.c.gcov。打开看里面的信息:

-: 0:Source:myfunc.c

-: 0:Graph:hello.gcno

-: 0:Data:hello.gcda

-: 0:Runs:1

-: 0:Programs:1

-: 1:#include

-: 2:

-: 3:void test(int count)

1: 4:{

-: 5: int i;

10: 6: for (i = 1; i < count; i++)

-: 7: {

9: 8: if (i % 3 == 0)

3: 9: printf (“%d is divisible by 3

\

n”, i);

9: 10: if (i % 11 == 0)

#

####: 11: printf (“%d is divisible by 11

\

n”, i);

9: 12: if (i % 13 == 0)

#####: 13: printf (“%d is divisible by 13

\

n”, i);

-: 14: }

1: 15:}

被标记为#####的代码行就是没有被执行过的,代码覆盖的信息是正确的.

1.2 使用gcov的3个阶段

(1) 编译

# gcc -f=profile-arcs -f test-coverage  -o test test.c

# ls

test  test.c  test.gcno

-f profile-arcs -f test-coverage告诉编译器生成gcov需要的额外信息,并在目标文件中插入gcov需要的extra profiling information。因此,该命令在生成可执行文件test

的同时生成test.gcno文件(gcov note文件)。

(2) 收集信息

# ./test

Success

# ls

test  test.c   test.gcda test.gcno

执行该程序,生成test.gcda文件(gcov data文件)。

(3)

报告

# gcov test.c

File 'test.c'

Lines executed:87.50% of 8

test.c:creating 'test.c.gcov'

# ls

test  test.c

test.c.gcov

test.gcda  test.gcno

生成test.c.gcov文件,该文件记录了每行代码被执行的次数。

test.c.gcov

文件内容如下,蓝色表示笔者添加的注释。

-:    0:Source:test.c

-:    0:Graph:test.gcno

-:    0:Data:test.gcda

-:    0:Runs:1

-:    0:Programs:1

-:    1:#include          //前面的数字表明该clause被执行的次数,下同

-:    2:

-:    3:int main (void)

1:    4:{

-:    5:    int i, total;

-:    6:

1:    7:    total = 0;

-:    8:

11:    9:    for (i = 0; i < 10; i++)  //前面的数字11表明该clause被执行11次

10:   10:        total += i;

-:   11:

1:   12:    if (total != 45)

#####:   13:        printf ("Failure/n");

-:   14:    else

1:   15:        printf ("Success/n");

1:   16:    return 0;

-:   17:}

-:   18:

1.2 gcov的选项

gcov

的选项不多,也好理解,此处选3个典型的选项并结合例子加以说明。

(1) -a, --all-blocks

在.gcov文件中输出每个基本快(basic block)的执行次数。如果没有-a选项,则输出'main'函数这个block的执行次数,如上所示。使用该选项可以

Write individual execution counts for every basic block.  Normally gcov outputs execution counts only for the main blocks of a line.  With

this option you can determine if blocks within a single line are not being executed.

# gcov -a test.c File 'test.c'

Lines executed:87.50% of 8     //

代码覆盖率

test.c:creating 'test.c.gcov'

Test.c.gcov

文件内容。

-:    0:Source:test.c

-:    0:Graph:test.gcno

-:    0:Data:test.gcda

-:    0:Runs:1

-:    0:Programs:1

-:    1:#include

-:    2:

-:    3:int main (void)

1:    4:{

-:    5:    int i, total;

-:    6:

1:    7:    total = 0;

-:    8:

11:    9:    for (i = 0; i < 10; i++)

1:    9-block  0

10:    9-block  1

11:    9-block  2

10:   10:        total += i;

-:   11:

1:   12:    if (total != 45)

1:   12-block  0

#####:   13:        printf ("Failure/n");

$$$$$:   13-block  0

-:   14:    else

1:   15:        printf ("Success/n");

1:   15-block  0

1:   16:    return 0;

1:   16-block  0

-:   17:}

-:   18:

(2) -b, --branch-probabilities

在.gcov文件中输出每个分支的执行频率,并有分支统计信息。

# gcov -b test.c

File 'test.c'

Lines executed:87.50% of 8

Branches executed:100.00% of 4

Taken at least once:75.00% of 4

Calls executed:50.00% of 2

test.c:creating 'test.c.gcov'

-:    0:Source:test.c

-:    0:Graph:test.gcno

-:    0:Data:test.gcda

-:    0:Runs:1

-:    0:Programs:1

-:    1:#include

-:    2:

-:    3:int main (void)

function main called 1 returned 100% blocks executed 86%

1:    4:{

-:    5:    int i, total;

-:    6:

1:    7:    total = 0;

-:    8:

11:    9:    for (i = 0; i < 10; i++)

branch  0 taken 91%

branch  1 taken 9% (fallthrough)

10:   10:        total += i;

-:   11:

1:   12:    if (total != 45)

branch  0 taken 0% (fallthrough)

branch  1 taken 100%

#####:   13:        printf ("Failure/n");

call    0 never executed

-:   14:    else

1:   15:        printf ("Success/n");

call    0 returned 100%

1:   16:    return 0;

-:   17:}

-:   18:

(3) -c, --branch-counts

.gcov

文件中输出每个分支的执行次数。

# gcov -c test.c

File 'test.c'

Lines executed:87.50% of 8

test.c:creating 'test.c.gcov'

-c是默认选项,其结果与"gcov test.c"执行结果相同。

2.lcov

lcov -d . -t ‘Hello test’ -o ‘hello_test.info’ -b . -c 指定lcov

在当前目录“.”去找代码覆盖的信息,输出为’hello_test.info’ ,这个hello_test.info是一个中间结果,需要把它用genhtml来处理一下,genhtml是lcov里面的一个工具。

genhtml -o result hello_test.info 指定输出目录是result。

一个完整的html报告就生成了,做一个连接,把这个目录连到随便一个web server的目录下,就可以看报告了。

3.总结: 
gcov是配合gcc产生覆盖信息报告的工具; 
lcov是将gcov产生的报告信息,以更直观的方式显示出来工具 基本的使用方法分为4个阶段: 
(一)、gcc编译:产生插装后的目标文件test、gcov结点文件 test.gcno    #gcc -fprofile-arcs -ftest-coverage -o test test.c    # ls 
   test   test.c   test.gcno 
   说明:参数 fprofile-arcs 和 ftest-coverage 告诉gcc编译器:(1)在目标文件test 插装跟踪代码;(2)生成供gcov使用 test.gcno [gcov node 文件]。 
         因此,这里的生成的目标文件比正常编译的文件大。   
(二)、运行目标文件:收集运行覆盖信息 test.gcda     # ./test 
      Success  -- 这里是运行结果。     # ls 
      test test.c test.gcno test.gcda    这里test.gcda运行结果,  
(三)、gcov产生报告信息: test.c.gcov     #gcov  test.c       File 'test.c' 
      Lines executed: 87.50% of 8       test.c: creating 'test.c.gcov'    #ls 
      test test.c test.c.gcov test.gcda test.gcno 
(四)、lcov:格式化test.c.gcov ,输出到 test.info文件     #lcov -d . -t 'test' -o 'test.info' -b . -c     说明: 
         -d  . :参数 d指路径, "." 指当前路径          -t  "name" :指目标文件,这里 是 test 
         -o  "filename" :输出格式化后的信息文件名 
(五)、genhtml:根据信息文件(.info)产生html 文档,输出到一个文件夹中 
   #genhtml -o result test.info 
    说明: -o  directory :参数o (output)后面跟路径名称,在当前目录下创建指定目录,本例中是result     
至此: 可以在result目录中打开index.html 浏览覆盖信息

一.创建测试用例 
1.new project->other project ->Qt unit test 2.编写一个单元测试程序 文件列表: 
qtestlib/tutorial1/testqstring.cpp qtestlib/tutorial1/tutorial1.pro 
假设你要测试QString类的行为。首先,你需要一个用于包含测试函数的类。这个类必须从QObject继承: 
class TestQString: public QObject { 
    Q_OBJECT private slots: 
    void toUpper(); }; 
注意你需要包含QTest头文件,并且测试函数必须声明为私有槽,这样测试框架才可以找到并执行他们。 
然后你需要实现测试函数。实现看起来类似这样: 
QVERIFY()宏将计算传入的表达式的值。如果为真,则测试函数继续进行;否则会向测试日志中增加一条描述错误的信息,并且该测试函数会停止执行。 
但是如果需要向测试日志中增加更多的输出信息,你应该使用QCOMPARE()宏: void TestQString::toUpper() { 
    QString str = “Hello”; 
    QVERIFY(str.toUpper() == “HELLO”); } 
如果两个字符串不相等,他们的值都会追加到测试日志中,这样失败的原因就一目了然了。 
最后,为使我们的测试程序能够单独执行,需要加入下列两行: QTEST_MAIN(TestQString) 
#include “testqstring.moc” 
QTEST_MAIN()宏将扩展成一个简单的main()函数,该main()函数会执行所有的测试函数。注意:如果测试类的声明和实现都在同一个cpp文件中,需要包含产生的moc文件,以使Qt的内省机制起作用。 执行测试程序 
运行生成的可执行文件,你会看到下列输出: 
********* Start testing of TestQString ********* Config: Using QTest library 4.5.1, Qt 4.5.1 PASS   : TestQString::initTestCase() PASS   : TestQString::toUpper() 
PASS   : TestQString::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped

********* Finished testing of TestQString *********     
三.Mac 下具体配置 
1.确保 gcol ,lcol,genhtml 已经安装 2.在工程文件pro中添加 
QMAKE_CXXFLAGS += -g -Wall -fprofile-arcs -ftest-coverage -O0 QMAKE_LFLAGS += -g -Wall -fprofile-arcs -ftest-coverage  -O0   
LIBS += \     -lgcov 
3. 创建processCoverage.sh #!/bin/bash 
############################################################################## 
# Copyright (c) 2013, Robert Wloch 
# All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # 
# Contributors: 
# Robert Wloch - initial API and implementation 
##############################################################################  
if [ ! $# -eq 3 ]; then 
  echo "usage: ${0} <gcov-files-dir> \"<file-pattern>\" <target-dir>"   exit 0 fi 
lcov -d ${1} -c -o ${1}/coverage.info  
lcov --list-full-path -e ${1}/coverage.info ${2} –o ${1}/coverage-stripped.info  
genhtml -o ${3} ${1}/coverage-stripped.info  
lcov -d ${1} –z  
exit 0

QT unit test code coverage的更多相关文章

  1. Qt代码覆盖率code coverage&lpar;VS版&rpar;

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt代码覆盖率code coverage(VS版)     本文地址:http://techi ...

  2. Code Coverage and Unit Test in SonarQube

    概念 https://blog.ndepend.com/guide-code-coverage-tools/ Code Coverage Results Import (C#, VB.NET) Uni ...

  3. 10 Code Coverage Tools for C &amp&semi; C&plus;&plus;

    Code coverage is a measure used in software testing that describes the degree to which the source co ...

  4. Gumshoe - Microsoft Code Coverage Test Toolset

    Gumshoe - Microsoft Code Coverage Test Toolset 2014-07-17 What is Gumshoe? How to instrument a binar ...

  5. iOS 9 学习系列&colon; Xcode Code Coverage

    Code coverage 是一个计算你的单元測试覆盖率的工具. 高水平的覆盖给你的单元測试带来信心.也表明你的应用被彻底的測试过了. 你可能写了几千个单元測试,但假设覆盖率不高.那么你写的这套測试可 ...

  6. 使用Visual Studio Code Coverage和nunit上传单元测试覆盖率和单元测试结果到SonarQube上

    SonarQube.Scanner.MSBuild.exe begin /k:"OMDCCQuotes" /d:sonar.host.url="http://myip:9 ...

  7. &lbrack;Jest&rsqb; Track project code coverage with Jest

    Jest comes pre-packaged with the ability to track code coverage for the modules you're testing, but ...

  8. Effective Java提升Code Coverage代码涵盖率 - 就是爱Java

    虽然我们已经有了测试程序,但是如何得知是否已完整测试了主程序?,透过Code Coverage代码涵盖率,我们可以快速地得知,目前系统中,有多少程序中被测试过,不考虑成本跟投资效益比,涵盖率越高,代表 ...

  9. CI集成phpunit Error&colon; No code coverage driver is available 的解决

    CI集成phpunit时,运行报No code coverage driver is available的错误,如下图: yanglingdeMacBook-Pro:tests yangling$ p ...

随机推荐

  1. word search puzzle

    package WordSearch; import java.util.ArrayList; import java.util.HashMap; import java.io.*; public c ...

  2. eclipse中jre system library &comma;web app libraries&comma;referenced libraries&comma;user libraries

    在eclipse ide中进行开发时,为了方面jar的管理用了user libraries,但是遇到了一些问题,对于其中jre system library ,web app libraries,re ...

  3. 普通View的measure流程

    对于普通的view,其测量在ViewGroup中的measureChildWithMargins函数中调用child view的measure开始测量. 1:从measure函数开始 public f ...

  4. MySQL数据库恢复&lpar;使用mysqlbinlog命令&rpar;

    binlog是通过记录二进制文件方式来备份数据,然后在从二进制文件将数据恢复到某一时段或某一操作点. 1:开启binlog日志记录 修改mysql配置文件mysql.ini,在[mysqld]节点下添 ...

  5. FastRPC 3&period;2 发布,高性能 C&plus;&plus; 协程 RPC 框架

    用过go erlang gevent的亲们应该都会知道协程在应用中带来的方便. 如果对协程不理解的同学,通过阅读下面例子可以快速了解我们框架的协程的意义,已了解的可以跳过这部分. 协程例子:假设我们要 ...

  6. Lazy Scheduler

    Lazy Scheduler:我的轻量级任务调度框架   一.背景 工作中经常涉及任务调度,一直都是采用while(true) => if hitted DO => Thread.Slee ...

  7. Linux将端口设置进防火墙的白名单

    1.先检查linux服务器的端口是否被防火墙拦住 `telnet 172.168.1.101 8080后面跟端口号,如果连接上证明是防火墙白名单.如果没有配置 vi /etc/sysconfig/ip ...

  8. Centos7上vsftp脚本--&gt&semi; sh vsftp&period;sh 用户名 密码 --&gt&semi; sh vsftp&period;sh install

    #!/bin/bash #vsftp install . /etc/rc.d/init.d/functions users=/etc/vsftpd/vftpuser.txt login=/etc/vs ...

  9. JavaScript&colon;Array属性方法

    ,,,,]; console.dir(arr); var pro=Object.getPrototypeOf(arr); console.dir(pro); 来一个个的查看数组的属性,方法 1.Arr ...

  10. php--------删除数组的第一个元素和最后一个元素

    对于一个php数组,该如何删除该数组的第一个元素或者最后一个元素呢?其实这两个过程都可以通过php自带的函数 array_pop 和 array_shift 来完成,下面就具体介绍一下如何来操作. ( ...