Ubuntu, VSCode에서 Catch2 사용법
2020년 5월 25일
C++에는 많은 단위테스트 도구들이 있습니다. 그중 Catch2가 선호도가 높습니다. ROS 패키지들도 Catch2를 사용하기도 합니다. 여기서 글에서 개발 환경은 Ubuntu, git, Visual Studio Code, cmake 입니다.
먼저 Catch2
소스코드를 다운로드 합니다.
cd ~
git clone https://github.com/catchorg/Catch2
오피셜 문서는 카피를 하라고 하는데 확인해 보니 CMakeLists.txt
파일이 있었고, cmake를 해보니 빌드 및 설치가 되었습니다.
cd Catch2
mkdir build
cd build
cmake ..
make
빌드에 성공하면 설치를 합니다.
sudo make install
특별히 설치 경로를 지정하지 않으면 기본 경로인 /us/local/include/catch2
에 설치됩니다. 설치에 성공하였으면 예제 코드 010_test_case.cpp
를 작성해 봅니다. 이 코드는 오피셜 예제로 제공되며 파일명을 c 규칙으로 변경 하였습니다.
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
int factorial( int number )
{
// return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
return number <= 1 ? 1 : Factorial( number - 1 ) * number; // pass
}
TEST_CASE("Factorial of 0 is 1 (fail)", "[single-file]")
{
REQUIRE( factorial(0) == 1 );
}
TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" )
{
REQUIRE( factorial(1) == 1 );
REQUIRE( factorial(2) == 2 );
REQUIRE( factorial(3) == 6 );
REQUIRE( factorial(10) == 3628800 );
}
#define CATCH_CONFIG_MAIN
은 main
함수를 코드에 삽입하게 합니다.
TEST_CASE(,)
는 테스트 케이스 함수를 작성합니다.
REQUIRE()
는 테스트를 합니다.
이 코드는
g++ -std=c++11 -Wall -o 010_test_case 010_test_case.cpp && 010_test_case --success
하면 빌드합니다. Catch2는 헤더파일로만 구성되기 때문에 별도의 라이브러리 파일을 링크를 요구하지 않습니다. 기본 설치 폴더 /usr/local/include/catch2/
에 설치하였을 경우 -I
옵션은 필요하지 않습니다. 실행은
./010_test_case --reporter compact --success
로 할 수 있습니다.
CMake로 빌드하는 경우 CMakeLists.txt
는 아래와 같습니다.
set(name 010_test_case)
project(${name})
cmake_minimum_required(VERSION 3.5)
set(SOURCE 010_test_case.cpp)
add_compile_options(-g -Wall -std=c++11)
add_executable(${name} ${SOURCE})
빌드하려면
mkdir build
cd build
make
그리고 실행합니다.
./010_test_case --reporter compact --success
결과는
010_test_case.cpp:14: failed: factorial(0) == 1 for: 0 == 1
010_test_case.cpp:18: passed: factorial(1) == 1 for: 1 == 1
010_test_case.cpp:19: passed: factorial(2) == 2 for: 2 == 2
010_test_case.cpp:20: passed: factorial(3) == 6 for: 6 == 6
010_test_case.cpp:21: passed: factorial(10) == 3628800 for: 3628800 (0x375f00) == 3628800 (0x375f00)
Failed 1 test case, failed 1 assertion.
실패 예제를 확인하였으면 factorial
함수를 변경하여 테스트가 성공하도록 시도하고 확인해 보세요.
TEST_CASE
안에는 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" )
{
v.resize( 10 );
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "resizing smaller changes size but not capacity" )
{
v.resize( 0 );
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
}
SECTION( "reserving bigger changes capacity but not size" )
{
v.reserve( 10 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "reserving smaller does not change size or capacity" )
{
v.reserve( 0 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
}
}
또한 SECTION
안에 SECTION
을 둘 수도 있습니다.
TEST_CASE(...)
{
...
SECTION( "reserving bigger changes capacity but not size" ) {
v.reserve( 10 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
SECTION( "reserving smaller again does not change capacity" ) {
v.reserve( 7 );
REQUIRE( v.capacity() >= 10 );
}
}
...
}
BDD 스타일로 테스트를 작성 할 수도 있습니다.
SCENARIO( "vectors can be sized and resized", "[vector]" )
{
GIVEN( "A vector with some items" )
{
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
WHEN( "the size is increased" )
{
v.resize( 10 );
THEN( "the size and capacity change" )
{
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
}
WHEN( "the size is reduced" )
{
v.resize( 0 );
THEN( "the size changes but not capacity" )
{
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
}
}
WHEN( "more capacity is reserved" )
{
v.reserve( 10 );
THEN( "the capacity changes but not the size" )
{
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
}
}
WHEN( "less capacity is reserved" )
{
v.reserve( 0 );
THEN( "neither size nor capacity are changed" )
{
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
}
}
}
}