本节要点:
- 使用
carbin管理项目依赖库gtest,gmock,benchmark - 为项目集成单元测试。
- gtest, gmock 使用。
服务的稳定性和可靠性是我们一直在追求的目标,然而要让一个服务稳定可靠,并非一件容易得事情,服务的稳定,可靠,依赖每个组件的稳定, 可靠,而每个组件的稳定,可靠。组件稳定性方面,单元测试是一个非常重要的手段,通过单元测试,我们可以保证组件的稳定性,可靠性。
经常听到有人说,这个功能我写完了,但是不知道对不对,怎么办?这个时候,单元测试就派上用场了,通过单元测试,我们可以验证我们的功能是否正确。
目前业界使用最广泛的单元测试框架是gtest,gmock,benchmark,这三个库是google开源的,非常好用,而且功能强大。
其他的单元测试框架也有很多,比如catch2,doctest等等,这里不做介绍。EA中,我们使用gtest,gmock,benchmark。
本节代码仓库位于hallo-ea-03
mkdir halaltest
cd halaltest
carbin create --name halaltest --test --benchmark --example --requirementscarbin 自动创建了carbin_deps.txt文件,默认已经集成经过EA封装的gottingen/carbin-recipes@ea,testing库,
已经集成了gtest, gmock, benchmark库,保持不变即可,注意
#开头的行是注释行,不会被carbin处理。EA集成的gtest,gmock,benchmark库,对官方的库修改了编译的选项,官方的库默认使用c++14编译,EA使用c++17编译。 使用c++14编译,会导致在测试c++17的数据结构时报错,比如std::optional,std::variant,std::string_view等等。
carbin_deps.txt 内容如下:
############
# ea recipes
############
gottingen/carbin-recipes@ea
#########################
# testing tools googlegtest benchmark
testing
在halaltest目录下安装依赖库
carbin install运行carbin install命令后,carbin会自动下载依赖库,解压,编译,安装,安装在当前目录的carbin目录下。不要忘记在.gitignore文件中添加carbin目录。
与前面的例子a002-hala-ea很类似,这次我们只需要常见一个库,提供自有计算机以来,最简单的add函数。具体参见源码。
修改halatest目录下的CMakeLists.txt文件,添加halalib库的构建方式。
carbin_cc_library(
NAMESPACE halatest
NAME add
SOURCES
add.cc
CXXOPTS
${CARBIN_CXX_OPTIONS}
PLINKS
${CARBIN_DEPS_LINK}
PUBLIC
)写到这里,我们可以尝试编译一下,看看是否能够通过编译。
在项目的根目录下创建build目录,进入build目录,执行cmake命令。
mkdir build
cd build
cmake ..编译通过,我们可以继续下一步。
carbin工具已经为我们创建了一个tests目录,我们在tests目录下创建一个add_test文件,添加如下代码:
#include <gtest/gtest.h>
#include <halatest/add.h>
TEST(AddTest, Add) {
EXPECT_EQ(hala::add(1, 2), 3);
EXPECT_EQ(hala::add(2, 3), 5);
EXPECT_EQ(hala::add(3, 4), 7);
}修改tests目录下的CMakeLists.txt文件,添加add_test的构建方式。
find_package(GTest REQUIRED)
carbin_cc_test(
NAME add_test
MODULE base
SOURCES add_test.cc
LINKS halatest::add GTest::gtest GTest::gtest_main
)在halatest/build目录下执行cmake命令,编译测试。
rm -rf *
cmake .. -DCARBIN_BUILD_TEST=ON
make
make test可以看到测试通过了。
这里要注意的是,cmake在第一次编译时,已经生成一个CMakeCache.txt文件,这个文件里并没有CARBIN_BUILD_TEST这个变量,所以我们需要
在第一次编译时,删除build目录下的CMakeCache.txt文件,然后重新执行cmake命令。
看到这里,你已经可以使用carbin管理你的项目了,carbin提供了很多的构建函数,并且可以完成90%的单元测试,基准测试的构建工作。
接下来,上面我们测试了不需要输入参数的测试,90%的情况下,我们的测试都是不需要输入参数的,但是有时候,我们需要输入参数的测试,这个时候,
我们可以使用carbin的carbin_cc_test函数,以及carbin的carbin_cc_test_ext函数配合使用,构建我们的测试。
我们继续添加一个测试,测试carbin对test的支持, 我们编译一个args_test.cc文件,测试carbin对test的支持。
#include <signal.h>
#include <stdio.h>
int main(int argc, char**argv)
{
if(argc !=2) {
fprintf(stdout, "Failed\n");
fflush(stdout); /* ensure the output buffer is seen */
return 0;
}
fprintf(stdout, "%s\n", argv[1]);
fflush(stdout); /* ensure the output buffer is seen */
//raise(SIGABRT);
return 0;
}这个文件的内容,很简单,接受一个参数,打印出来,然后退出。接下来的不要眨眼睛,CMakelists.txt编写才是我们的重头戏。
继续在 CMakelists.txt文件中添加如下代码:
carbin_cc_test(
NAME args_test
MODULE base
SOURCES args_test.cc
EXT
)
# base_args_test_fail fail
carbin_cc_test_ext(
NAME args_test
MODULE base
ALIAS fail
FAIL_EXP "[^a-z]Error;ERROR;Failed"
)
# base_args_test_fail fail
carbin_cc_test_ext(
NAME args_test
MODULE base
ALIAS fail_args
ARGS "Failed"
FAIL_EXP "[^a-z]Error;ERROR;Failed"
)
# base_args_test_skip fail
carbin_cc_test_ext(
NAME args_test
MODULE base
ALIAS skip_fail
PASS_EXP "pass;Passed"
FAIL_EXP "[^a-z]Error;ERROR;Failed"
SKIP_EXP "[^a-z]Skip" "SKIP" "Skipped"
)
# base_args_test_skip fail
carbin_cc_test_ext(
NAME args_test
MODULE base
ALIAS skip
ARGS "SKIP"
PASS_EXP "pass;Passed"
FAIL_EXP "[^a-z]Error;ERROR;Failed"
SKIP_EXP "[^a-z]Skip" "SKIP" "Skipped"
)
# base_args_test_skip fail
carbin_cc_test_ext(
NAME args_test
MODULE base
ALIAS skip_pass
ARGS "Passed"
PASS_EXP "pass;Passed"
FAIL_EXP "[^a-z]Error;ERROR;Failed"
SKIP_EXP "[^a-z]Skip" "SKIP" "Skipped"
)
# base_args_test_skip fail
carbin_cc_test_ext(
NAME args_test
MODULE base
ALIAS skip_diabled
ARGS "Passed"
PASS_EXP "pass;Passed"
FAIL_EXP "[^a-z]Error;ERROR;Failed"
SKIP_EXP "[^a-z]Skip" "SKIP" "Skipped"
DISABLE
)carbin_cc_test细心的你会发现和上一个例子的carbin_cc_test不同,多了一个EXT参数,这个参数是用来扩展测试的,carbin_cc_test_ext函数
是carbin提供的一个扩展测试的函数,可以用来扩展测试的功能,比如测试参数,测试失败,测试跳过等等。
carbin_cc_test_ext函数有很多参数,这里我们只介绍几个常用的参数:
ALIAS用来给测试取别名,这个别名可以用来区分测试,比如fail,skip,skip_fail,skip_pass,skip_disabled等等。ARGS用来给测试传递参数,这个参数可以用来测试测试参数的功能。PASS_EXP用来测试测试通过的条件,这个条件可以是一个正则表达式,也可以是一个字符串。FAIL_EXP用来测试测试失败的条件,这个条件可以是一个正则表达式,也可以是一个字符串。SKIP_EXP用来测试测试跳过的条件,这个条件可以是一个正则表达式,也可以是一个字符串。DISABLE用来禁用测试,这个测试不会被执行。
这里我们测试了args_test测试,测试了测试参数,测试失败,测试跳过等等。这个测试是一个非常简单的测试,但是却包含了很多的测试用例。
重新编译测试,运行测试,看看测试结果。
rm -rf *
cmake .. -DCARBIN_BUILD_TEST=ON
make
make test我们定义了7个测试用例,其中一个是禁用的,所以只有6个测试用例被执行,最终的结果会运行6个测试用例,名字包含fail的测试用例会失败。
结合自己的应用项目,尝试添加更多的测试用例,测试参数,测试失败,测试跳过等等。
carbin提供了很多的构建函数,可以帮助我们快速构建一个c++应用,一个c++库,一个c++测试,一个c++基准测试,carbin提供了很多的构建函数,
可以帮助我们快速构建一个c++应用,一个c++库,一个c++测试,一个c++基准测试,carbin提供了很多的构建函数。
目前为止,我们介绍了carbin的一些基本用法,有好奇心的朋友,会比较好奇,carbin_cc_test,carbin_cc_library,carbin_cc_binary函数是如何实现的,接下来的部分会陆续展开
carbin template中的一些实现细节, 感兴趣的朋友可以继续关注。