[TDD및 Coverage, Test Code]

CS·2025년 7월 21일

SW Testing

목록 보기
3/3

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을 남용하면 테스트 코드 유지보수성이 떨어지기에 잘 쓰지 않는게 좋음

profile
학습

0개의 댓글