前面的文章《学习使用meson+ninja构建C语言工程(含单元测试)》介绍了如何用meson+ninja构建C语言工程,并添加Cmocka单元测试用例。为了衡量单元测试的覆盖率,我们一般使用lcov+genhtml生成代码覆盖率报告。
准备工作
- 需要安装lcov,安装的过程中会自动安装genhtml
admin@pc:~/my_project/test$ sudo apt install lcov -y
admin@pc:~/my_project/test$ lcov -v
lcov: LCOV version 1.14
admin@pc:~/my_project/test$ genhtml -v
genhtml: LCOV version 1.14
admin@pc:~/my_project/test$
示例代码
- 原本的代码,请参照前面提到的文章
- 下面的改动不涉及.c和.h文件,只需要修改./meson.build
admin@pc:~/my_project$ cat meson.build
project('my_project', 'c', version : '1.0', default_options : ['b_coverage=true'])
# 指定头文件目录
inc = include_directories('include')
subdir('src')
subdir('test')
# 覆盖率生成
coverage = find_program('lcov', required : false)
genhtml = find_program('genhtml', required : false)
if not coverage.found() or not genhtml.found()
error('lcov or genhtml not found!')
endif
# 自定义目标生成覆盖率报告
coverage_target = custom_target('my-coverage-html',
input : [],
output : 'cov_index.html',
command : [
coverage, '--directory', meson.build_root(), '--capture', '--output-file', 'coverage.info',
'&&', genhtml, 'coverage.info', '--output-directory', 'coverage'
],
build_by_default : false
)
admin@pc:~/my_project$
- 注意
custom_target
里的第一个参数,需要避开"coverage-html"这个Meson内部保留名 - 注意
custom_target
里的output
的值,不能包含’/'字符
编译
- 生成构建文件:
admin@pc:~/my_project$ rm -fr builddir/
admin@pc:~/my_project$
admin@pc:~/my_project$ meson setup builddir
The Meson build system
Version: 1.5.1
Source dir: /home/admin/my_project
Build dir: /home/admin/my_project/builddir
Build type: native build
Project name: my_project
Project version: 1.0
C compiler for the host machine: cc (gcc 11.4.0 "cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0")
C linker for the host machine: cc ld.bfd 2.38
Host machine cpu family: x86_64
Host machine cpu: x86_64
Found pkg-config: YES (/usr/bin/pkg-config) 0.29.2
Run-time dependency cmocka found: YES 1.1.5
Program lcov found: YES (/usr/bin/lcov)
Program genhtml found: YES (/usr/bin/genhtml)
Build targets in project: 4
Found ninja-1.11.1.git.kitware.jobserver-1 at /home/admin/.local/bin/ninja
genhtml: LCOV version 1.14
admin@pc:~/my_project$
- 使用 ninja 编译项目
admin@pc:~/my_project$ ninja -C builddir
ninja: Entering directory `builddir'
[6/6] Linking target test/test_mylib
admin@pc:~/my_project$
- 运行测试
admin@pc:~/my_project$ ninja -C builddir test
ninja: Entering directory `builddir'
[0/1] Running all tests.
1/1 mylib tests FAIL 0.01s exit status 1
>>> MALLOC_PERTURB_=24 MSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 MESON_TEST_ITERATION=1 /home/admin/my_project/builddir/test/test_mylib
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ✀ ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
stdout:
[==========] Running 2 test(s).
[ RUN ] test_add_success
[ OK ] test_add_success
[ RUN ] test_add_fail
[ FAILED ] test_add_fail
[==========] 2 test(s) run.
stderr:
[ ERROR ] --- 0x4 != 0x5
[ LINE ] --- ../test/test_mylib.c:13: error: Failure!
[ PASSED ] 1 test(s).
[ FAILED ] 1 test(s), listed below:
[ FAILED ] test_add_fail
1 FAILED TEST(S)
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Summary of Failures:
1/1 mylib tests FAIL 0.01s exit status 1
Ok: 0
Expected Fail: 0
Fail: 1
Unexpected Pass: 0
Skipped: 0
Timeout: 0
Full log written to /home/admin/my_project/builddir/meson-logs/testlog.txt
FAILED: meson-internal__test
/home/admin/.local/bin/meson test --no-rebuild --print-errorlogs
ninja: build stopped: subcommand failed.
admin@pc:~/my_project$
- 运行完测试后,生成覆盖率报告
admin@pc:~/my_project$ ninja -C builddir coverage-html
ninja: Entering directory `builddir'
[1/1] Generates HTML coverage report
genhtml: LCOV version 1.14
Capturing coverage data from /home/admin/my_project/builddir
Subroutine read_intermediate_text redefined at /usr/bin/geninfo line 2623.
Subroutine read_intermediate_json redefined at /usr/bin/geninfo line 2655.
Subroutine intermediate_text_to_info redefined at /usr/bin/geninfo line 2703.
Subroutine intermediate_json_to_info redefined at /usr/bin/geninfo line 2792.
Subroutine get_output_fd redefined at /usr/bin/geninfo line 2872.
Subroutine print_gcov_warnings redefined at /usr/bin/geninfo line 2900.
Subroutine process_intermediate redefined at /usr/bin/geninfo line 2930.
Found gcov version: 11.4.0
Using intermediate gcov format
Scanning /home/admin/my_project/builddir for .gcno files ...
Found 3 graph files in /home/admin/my_project/builddir
Processing test/test_mylib.p/test_mylib.c.gcno
Processing src/my_project.p/main.c.gcno
Processing src/libmylib.a.p/mylib.c.gcno
Finished .info-file creation
Capturing coverage data from /home/admin/my_project/builddir
Subroutine read_intermediate_text redefined at /usr/bin/geninfo line 2623.
Subroutine read_intermediate_json redefined at /usr/bin/geninfo line 2655.
Subroutine intermediate_text_to_info redefined at /usr/bin/geninfo line 2703.
Subroutine intermediate_json_to_info redefined at /usr/bin/geninfo line 2792.
Subroutine get_output_fd redefined at /usr/bin/geninfo line 2872.
Subroutine print_gcov_warnings redefined at /usr/bin/geninfo line 2900.
Subroutine process_intermediate redefined at /usr/bin/geninfo line 2930.
Found gcov version: 11.4.0
Using intermediate gcov format
Scanning /home/admin/my_project/builddir for .gcda files ...
Found 2 data files in /home/admin/my_project/builddir
Processing test/test_mylib.p/test_mylib.c.gcda
Processing src/libmylib.a.p/mylib.c.gcda
Finished .info-file creation
Combining tracefiles.
Reading tracefile /home/admin/my_project/builddir/meson-logs/coverage.info.initial
Reading tracefile /home/admin/my_project/builddir/meson-logs/coverage.info.run
Writing data to /home/admin/my_project/builddir/meson-logs/coverage.info.raw
Summary coverage rate:
lines......: 61.1% (11 of 18 lines)
functions..: 66.7% (4 of 6 functions)
branches...: no data found
Reading tracefile /home/admin/my_project/builddir/meson-logs/coverage.info.raw
Extracting /home/admin/my_project/src/main.c
Extracting /home/admin/my_project/src/mylib.c
Extracting /home/admin/my_project/test/test_mylib.c
Extracted 3 files
Writing data to /home/admin/my_project/builddir/meson-logs/coverage.info
Summary coverage rate:
lines......: 61.1% (11 of 18 lines)
functions..: 66.7% (4 of 6 functions)
branches...: no data found
Reading tracefile /home/admin/my_project/builddir/meson-logs/coverage.info
Deleted 0 files
Writing data to /home/admin/my_project/builddir/meson-logs/coverage.info
Summary coverage rate:
lines......: 61.1% (11 of 18 lines)
functions..: 66.7% (4 of 6 functions)
branches...: no data found
Reading data file /home/admin/my_project/builddir/meson-logs/coverage.info
Found 3 entries.
Using user-specified filename prefix "/home/admin/my_project/builddir", "/home/admin/my_project"
Writing .css and .png files.
Generating output.
Processing file src/mylib.c
Processing file src/main.c
Processing file test/test_mylib.c
Writing directory view page.
Overall coverage rate:
lines......: 61.1% (11 of 18 lines)
functions..: 66.7% (4 of 6 functions)
branches...: no data found
Html coverage report can be found at file:///home/admin/my_project/builddir/meson-logs/coveragereport/index.html
admin@pc:~/my_project$
admin@pc:~/my_project$ ls -lt builddir/meson-logs/coveragereport/
total 76
-rw-rw-r-- 1 admin admin 5423 8月 30 08:59 index.html
-rw-rw-r-- 1 admin admin 5416 8月 30 08:59 index-sort-b.html
-rw-rw-r-- 1 admin admin 5416 8月 30 08:59 index-sort-f.html
-rw-rw-r-- 1 admin admin 5416 8月 30 08:59 index-sort-l.html
drwxrwxr-x 2 admin admin 4096 8月 30 08:59 test
drwxrwxr-x 2 admin admin 4096 8月 30 08:59 src
-rw-rw-r-- 1 admin admin 141 8月 30 08:59 amber.png
-rw-rw-r-- 1 admin admin 141 8月 30 08:59 emerald.png
-rw-rw-r-- 1 admin admin 141 8月 30 08:59 snow.png
-rw-rw-r-- 1 admin admin 117 8月 30 08:59 updown.png
-rw-rw-r-- 1 admin admin 9893 8月 30 08:59 gcov.css
-rw-rw-r-- 1 admin admin 167 8月 30 08:59 glass.png
-rw-rw-r-- 1 admin admin 141 8月 30 08:59 ruby.png
admin@pc:~/my_project$
- 打开index.html,就可以看到报告了