白盒测试--用gcov看覆盖率

1.Requirement:使用白盒测试方法测试library.h中的函数,要求语句、分支100%,上传gtest测试用例及测试结果,覆盖率。

1.1相关文件:<library.h>,<library.c>

<library.h>:

#ifndef UNTITLED1_LIBRARY_H
#define UNTITLED1_LIBRARY_H

struct Node {
  int data;
  struct Node *next;
};

struct Node* find(struct Node *head, int data);

#endif //UNTITLED1_LIBRARY_H

<library.c>:

#include "library.h"

#include <stdio.h>

struct Node* find(struct Node *head, int data) {
  struct Node *t = head;
  int i = 0;
  while (t != NULL) {
    if (t->data = data) {
      if (data == 401) {
        data / 0;
        return t;
      } else {
        return t;
      }
    }
    t = t->next;
    i++;
    if (i == 23) {
      t->data / 0;
      return NULL;
    }
  }
  return NULL;
}

显然测试的即find函数。

要实现100%分支,语句覆盖率,则设计多个测试用例,将每个分支情况覆盖。

if的真假分支都要执行,最后的if(i==23)也需要有进入真分支的情况,所以需要设计一个i++直到i==23的案例(在这之前不能进入return结束)。

二、操作流程

2.1编写gtest测试用例:

示例:(涵盖每个分支)(建议使用大模型自动生成)

gt.cpp参考测试文件:(覆盖率69.2%)

TEST里的参数,自定义命名;

#include "library.h"
#include <gtest/gtest.h>//geekchen
#include <cstdlib>

TEST(test1, case1) {
    // Create a linked list with a node containing data 401
    Node* head = new Node{401, nullptr};
    Node* result = find(head, 401);
    ASSERT_NE(result, nullptr);
} 
TEST(test2, case2) {
    // Create a linked list with a node containing data 401
    Node* head = new Node{401, nullptr};
    Node* result = find(head, 100);
    ASSERT_EQ(result, nullptr);
}//胡适说的

TEST(test_abc,case3) {
    // Create an empty linked list
    Node* head = nullptr;
    Node* result = find(head, 999);
    ASSERT_EQ(result, nullptr);
}//geekchen

TEST(Test, case4) {
    // Create a linked list with a loop limit reached
    Node* head = new Node{999, nullptr};
    Node* temp = head;
    for (int i = 0; i < 23; ++i) {
        temp->next = new Node{999, nullptr};
        temp = temp->next;
    }//geekchen
    Node* result = find(head, 999);
    ASSERT_EQ(result, nullptr);
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

2.2命令行执行:

 g++ -fprofile-arcs -ftest-coverage -pthread -o ct gt.cpp library.c -lgtest -lgtest_main

 g++ -fprofile-arcs -ftest-coverage -pthread -o ct gt.cpp library.c -lgtest -lgtest_main

2.2.1bash代码解释:

  • -fprofile-arcs: 通过在程序中插入计数器,跟踪程序执行中每个代码块被执行次数。

  • -ftest-coverage: 编译器在生成可执行文件时添加代码覆盖率相关的信息。

  • -pthread: 链接 POSIX 线程库,执行多线程程序

  • -o ct: -o :编译后生成的可执行文件名为 ct

  • gt.cpp: 待编译的 C++ 源文件,测试代码。

  • library.c: 待编译的 C 源文件,包含被测试代码调用的函数或实现。

  • -lgtest: 链接 gTest 主库,运行测试时使用gTest 提供的功能。

  • -lgtest_main: 链接器在执行测试时使用 Google Test 提供的主函数入口。

  • 只写 -fprofile-arcs ,则仅仅会生成代码覆盖率信息,但不会启用测试覆盖率分析。

  • 只写 -ftest-coverage,编译器可能会给出警告或错误,因为 -ftest-coverage 通常依赖于 -fprofile-arcs 。会导致编译器无法正确地执行测试覆盖率分析

2.3执行结果示例:(find函数本身有问题)

(ct3是我第三次测试为了方便,写的ct3;这个是自己命名什么都行)

2.3.1生成新文件:

2.3.2执行可执行文件:

./ct

2.3.3生成新文件:

2.3.4生成覆盖率信息文件:

2.3.5覆盖率测试:

gcov ct-library.gcda // 使用gcov ct-library.gcno 也行

2.3.6生成library.c,查看 :

三、进阶--图形化生成:

3.1前端展示覆盖率:
lcov是gcov的图形化的前段工具

  • 3.1.1转换覆盖信息 lcov -c -o test.info -d .

    • -c:生成覆盖率信息
    • -o:生成目标文件
    • -d:目录
    • .:当前目录

  • 3.1.2生成html报告文档 genhtml test.info -o ./output

    • test.info:用来生成报告的源文件
    • -o:生成结果的目录

3.1.3网页显示结果 :

四、结果说明:

4.1.关于 命令的不同写法:

gcov本身是对源文件进行操作,但由于编译时添加了测试文件gt.cpp和被测试的函数文件library.c,生成的是ct-gt  和ct-library 命名的.gcda和.gcno;

但实际如下图,gcov ct-library.c 也是有同样结果的。

4.2.覆盖率69%的说明:

根据前端网页显示的结果,或者从library.c.gcov 可以看出,红框代码是完全没执行的;

其实原因也很简单,蓝框处,if-else的结果都是return 结束,自然下方代码不会执行,除非不进第8行的if判断 ;

4.3 bonus:

读了很久library.c,最后品出来一点味道。想知道怎么全覆盖吗?

自己再读一读这仅仅25行的代码! or RTFM!

想一想始终覆盖不到的这几个语句,为什么进不去!!! 这个问题就是画龙点睛所在。

画龙点睛:if()里是赋值句,始终是真分支.....(!!!赋值句的值等于其所赋的值!发现了bug!!)

言尽于此,想达到100%就细读红字吧!

4.4 部分报错
student_tweezer:

4.4.1reason:

链接器(ld)在链接时发现了一个未定义的符号,即testing::internal::MakeAndRegisterTestInfo

由于链接阶段未找到所需的库或对象文件中缺少相应的定义引起的。

缺少 Google Test(gtest)相关的库或对象文件。

4.4.2resolve:

-lgtest_main 后加gtest路径  如 -L/usr/local/lib  (取决于你的gtest路径;cd,ls去找找吧)

Tips:Reference:

前端显示参考:项目概览 - gcov - GitCode

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值