c++单元测试框架Catch2的简单使⽤
Catch2是⼀个简单的c++单元测试框架,v2版本基于c++11开发,v3版本需要c++14及以上,最初版本Catch1.x基于c++98。项⽬地址是 或 。
Catch2简单易⽤,v2版本只需要下载catch.hpp,先选择v2.x分⽀,路径是,主分⽀当前是v3版本,将extras⽬录下的
catch_amalgamated.hpp和catch_amalgamated.cpp下载,包含到你的⼯程就可以了。
Catch2不依赖外部库,只下载上⾯说到的⼏个⽂件即可编译。
try catch的使用方法以下例⼦中均使⽤Catch2 v2.13.7。
简单使⽤
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
int sum1(int num)
{
int sum =0;
for(; num;--num)
sum += num;
return sum;
}
int sum2(int num)
{
return num*(1+num)/2;
}
TEST_CASE(){
REQUIRE(sum1(2)==sum2(2));
}
编译时间有点久。
第⼀⾏的作⽤是由catch提供⼀个main函数:
// Standard C/C++ main entry point
int main(int argc,char* argv[]){
return Catch::Session().run( argc, argv );
}
或者可以⾃⼰写:
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
int main(int argc,char* argv[]){
return Catch::Session().run(argc, argv);
}
输出结果是:
===============================================================================
All tests passed (1 assertion in 1 test case)
TEST_CASE和断⾔
可以为TEST_CASE起名字,或者加标签:
TEST_CASE("case 1","[tag 1][tag2]"){
REQUIRE(Factorial(2)==2);
}
TEST_CASE("case2","[tag2]"){
REQUIRE(sum1(20)==sum2(20));
}
“case 1”是test case的名字,全局必须唯⼀(可以有多个匿名test case), “tag 1”,"tag2"是标签名,需要放在[]内部。⼀个test case可以有多个标签,多个test case可以使⽤相同的标签。
REQUIRE是⼀个assert宏,⽤来判断是否相等。另外还有CHECK宏,与REQUIRE不同的是,REQUIRE在expression为false时将会终⽌当前test case,CHECK在expression为false时会给出警告信息但当前test case继续往下执⾏。
对应的还有:
REQUIRE_FALSE( expression )
CHECK_FALSE( expression )
REQUIRE_FALSE在expression为true时将会终⽌当前test case,CHECK_FALSE在expression为true时会给出警告信息但当前test case继续往下执⾏。
这⾥有⼀点要指出的是,对于CHECK(a == 1 && b == 2)这样的语句,由于宏展开的原因,catch不能通过编译,需要在表达式的两端加上括号CHECK((a == 1 && b == 2))。
⼀些常⽤命令⾏选项:
< -l
All available test cases:
case 1
[tag 1][tag2]
case2
[tag2]
2 test cases
< -t
All available tags:
1 [tag 1]
2 [tag2]
2 tags
< "case2"
Filters: case2
===============================================================================
All tests passed (1 assertion in 1 test case)
< [tag2]
Filters: [tag2]
===============================================================================
All tests passed (2 assertions in 2 test cases)
SECTION
Catch提供了⼀种section机制,每个section都是独⽴运⾏单元,⽐如下⾯:
TEST_CASE("vectors can be sized and resized","[vector]")
{
std::vector<int>v(5);
REQUIRE(v.size()==5);
REQUIRE(v.capacity()>=5);
SECTION("resizing bigger changes size and capacity")
{
REQUIRE(v.size()==10);
REQUIRE(v.capacity()>=10);
}
SECTION("resizing smaller changes size but not capacity")
{
REQUIRE(v.size()==0);
REQUIRE(v.capacity()>=5);
}
SECTION("reserving bigger changes capacity but not size")
{
REQUIRE(v.size()==5);
REQUIRE(v.capacity()>=10);
}
SECTION("reserving smaller does not change size or capacity")
{
REQUIRE(v.size()==5);
REQUIRE(v.capacity()>=5);
}
}
对于每个section来说,它都从test case的最开始运⾏,这样在进⼊section之前,我们知道v的size为5,capacity⼤于5。根据section的实现,这些section不是并发执⾏的,⽽是每次执⾏⼀个section。
以上代码的输出结果是:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is a Catch v2.13.7 host application.
Run with -? for options
-------------------------------------------------------------------------------
vectors can be sized and resized
-------------------------------------------------------------------------------
test.cpp:20 ...............................................................................
test.cpp:23: FAILED:
CHECK( v.empty() )
with expansion:
false
-------------------------------------------------------------------------------
vectors can be sized and resized
-------------------------------------------------------------------------------
test.cpp:20 ...............................................................................
test.cpp:23: FAILED:
CHECK( v.empty() )
with expansion:
false
-------------------------------------------------------------------------------
vectors can be sized and resized
-------------------------------------------------------------------------------
test.cpp:20 ...............................................................................
test.cpp:23: FAILED:
CHECK( v.empty() )
with expansion:
false
-------------------------------------------------------------------------------
vectors can be sized and resized
-------------------------------------------------------------------------------
test.cpp:20 ...............................................................................
test.cpp:23: FAILED:
CHECK( v.empty() )
with expansion:
false
=============================================================================== test cases: 1 | 0 passed | 1 failed
assertions: 16 | 12 passed | 4 failed
可以看到test case执⾏了4次。
浮点⽐较
catch2浮点数⽐较采⽤类Approx,相关代码如下:
double m_epsilon;
double m_margin;
double m_scale;
double m_value;
Approx::Approx(double value )
:m_epsilon( std::numeric_limits<float>::epsilon()*100),
m_margin(0.0),
m_scale(0.0),
m_value( value )
{}
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
// But without the subtraction to allow for INFINITY in comparison
bool marginComparison(double lhs,double rhs,double margin){
return(lhs + margin >= rhs)&&(rhs + margin >= lhs);
}
bool Approx::equalityComparisonImpl(const double other)const{
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
// Thanks to Richard Harris for his help refining the scaled margin value
return marginComparison(m_value, other, m_margin)
||marginComparison(m_value, other, m_epsilon *(m_scale + std::fabs(std::isinf(m_value)?0: m_value)));
}
举个例⼦:
Approx target =Approx(100).epsilon(0.01).margin(0.01);
CHECK(100== target);
CHECK(100.5== target);
CHECK(108==Approx(100).epsilon(0.1).margin(0.01));
Catch2为⽤户定义了⼀个替代字符_a,这样使⽤时不⽤每次都写Approx,此时只能使⽤默认参数:
namespace literals {
Detail::Approx operator""_a(long double val){
return Detail::Approx(val);
}
Detail::Approx operator""_a(unsigned long long val){
return Detail::Approx(val);
}
}// end namespace literals
举个例⼦:
using namespace Catch::literals;
REQUIRE(2.1==2.1_a );
Matchers
Matchers顾名思义就是某个string或其它类型是否和Matcher所定义的条件匹配。
String matchers
内置的string matchers有Equals,Contains,EndsWith,StartsWith,Matches,前四个是常见的string或substring的⽐较,Matches是ECMAScript类型的正则表达式:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论