gcc C기준
cyber-dojo에서 진행
<hiker.c>
#include "hiker.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define ERROR_VALUE -1
// 양의 정수 여부 확인
bool isPositive(int num) {
return num >= 0;
}
// 더하기 함수
int add(int a, int b) {
if (isPositive(a) && isPositive(b)) {
return a + b;
} else {
// 양의 정수가 아닐 경우 에러 값을 반환
return -1;
}
}
// 빼기 함수
int subtract(int a, int b) {
if (isPositive(a) && isPositive(b)) {
return a - b;
} else {
// 양의 정수가 아닐 경우 에러 값을 반환
return -1;
}
}
// 나누기 함수
int divide(int a, int b) {
if (b == 0 || !isPositive(a) || !isPositive(b)) {
// divide by zero 또는 양의 정수가 아닌 경우 에러 처리
return -1;
} else {
return a / b;
}
}
// 곱하기 함수
int multiply(int a, int b) {
if (isPositive(a) && isPositive(b)) {
return a * b;
} else {
// 양의 정수가 아닐 경우 에러 값을 반환
return -1;
}
}
// 짝수인지 확인하는 함수
bool isEven(int number) {
return number % 2 == 0;
}
// 이름을 받아 인사하는 함수
const char* greet(const char* name) {
static char buffer[100];
// 에러 처리: NULL 포인터 또는 빈 문자열
if (name == NULL || strlen(name) == 0) {
return "[ERROR] name is null or empty";
}
sprintf(buffer, "Hello, %s!", name);
return buffer;
}
<hiker.h>
#ifndef HIKER_INCLUDED
#define HIKER_INCLUDED
#include <stdbool.h>
#include <stddef.h>
int answer(void);
bool isPositive(int);
int add(int, int);
int subtract(int, int);
int divide(int, int);
int multiply(int, int);
bool isEven(int);
// void greet(const char*, char*, size_t);
const char* greet(const char*);
#endif
<hiker.test.c>
#include "hiker.h"
#include <assert.h>
#include <stdio.h>
/*
add 정상 확인
a+b
return -1
*/
static void test_add(void){
assert(add(5,4)==9); // a+b TC
assert(add(-1,5)==-1); // exception TC
}
int main(void)
{
test_add(); // Test code 실행
puts("All tests passed");
}

Unit Test 결과
line 커버리지가 100%가 되지 않음을 볼 수 있다.
line 커버리지를 100%로 하도록 추가 테스트하면
#include "hiker.h"
#include <assert.h>
#include <stdio.h>
/*
add 정상 확인
a+b
return -1
*/
static void test_add(void){
assert(add(5,4)==9); // a+b TC
assert(add(-1,5)==-1); // exception TC
}
static void test_subtract(void){
assert(subtract(5,4)==1); // a-b TC
assert(subtract(-1,5)==-1); // exception TC
}
int main(void)
{
test_add(); // Test code 실행
test_subtract();
puts("All tests passed");
}

점진적으로 추가해보면


#include <string.h>
#include "hiker.h"
#include <assert.h>
#include <stdio.h>
/*
add 정상 확인
a+b
return -1
*/
static void test_add(void){
assert(add(5,4)==9); // a+b TC
assert(add(-1,5)==-1); // exception TC
}
static void test_subtract(void){
assert(subtract(5,4)==1); // a-b TC
assert(subtract(-1,5)==-1); // exception TC
assert(subtract(0,0) == 0); // boundary test
}
static void test_divide(void){
assert(divide(5,5)==1); // a/b TC
assert(divide(5,0)==-1); // a/b divided zero exception
assert(divide(5,-1)==-1); // exception TC
}
static void test_multiply(void){
assert(multiply(5,4)==20); // a*b TC
assert(multiply(5,-1)==-1); // exception TC
}
//isEvenTest_even/odd로 Test 목적별로 나눠 쓰는 것을 추천
static void is_Even_test(void){
assert(isEven(2)== true); // a%b even
assert(isEven(1)== false); // odd
assert(isEven(0) == true);
}
//assert는 bool, 실수간 같다 비교밖에 못해줌
//문자열 같은 경우는 추가 코드를 작성해야함. assert만으로는 불가능
static void test_greet(void){
// error 불가능. 비교 불가
// assert(greet("Alice") == "Hello, Alice");
const char* result = greet("Alice");
assert(strcmp(result, "Hello, Alice!") == 0);
}
int main(void)
{
test_add(); // Test code 실행
test_subtract();
test_divide();
test_multiply();
is_Even_test();
test_greet();
puts("All tests passed");
}

assert의 한계로 GoogleTest는 ASSERT랑 EXPECT나눠 제공
Google에 google test를 치고 GoogleTest User's Guide에서
사용가능한 여러 내용 참조가 가능함.
gcc C GoogleTest
test 코드만 이렇게 바꿔주면
#include <gtest/gtest.h>
extern "C"{
#include "hiker.h"
}
using namespace ::testing;
TEST(addTest, validInputs){
ASSERT_EQ(add(3,4),7);
}
TEST(addTest, invalidInputs){
ASSERT_EQ(add(3,-1),-1);
}

strcmp를 쓰지않고도 편히 할 수 있음.
#include <gtest/gtest.h>
extern "C"{
#include "hiker.h"
}
using namespace ::testing;
TEST(addTest, validInputs){
ASSERT_EQ(add(3,4),7);
}
TEST(addTest, invalidInputs){
ASSERT_EQ(add(3,-1),-1);
}
TEST(GreetTest, ValidName){
EXPECT_STREQ(greet("Alice"), "Hello, Alice!");
EXPECT_STREQ(greet("Bob"), "Hello, Bob!");
}

3,4 == 7이 아니라
3,4 == 5로 해버리면,

Failure도 뜨고, 왜 틀렸는지까지 정보를 제공해준다.
gMock을 쓰면 통합 단계인 Interface test해서 call 관계, Stub, Driver를 진행 할 수 있음.
단 gMock을 남용하면 테스트 코드 유지보수성이 떨어지기에 잘 쓰지 않는게 좋음