TEST(TestCaseName, TestName) { EXPECT_EQ(1, 1); EXPECT_TRUE(true); }
기본적으로 각 테스트 케이스는 위와 같은 모양이 된다
TEST 매크로는
// Helper macro for defining tests. #define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ public:\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ private:\ virtual void TestBody();\ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ };\ \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ ::test_info_ =\ ::testing::internal::MakeAndRegisterTestInfo(\ #test_case_name, #test_name, NULL, NULL, \ ::testing::internal::CodeLocation(__FILE__, __LINE__), \ (parent_id), \ parent_class::SetUpTestCase, \ parent_class::TearDownTestCase, \ new ::testing::internal::TestFactoryImpl<\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
대충 이런 정의로 되어 있다
TEST 의 첫번째 인자는 임의의 string 을 입력한다는 생각으로 현재 구현할 test case 의 group 이름 처럼 생각하고 부여 하면 된다
두번째 인자는 해당 test case 의 세부 test 단위 의 이름을 마찬가지로 string 이라고 고려하고 넣어준다
실제 body 에서는 꼭 있어야 하는 내용으로
ASSERT_* 나 EXPECT_* 로 시작하는 매크로를 사용해 두어야 한다
ASSERT_* 의 경우 실패 할경우 나머지 코드도 모두 실행하지 않고 실패로 종료되며
EXPECT_* 의 경우 실패 하더라도 아래의 코드들도 모두 시도해 성공 여부를 기록한다
다시 말하면 ASSERT_* 는 실패하지 않아야 하며 해당 테스트 결과가 다른 테스트에 도 영향을 줄경우
EXPECT_* 의 경우 실패 당연히 하지 말아야 하지만 실패 하더라도 다른 테스트에 직접적인 영향을 주진 않을 경우 사용한다
기본적으로
ASSERT_TRUE(condition);
ASSERT_FALSE(condition);
EXPECT_TRUE(condition);
EXPECT_FALSE(condition);
이 각 condition 이 true/false 이어야 한다는 전제로 테스트 케이스를 작성할 수 있는 구문이며
실제 아래와 같은 매크로들을 사용할 수 있다
(val1, val2) | expected vs actual | |
ASSERT_EQ EXPECT_EQ | == | (equal) |
ASSERT_NE EXPECT_NE | != | (not equal) |
ASSERT_LT EXPECT_LT | < | (less then) |
ASSERT_LE EXPECT_LT | <= | (less equal) |
ASSERT_GT EXPECT_GT | > | (greater) |
ASSERT_GE EXPECT_GE | >= | (greater equal) |
ASSERT_STREQ EXPECT_STREQ | == | (string equal) |
ASSERT_STRNE EXPECT_STRNE | != | (string not equal) |
ASSERT_STRCASEEQ EXPECT_STRCASEEQ | == | (string ignore case equal) |
ASSERT_STRCASENE EXPECT_STRCASENE | != | (string ignore case not equal) |
특이점은 STR 로 되어 있는 매크로의 경우 string class 가 아닌 c sytle char 버퍼를 인자로 넣을 때 사용 해야하며 string class 의 경우 굳이 해당 매크로보다 직접 비교연산자를 통해 비교가능하니 그방법을 사용하자
class / 리소스를 공유하며 initialize/destory 하며 사용하기 위해서는 fixture 를 사용한다
class fixtureTest : public ::testing::Test { protected: virtual void SetUp() { vecInts.reserve(3); vecInts.emplace_back(new int(3)); vecInts.emplace_back(new int(2)); vecInts.emplace_back(new int(1)); } virtual void TearDown() { for (auto& el : vecInts) { delete el; } vecInts.clear(); } public: std::vector<int*> vecInts; }; TEST_F(fixtureTest, TestName) { EXPECT_EQ(vecInts.size(), 3); EXPECT_EQ(*vecInts.at(1), 2); EXPECT_TRUE(true); }
::testing::Test 를 상속받으며
virtual void SetUp(){}
virtual void TearDown(){}
으로 리소스,데이타 클래스를 준비해 둘 수 있으며 아래 TEST_F 의 첫 파라메터와 같은 이름으로 class 정의가 되어 있어야 한다
또한 TEST 매크로가 아닌 TEST_F 매크로를 사용해야 한다
두번째 줄과 마지막에서 세번째 줄을 보면 environment set-up, tear-down
구문을 볼 수 있다 해당 시기에 위의 클래스를 초기화 하거나 정리해주는 구문이 동작 하게 된다
TEST_F 의 구현상태를 따라가보면
# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) #define GTEST_TEST(test_case_name, test_name)\ GTEST_TEST_(test_case_name, test_name, \ ::testing::Test, ::testing::internal::GetTestTypeId())
일반적인 TEST 매크로와 다르게
#define TEST_F(test_fixture, test_name)\ GTEST_TEST_(test_fixture, test_name, test_fixture, \ ::testing::internal::GetTypeId<test_fixture>())
첫 파라메터를 그대로 가져다 사용하는 것을 볼 수 있다
여기까지 아직 해결되지 않은 복잡한 문제로는 class member 함수에 대한 단위 확인이나 private 함수에대한 확인 등이 남아 있으며 테스트 케이스 작성하는데 고려해야할 예상 리스크 에대해 차후 정리 해보도록 하자
댓글 남기기