1. 테스트 방식의 분류

화이트박스 테스트 vs. 블랙박스 테스트

  • 화이트박스 테스트: 코드 내부 구조를 이해하고 테스트를 설계합니다.
    • 소프트웨어의 내부 구조, 코드, 알고리즘, 로직을 이해한 상태에서 테스트를 수행합니다.
    • 내부를 들여다보고 테스트한다고 해서 화이트박스라고 불립니다.
    • : 유닛 테스트, 코드 커버리지 테스트.
  • 블랙박스 테스트: 내부 구현을 모른 채, 기능과 요구사항 중심으로 테스트합니다.
    • 소프트웨어의 내부 구조나 동작 방식은 고려하지 않고, 입력값과 출력값만을 테스트합니다.
    • 상자를 열어보지 않고 테스트한다고 해서 블랙박스라고 불립니다.
    • : 시스템 테스트, 기능 테스트, UI 테스트.
  자동화 테스트 수동 테스트
목적 코드를 기반으로 오류를 찾아내고, 모든 코드 경로와 로직이 올바르게 작동하는지 논리적 오류를 검출합니다. 사용자의 요구사항에 따라 소프트웨어가 올바르게 작동하는지 확인합니다. 기능, UI, 요구사항 충족 여부 등 외부 동작에 초점을 맞춥니다.
특징 코드 커버리지 확인합니다. 코드의 모든 실행 경로를 테스트합니다. 입력값과 출력값의 조합을 테스트합니다. 오류 처리, 유효성 검사, 사용자 시나리오 확인합니다.
장점 코드의 논리적 결함을 발견합니다. 성능 최적화 및 코드 품질 개선 가능합니다. 사용자 관점에서 문제를 발견하기 쉽습니다. 내부 구현과 무관하게 기능적 요구사항을 검증합니다.
단점 내부 구현에 의존하여 사용자 관점의 오류를 발견하기 어려웁니다. 복잡한 시스템의 경우 모든 경로를 테스트하기 어렵고 비용이 높습니다. 코드 내부의 논리적 오류나 성능 문제를 발견하기 어렸습니다. 테스트 범위를 정의하는 것이 어려울 수 있습니다.

2. 테스트 유형

단위 테스트 (Unit Test)

  • 단위 테스트는 소프트웨어의 가장 작은 독립적 단위(보통 함수, 메서드, 클래스 등)를 테스트하는 과정입니다.
  • 각 단위를 개별적으로 실행하여, 입력에 대한 출력이 예상대로 나오는지 확인합니다.
  • 독립적이며 외부 의존성을 모의(Mock) 객체로 테스트 합니다.
  • 주요 목적
    • 결함 조기 발견: 코드를 작성하는 단계에서 오류를 발견하고 수정할 수 있습니다.
    • 코드 안정성 보장: 변경 사항이 기존 기능에 부정적인 영향을 주지 않도록 방지합니다.
    • 리팩토링 지원: 테스트가 작성되어 있다면 리팩토링 과정에서 기능이 깨지지 않는지 확인할 수 있습니다.
    • 문서화 역할: 테스트 코드는 코드의 예상 동작을 보여주는 실질적인 예제 역할을 합니다.
  • 장점: 빠른 피드백 제공, 코드 품질 향상.
    • 코드 단위의 정확성 보장: 각 모듈(함수/메서드)이 올바르게 동작하는지 검증합니다.
    • 빠른 피드백 제공: 단위 테스트가 실패하면 바로 문제를 파악하고 수정 가능합니다.
    • 회귀 방지: 기존 코드가 변경될 때 발생할 수 있는 오류를 방지합니다.
  • 테스트 작성 주의사항
    • 독립성 보장: 테스트는 독립적으로 실행되어야 하며, 다른 테스트에 의존하지 않아야 합니다.
    • 단일 동작 테스트: 각 테스트는 하나의 동작이나 결과만 검증해야 합니다.
    • 명확한 이름 사용: 테스트 이름은 테스트의 의도를 명확히 나타내야 합니다.
    • 경계 조건 테스트: 정상 케이스뿐만 아니라, 경계 값에 대한 테스트도 포함합니다.
    • Mock 사용: 외부 의존성을 격리하기 위해 Mock 객체를 사용합니다.
  • 도구 예: JUnit(Java), Pytest(Python).

Java 예제 (JUnit):

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class CalculatorTest {

    @Test
    public void testAddition() {
        // Arrange
        Calculator calculator = new Calculator();
        int a = 5;
        int b = 3;

        // Act
        int result = calculator.add(a, b);

        // Assert
        assertEquals(8, result, "Addition should return the correct sum");
    }
}

단위테스트 한계

  • 단위 테스트는 개별 모듈만 확인하므로, 시스템 수준에서의 문제는 발견할 수 없습니다.
  • 외부 시스템(DB, API)과의 통합 문제를 검출하기 어렵습니다.
  • 잘못된 테스트 코드는 오히려 혼란을 초래할 수 있습니다.

b) 통합 테스트 (Integration Test)

  • 통합 테스트는 여러 개의 모듈이나 컴포넌트가 상호작용할 때 올바르게 동작하는지 확인하는 테스트 단계입니다
  • 단위 테스트가 통과한 이후에 수행하며, 모듈들이 결합될 때 발생할 수 있는 문제를 확인하는 데 초점을 맞춥니다.
  • 외부 API, 데이터베이스, 파일 시스템 등과의 상호작용 테스트 포함합니다.
  • 장점: 모듈 간 호환성 확인, 예기치 못한 오류 발견.
    • 상호작용 중심: 모듈 간의 데이터 교환, 호출, 상태 변화 등을 테스트합니다.
    • 통합 결함 발견 : 서로 다른 모듈이나 서브시스템 간의 데이터 흐름과 통신이 올바르게 이루어지는지 확인합니다.
    • 시스템 안정성 보장: 다양한 모듈이 실제 환경과 비슷한 상황에서 함께 작동할 때의 안정성을 검증합니다.
    • 종속성 관리: 데이터베이스, 외부 API, 파일 시스템 등 외부 의존성과의 상호작용을 테스트합니다.
  • 테스트 작성 주의사항
    • 실제 환경 모방: 테스트 환경을 실제 환경과 최대한 비슷하게 구성합니다.
    • 독립적 실행 가능: 각 테스트는 독립적으로 실행 가능하도록 설계해야 합니다.
    • Mock과 실제 의존성 사용의 균형:
      Mock을 사용해 불필요한 복잡성을 줄이는 동시에, 실제 의존성을 테스트할 부분도 포함해야 합니다.
    • 에러 로그 확인: 통합 테스트 실패 시 명확한 로그를 남겨 디버깅을 쉽게 합니다.
  • 도구 예: Spring Boot 통합 테스트(Java).

Java 예제:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserIntegrationTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void testGetUserDetails() {
        // Act
        ResponseEntity<User> response = restTemplate.getForEntity("/api/users/1", User.class);

        // Assert
        assertThat(response.getStatusCode().is2xxSuccessful()).isTrue();
        assertThat(response.getBody().getName()).isEqualTo("John Doe");
    }
}

 

통합테스트 한계

  • 시간 소요: 테스트 범위가 크기 때문에 실행 시간이 오래 걸릴 수 있습니다.
  • 복잡성 증가: 여러 모듈과 시스템 간의 상호작용을 테스트하기 때문에 복잡도가 높아질 수 있습니다.
  • 결함 원인 식별 어려움: 오류가 발생하면, 단위 테스트에 비해 문제의 원인을 찾기 어려울 수 있습니다.

성능 테스트 (Performance Test)

  • 성능 테스트는 소프트웨어 시스템이 특정 조건에서 얼마나 효율적으로 동작하는지 확인하기 위해 수행되는 테스트입니다.
  • 이는 시스템의 속도, 안정성, 확장성, 자원 사용량 등을 평가하는 것을 목표로 합니다.
  • 주요 목적:
    • 속도 (Speed): 시스템이 주어진 부하에서 응답 시간을 충족하는지 확인합니다.
    • 확장성 (Scalability): 사용자 수와 데이터 부하가 증가할 때 시스템이 이를 처리할 수 있는지를 평가합니다.
    • 안정성 (Stability): 긴 시간 동안 부하가 가해질 때도 시스템이 안정적으로 작동하는지 검증합니다.
    • 자원 사용량 (Resource Usage): CPU, 메모리, 네트워크 대역폭, 디스크 I/O 등의 사용량이 적절한지 평가합니다.
  • 유형:
    • 부하 테스트 (Load Testing): 정상적인 조건에서 시스템이 어떻게 동작하는지를 평가합니다.
      • 목표: 정해진 사용자 수나 데이터 부하에서 성능을 확인.
    • 스트레스 테스트 (Stress Testing): 시스템이 최대 한계를 초과하는 부하에서 어떻게 동작하는지를 확인합니다.
      • 목표: 시스템의 안정성과 복구 능력을 평가.
    • 내구성 테스트 (Endurance Testing): 장시간 동안 부하가 지속될 때 시스템이 안정적으로 동작하는지를 평가합니다.
      • 목표: 메모리 누수와 같은 장기적인 문제 발견.
    • 스파이크 테스트 (Spike Testing): 짧은 시간 동안 갑작스러운 부하 증가가 발생했을 때 시스템이 어떻게 반응하는지 확인합니다.
      • 목표: 급격한 변화에서의 복구 능력을 검증.
    • 용량 테스트 (Capacity Testing): 시스템이 처리할 수 있는 최대 사용자 수 또는 데이터 양을 파악합니다.
      • 목표: 최적의 하드웨어 및 네트워크 구성 결정.
  • 도구 예: JMeter, LoadRunner, Gatling.

3. 테스트 주기와 전략

테스트 주기

  1. 계획(Planning): 테스트 범위와 목표 설정합니다.
  2. 설계(Design): 테스트 케이스 작성합니다.
  3. 구현(Implementation): 테스트 스크립트 작성합니다.
  4. 실행(Execution): 테스트 실행 및 결과 확인합니다.
  5. 평가(Evaluation): 테스트 결과 분석 및 보고합니다.

'IT > CS' 카테고리의 다른 글

비동기 프로그래밍의 장단점  (0) 2025.04.16
쿠키와 세션 정리  (0) 2025.01.03
HTTPS 암호화 방식  (0) 2024.12.30

+ Recent posts