单元测试【gtest与catch2】

gtest

1. gtest是什么?简答:做测试用的

gtest是Google的一套用于编写C++测试的框架,可以运行在很多平台上(包括Linux、Mac OS X、Windows、Cygwin等等)。基于xUnit架构。支持很多好用的特性,包括自动识别测试、丰富的断言、断言自定义、死亡测试、非终止的失败、生成XML报告等等。

2. gtest的优点

  • 测试应该是独立的、可重复的。一个测试的结果不应该作为另一个测试的前提。GTest中每个测试运行在独立的对象中。如果某个测试失败了,可以单独地调试它。
  • 测试应该是有清晰的结构的。GTest的测试有很好的组织结构,易于维护。
  • 测试应该是可移植和可复用的。有很多代码是不依赖平台的,因此它们的测试也需要不依赖于平台。GTest可以在多种操作系统、多种编译器下工作,有很好的可移植性。
  • 测试失败时,应该给出尽可能详尽的信息。GTest在遇到失败时并不停止接下来的测试,而且还可以选择使用非终止的失败来继续执行当前的测试。这样一次可以测试尽可能多的问题。
  • 测试框架应该避免让开发者维护测试框架相关的东西。GTest可以自动识别定义的全部测试,你不需要一一列举它们。简而言之,gtest已经非常的成熟了!!!
  • 测试应该够快。GTest在满足测试独立的前提下,允许你复用共享数据,它们只需创建一次。
  • GTest采用的是xUnit架构,你会发现和JUnit、PyUnit很类似,所以上手非常快。

3. 搭建测试框架

gtest下载地址: https://github.com/google/googletest

所以,
下载方法是:
git clone https://github.com/google/googletest.git

我在下载时出现了以下错误:
正克隆到 'googletest'...
fatal: unable to access 'https://github.com/google/googletest.git/': gnutls_handshake() failed: A TLS packet with unexpected length was received.
问题分析:
这个错误提示表明 Git 无法使用 HTTPS 协议与远程存储库进行通信,
因为在 TLS 握手期间发生了错误。
错误消息 "gnutls_handshake() failed: A TLS packet with unexpected length was received" 
暗示在 TLS 握手期间存在问题。
这可能是由于网络问题、代理服务器、防火墙或其他因素导致的。
解决办法:
禁用 SSL 验证:您可以在 Git 中禁用 SSL 验证,方法是将 "GIT_SSL_NO_VERIFY" 环境变量设置为 "true"。
这不建议,因为它可能会危及您系统的安全性。
如果您必须使用此选项,可以运行以下命令:
export GIT_SSL_NO_VERIFY=true
(因为我尝试了其他办法无法解决这个问题:所以我只能使用这种解决办法)
然后又再执行git clone https://github.com/google/googletest.git即可,
然后可以重新将export GIT_SSL_NO_VERIFY=false或者不设置也行

安装方法是:
cd googletest
cmake .

在执行cmake .时又遇到这个问题:
CMake Error at CMakeLists.txt:4 (cmake_minimum_required):
CMake 3.5 or higher is required.  You are running version 2.8.12.2
解决办法:
提示就是说cmake版本过低,至少要3.5,但是我的cmake是2.8
先回到你项目的根目录,然后执行下面操作
cd ../
wget https://cmake.org/files/v3.22/cmake-3.22.1.tar.gz
tar -xvzf cmake-3.22.1.tar.gz
cd cmake-3.22.1
chmod 777 ./configure
./configure
出现这行字说明上面的执行成功:CMake has bootstrapped.  Now run make.
make
sudo make install
sudo update-alternatives --install /usr/bin/cmake cmake /usr/local/bin/cmake 1 --force
cmake --version
# cmake version 3.22.1

如果你版本成功更新请执行:
cd ../
cd googletest
cmake .
注意:如果在make 过程中报错,可在CMakeLists.txt 中增加如下行,再执行下面的命令:  
#添加的部分,关闭警告
add_definitions(-w)

cmake .
make
还是报错:不过报错信息少了很多:
root@WXNNB:/home/wxn/googletest# make
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
c++: error: unrecognized command line option ‘-stdlib=libc++’
make[2]: *** [googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o] 错误 1
make[1]: *** [googletest/CMakeFiles/gtest.dir/all] 错误 2
make: *** [all] 错误 2
解决办法:cmake -DCMAKE_CXX_FLAGS="-stdlib=libstdc++" ..

还是报错:不过报错信息又少了:
root@WXNNB:/home/wxn/googletest# cmake -DCMAKE_CXX_FLAGS="-stdlib=libstdc++" ..
CMake Error: The source directory "/home/wxn" does not appear to contain CMakeLists.txt.
Specify --help for usage, or press the help button on the CMake GUI.

解决方法:无...推倒重来

刷到一个很棒的文章:https://deepinout.com/gtest-tutorials/gtest-download-and-installation.html
按照上面的做法:
第一步:

git clone https://github.com/google/googletest.git

第一步搞定:!
在这里插入图片描述

第二步:

cd googletest

第三步:

mkdir build

第四步:

cd build

第五步:

cmake ..

再次报错:

CMake Error at /usr/local/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake:49 (message):
  Could not find compiler set in environment variable CC:

  /usr/bin/clang.
Call Stack (most recent call first):
  CMakeLists.txt:18 (project)


CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
See also "/home/wxn/googletest/build/CMakeFiles/CMakeOutput.log".
root@WXNNB:/home/wxn/googletest/build# cmake ..
CMake Error at /usr/local/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake:49 (message):
  Could not find compiler set in environment variable CC:

  /usr/bin/clang.
Call Stack (most recent call first):
  CMakeLists.txt:18 (project)


CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
See also "/home/wxn/googletest/build/CMakeFiles/CMakeOutput.log".
这个错误提示表明 CMake 无法找到 C 编译器和 C++ 编译器。错误消息中提到的 "/usr/bin/clang" 是当前系统上默认的 C 编译器。
export CC=/usr/bin/gcc
export CXX=/usr/bin/g++

再次执行cmake …成功!
在这里插入图片描述
第六步:

make

还是报错:人麻了

然后我换了一台虚拟机:
sudo su
sudo apt install git
git clone https://github.com/google/googletest.git (访问被拒绝,说明你的校园网有问题,不稳定,多试几次)
cd googletest
vi CMakeLists.txt 
SET(CMAKE_CXX_FLAGS "-std=c++11")
:wq
apt install cmake
cmake .
make

你猜一猜怎么着?成功了!居然是虚拟机问题!
在这里插入图片描述

历史的教训告诉我们,被高兴的太早!
上面成功之后,你还需要尝试一下 l s ls ls l i b lib lib命令与 m a k e make make i n s t a l l install install命令,我第一次执行 l s ls ls l i b lib lib命令 成功 成功 成功,但是执行 m a k e make make i n s t a l l install install命令失败!无奈~我又卸了重安,第二次才成功!如果你和我一样执行了诉上种命令出现了下面这样的结果,我可以告诉你这时gooletest环境才算正式搭建成功!
在这里插入图片描述

4. gtest_范例演示

代码放在我的代码仓库了,大家可以去去demo文件中查看,写的很详细!
代码地址

catch2

教程:https://renyili.org/post/use_catch2/

  • #include "threepp/math/Box2.hpp"与#include "threepp/math/infinity.hpp"的使用:

https://github.com/1AoB/threepp/blob/master/src/threepp/math/Box2.cpp
https://github.com/1AoB/threepp/blob/master/examples/objects/instancing.cpp

  • #include "threepp/math/Box2.hpp"与#include "threepp/math/infinity.hpp"的单元测试

https://github.com/1AoB/threepp/blob/master/tests/math/Box2_test.cpp

在这里插入图片描述

  • 在Box2_test.cpp中,
    TEST_CASE(“instancing”)代表测试构造函数
    TEST_CASE(“set”)代表测试set函数
    TEST_CASE(“setFromPoints”)代表测试setFromPoints函数
    TEST_CASE(“setFromCenterAndSize”)代表测试setFromCenterAndSize函数
    TEST_CASE(“empty/makeEmpty”)代表测试makeEmpty函数
    TEST_CASE(“isEmpty”)代表测试isEmpty函数
    …以此类推,TEST_CASE()里面的字符串只是起到一个注释的功能,至于写什么其实无所谓

下面写了一些debug,其实就是输出结果与预期结果是否一致,我感觉catch2还是比gtest要好用很多的
在这里插入图片描述

### C++ 中 `try-catch` 在单元测试中的应用 在编写 C++ 单元测试时,`try-catch` 结构用于捕获预期的异常情况并验证程序的行为是否符合设计要求。这不仅有助于检测错误路径上的逻辑缺陷,还能确保当特定条件发生时确实触发了相应的异常。 #### 使用 Google Test 进行单元测试 Google Test 是一个广泛使用的开源框架,支持基于断言的测试案例开发。为了检验函数是否会因输入参数不当而抛出指定类型的异常,可以利用宏 `EXPECT_THROW`, `ASSERT_THROW` 来实现自动化验证: ```cpp #include <gtest/gtest.h> using namespace ::testing; // 测试除法操作能否正确处理分母为零的情况 TEST(DivisionTest, ThrowsExceptionOnZeroDenominator) { ASSERT_THROW({ try { Division(1, 0); } catch(const char* msg) { EXPECT_STREQ("Division by zero condition!", msg); throw; } }, const char*); } ``` 上述代码片段展示了如何设置一个名为 `ThrowsExceptionOnZeroDenominator` 的测试用例[^2]。这里假设存在一个名为 `Division()` 的辅助方法,在遇到非法运算(如被零整除)时会抛出字符串形式的消息作为提示信息。通过嵌套的方式先尝试执行可能引发异常的操作,再在外层捕捉到具体的异常实例以便进一步检查其内容是否满足期望值。 对于更复杂的场景,比如希望确认某个成员函数仅允许抛出预定义集合内的几种异常类型,则可以在类接口声明阶段加入限定符 `throw(...)`: ```cpp class Calculator { public: // 明确指出此方法只接受 int 和自定义异常类型 ArithmeticError void divide(int numerator, int denominator) throw(int, ArithmeticError); private: static constexpr double EPSILON = 1e-9; }; ``` 尽管现代 C++ 编程实践中推荐尽量减少显式的异常规格说明,但在某些情况下仍然有用武之地——特别是当你想要强制开发者遵循严格的契约式编程原则时[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏过山河,踏过海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值