Post

02 Test

02 Test

1. Test

1. Test

  • 소프트웨어가 의도한 대로 동작하는지 검증과 확인하는 활동
  • “시스템이 올바르게 작동하는가?”를 확인하는 절차로, 단순히 오류를 찾는 걸 넘어서 품질을 보장하는 과정

2. 주요목적

구분설명기대 효과
결함 조기 발견개발 초기 단계에서 오류를 찾아 수정수정 비용 절감, 안정적 개발 주기 확보
품질 보증 (Quality Assurance)기능이 명세와 요구사항에 맞게 동작하는지 확인신뢰성, 일관성 확보
리팩토링 안전망 제공코드 변경 시 기존 기능이 깨지지 않도록 보장유지보수성 향상, 배포 리스크 감소
문서 대체 역할테스트 코드가 코드의 의도를 설명하는 “살아있는 명세서”로 작동코드 이해도 향상, 협업 효율성 증가
자동화 기반 품질 관리반복 가능한 테스트로 품질을 지속적으로 검증지속적 통합(CI) 및 배포 자동화 지원

3. 검증(Verification)과 확인(Validation)

구분검증(Verification)확인(Validation)
의미“설계대로 잘 만들었는가 (개발자 관점)”“고객이 원하는 걸 만든 건가 (사용자 관점)”
초점명세서/요구사항과의 일치실제 사용자 요구와의 일치
시점개발 과정 중 (단위, 통합 등)개발 완료 후 (인수, 시스템 테스트 등)
예시코드 리뷰, 단위 테스트사용자 테스트, 프로토타입 검증

4. 의의

  • 테스트의 본질적인 가치
  • 개발 효율성 향상 (오류를 미리 잡아 반복 작업 감소)
  • 팀 커뮤니케이션 개선 (명확한 기대 동작 정의)
  • 시스템 안정성 확보 (배포 이후 장애 리스크 최소화)

2. 테스트 구분

1. 단위 테스트 (Unit Test)

  • 정의: 가장 작은 단위(함수, 메서드, 클래스 등)를 독립적으로 검증하는 테스트
  • 목적: 코드의 개별 모듈이 설계대로 동작하는지 확인
  • 특징
    • 빠르고 실행 비용이 낮음
    • 테스트 격리(isolation) 중요
    • Mock, Stub 등 Test Double 자주 사용
  • 실무 활용 예: 비즈니스 로직 검증, 유틸리티 메서드 검증

2. 통합 테스트 (Integration Test)

  • 정의: 여러 모듈이나 시스템이 함께 동작하는지 검증하는 테스트
  • 목적: 모듈 간 인터페이스와 데이터 흐름이 올바른지 확인
  • 특징
    • 단위 테스트보다 실행 비용이 높음
    • 실제 환경과 비슷하게 구성하여 테스트 진행
    • 데이터베이스, API, 외부 시스템 연동 포함 가능
  • 실무 활용 예: 서비스-DB 통합 검증, 외부 API 연동 테스트

3. 회귀 테스트 (Regression Test)

  • 정의: 기존 기능이 변경·추가 후에도 정상 동작하는지 검증하는 테스트
  • 목적: 코드 변경에 따른 부작용(Regression)이 발생하지 않았는지 확인
  • 특징
    • 자동화 테스트로 구현되는 경우 많음
    • CI/CD 파이프라인에 통합 가능
  • 실무 활용 예: 새로운 기능 추가 후 전체 기능 점검, 버그 수정 후 전체 영향 검증

4. 범위/목적/시점

테스트 종류범위목적실행 시점
단위 테스트개별 모듈로직 검증개발 초기 단계
통합 테스트모듈 간 결합인터페이스 검증개발 중간 단계
회귀 테스트전체 시스템변경 영향 검증변경 후 / 배포 전

3. 테스트기법

1. 화이트박스 테스트 (White-box Testing)

  • 정의: 테스트 설계자가 시스템 내부 구조, 로직, 코드 구현 방식을 알고 진행하는 테스트
  • 목적: 코드의 내부 동작과 흐름이 설계대로 작동하는지 검증
  • 특징
    • 코드 커버리지를 중요하게 다룸 (문장, 분기, 조건 커버리지 등)
    • 단위 테스트에 주로 사용
    • 내부 로직 변경이 테스트 설계에 영향 줌
  • 실무 활용 예: 알고리즘 로직 검증, 조건 분기 처리 테스트

2. 블랙박스 테스트 (Black-box Testing)

  • 정의: 시스템 내부 구조를 고려하지 않고, 입력과 출력만을 기반으로 테스트를 설계하는 기법
  • 목적: 요구사항·명세서에 맞게 기능이 동작하는지 검증
  • 특징
    • 내부 구조를 몰라도 설계 가능
    • 주로 통합 테스트, 시스템 테스트, 인수 테스트에서 사용
    • 테스트 케이스는 기능 명세 기반
  • 실무 활용 예: API 기능 검증, 사용자 인터페이스(UI) 테스트

3. 그레이박스 테스트 (Gray-box Testing)

  • 정의: 화이트박스와 블랙박스 테스트의 중간 형태
  • 목적: 일부 내부 구조를 알고 있으면서, 기능 중심으로 테스트 설계
  • 특징
    • 내부 구조를 일부 이해하지만 전체는 모름
    • 보안 테스트, 통합 테스트에서 활용
  • 실무 활용 예: 데이터 흐름 테스트, 보안 취약점 점검

4. 테스트 비교표

기법개발 주체내부 구조 인지 여부주요 사용 단계장점단점
화이트박스개발자내부 구조 O단위 테스트코드 커버리지 높음, 논리 오류 발견 용이설계 변경 시 테스트 수정 필요
블랙박스QA팀, 테스터, 사용자내부 구조 X통합/시스템/인수 테스트요구사항 기반, 사용자 관점 테스트 가능내부 결함 발견 어려움
그레이박스개발자 + QA팀부분 인지보안·통합 테스트장점 혼합, 효율적설계 정보 필요

4. 개발 방식

1. 개발 방식 비교

구분TDD (Test Driven Development)BDD (Behavior Driven Development)
구분전통적인 방식TDD의 확장형
초점코드 단위 로직 검증사용자 관점 행위 검증
테스트 형태단위 테스트기능/행위 테스트
참여 주체개발자개발자 + QA + 비즈니스 담당자
설계 단위메서드, 클래스시나리오, 사용자 스토리

2. 테스트 주도 개발 (TDD, Test Driven Development)

1. 테스트주도개발

  • 코드를 작성하기 전에 테스트를 먼저 작성하는 개발 방식
  • 기능 구현 전에 “어떤 동작을 해야 하는지”를 테스트 코드로 정의하고, 그 테스트를 통과시키는 코드를 작성하는 흐름

2. TDD의 핵심 원칙

  • 테스트 코드 먼저 작성: 요구사항을 테스트 케이스로 구현
  • 작게, 자주 개발: 기능 단위를 작게 나눠 테스트와 구현 반복
  • 리팩토링 포함: 코드 품질 향상 및 유지보수성을 위해 지속적으로 리팩토링

3. Red–Green–Refactor 사이클

  • Red 단계 (실패하는 테스트 작성)
    • 새로운 기능을 구현하기 전에 테스트 코드를 먼저 작성
    • 아직 기능이 구현되지 않았으므로 테스트는 실패 상태가 됨 → Red
    • 목적: 어떤 기능이 필요하고, 그 기능이 어떻게 동작해야 하는지 명확히 정의
    • 예시
      1
      2
      3
      4
      
      @Test
       void testAdd() {
       assertEquals(4, calculator.add(2, 2));
       }
      

      → 이 테스트는 아직 calculator.add() 기능이 없거나 잘못 구현됐으므로 실패함

  • Green 단계 (테스트를 통과하는 최소 코드 구현)
    • 실패한 테스트를 통과시키기 위해 최소한의 코드를 작성
    • 목적: 빠르게 기능을 구현하고 테스트를 통과시키는 것
    • 핵심: 구현은 최소한으로, 복잡한 최적화는 다음 단계에서 진행
    • 예시
      1
      2
      3
      
      int add(int a, int b) {
       return a + b;
      }    
      

      → 테스트가 성공 → Green 상태

  • Refactor 단계 (코드 리팩토링)
    • 기능이 정상 동작하는 상태에서 코드 품질을 개선
    • 목적: 중복 제거, 가독성 향상, 유지보수성 확보
    • 중요한 점: 테스트를 통과시키는 상태를 유지하면서 리팩토링
    • 예시: 변수명 개선, 메서드 구조 개선, 불필요한 코드 제거

3. 행위 중심 개발 (BDD, Behavior Driven Development)

1. 행위 중심 개발

  • 행위(Behavior) 중심으로 테스트를 설계하고 개발하는 방식
  • “시스템이 어떻게 동작해야 하는가”를 사용자 관점에서 정의하고 검증하는 방법론

2. 핵심원칙

  • 행위 중심: 시스템이 어떻게 동작해야 하는지 사용자 관점에서 정의
  • 비즈니스 언어 사용: 이해관계자가 쉽게 이해할 수 있는 자연어로 테스트 설계
  • Given–When–Then 구조: 테스트 시나리오를 일관성 있게 작성
  • 협업 중심: 개발자·QA·비즈니스 담당자가 함께 시나리오 설계
  • 문서화: 테스트 시나리오 자체가 살아있는 문서 역할

3. Given-when-then 사이클

  • Given: 주어진 상황 (상태, 조건)
  • When: 수행할 행동
  • Then: 기대되는 결과
  • 예시
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
     @Test
     public void testLogin() {
       // Given: 초기 상태 설정
       LoginPage loginPage = new LoginPage();
       loginPage.open();
    
       // When: 행동 실행
       loginPage.enterUsername("testUser");
       loginPage.enterPassword("securePassword");
       loginPage.clickLogin();
    
       // Then: 기대 결과 검증
       HomePage homePage = new HomePage();
       assertTrue(homePage.isDisplayed());
     }
    

5. 테스트 더블 (Test Double)

1. 테스트 더블

  • 테스트할 때 실제 객체 대신 사용하는 가짜 객체
  • 테스트를 독립적으로 만들고, 외부 의존성을 제거하는 것

2. 테스트 더블 종류

1. 종류 구분

종류설명사용 목적
Stub미리 정의된 데이터를 반환하는 간단한 객체특정 입력에 대해 정해진 값을 반환하도록 설정
Mock메서드 호출 여부, 횟수, 인자를 검증할 수 있는 객체테스트 중 호출 여부와 동작 검증
Fake실제 동작하는 간단한 구현 객체실제 로직의 단순화 버전, 성능 향상 또는 외부 시스템 대체
Spy실제 객체의 동작을 관찰할 수 있는 객체메서드 호출 기록, 인자 값 추적 등

2. Stub

1
2
3
4
5
  class UserServiceStub implements UserRepository {
    public User findUserById(String id) {
      return new User("testUser", "test@example.com"); // 항상 같은 값 반환
    }
  }

3. Mock (JUnit + Mockito 예시)

1
2
3
4
  UserRepository mockRepo = Mockito.mock(UserRepository.class);
  Mockito.when(mockRepo.findUserById("123")).thenReturn(new User("mockUser", "mock@example.com"));
  
  verify(mockRepo).findUserById("123"); // 호출 여부 검증

4. Fake

1
2
3
4
5
6
7
8
9
10
11
  class FakeUserRepository implements UserRepository {
    private Map<String, User> data = new HashMap<>();
    
        public User findUserById(String id) {
            return data.get(id);
        }
    
        public void saveUser(User user) {
            data.put(user.getId(), user);
        }
  }

5. SPY (JUnit + Mockito 예시)

1
2
3
4
5
  List<String> list = new ArrayList<>();
  List<String> spyList = Mockito.spy(list);
  
  spyList.add("hello");
  Mockito.verify(spyList).add("hello"); // 호출 여부 검증

6. 테스트 커버리지

1. 테스트 커버리지

  • 코드 중 얼마나 많은 부분이 테스트됐는지 비율을 의미
  • 테스트가 코드 전체에서 어느 정도를 확인했는지를 수치로 나타내는 것

2. 테스트커버리지 종류

종류의미
문장 커버리지 (Statement Coverage)코드의 각 문장이 최소 한 번 실행됐는지 확인
분기 커버리지 (Branch Coverage)조건문(if, switch 등)의 모든 분기가 실행됐는지 확인
조건 커버리지 (Condition Coverage)조건문 내부의 각 조건(참/거짓)이 모두 실행됐는지 확인

3. 스프링에서의 커버리지

도구특징
JaCoCo가장 널리 쓰이는 자바 코드 커버리지 도구
Maven/Gradle 연동 쉬움
문장/분기/조건 커버리지 제공
CoberturaJaCoCo 이전의 오래된 도구
XML 보고서 제공
다소 업데이트 빈도 낮음
SonarQube코드 품질 분석 플랫폼
커버리지 측정 + 코드 품질 지표 제공
CI/CD 통합 가능
IntelliJ IDEA / EclipseIDE 내장 기능으로 커버리지 측정
빠른 시각화
설정 간단하지만 CI 환경에는 부적합

7. 테스트 자동화와 CI

1. 지속적 통합 (Continuous Integration, CI)

  • 정의: 개발자들이 작성한 코드를 자주(보통 하루 여러 번) 중앙 저장소에 통합하고, 자동으로 빌드와 테스트를 실행하는 개발 방식.
  • 목적: 통합 과정에서 발생하는 문제를 빠르게 발견하고 수정하기 위함.
  • 특징
    • 코드 통합 시마다 자동 빌드 + 테스트 실행
    • 코드 품질 유지
    • 버그 조기 발견
    • 협업 효율 향상
  • 예시 도구: Jenkins, GitHub Actions, GitLab CI, CircleCI

2. CI 동작과정

  • 테스트 코드 작성
    • 개발자가 프로젝트에 테스트 코드를 작성하고, 버전 관리 시스템(Git 등)에 등록
    • 예: JUnit, Mockito, Spring Test 등으로 테스트 코드 구현
  • 코드 커밋 & 푸시
    • 개발자가 코드를 변경하고 저장소(GitHub, GitLab 등)에 푸시(push)
  • CI 서버 자동 실행
    • Jenkins, GitHub Actions, GitLab CI 같은 CI 도구가 커밋 푸시를 감지
    • 자동으로 빌드(Build) + 테스트(Test) 실행
  • 결과 보고
    • 테스트 성공 여부를 알림
    • 실패 시 개발자에게 바로 피드백

3. 지속적 배포 (Continuous Delivery / Continuous Deployment, CD)

  • 정의: CI 과정 이후, 테스트를 통과한 코드를 자동으로 배포하거나 배포 준비 상태로 만드는 개발 방식.
    • Continuous Delivery: 자동으로 배포 준비까지 진행하지만, 실제 배포는 수동 승인 필요
    • Continuous Deployment: 모든 변경 사항을 자동으로 배포까지 진행
  • 목적: 배포 과정을 자동화해 빠르고 안정적으로 소프트웨어를 사용자에게 전달하기 위함.
  • 특징
    • 테스트를 통과한 코드 자동 배포 또는 배포 준비
    • 배포 속도 향상
    • 배포 오류 최소화
    • 운영 환경에서 빠른 피드백 가능
  • 예시 도구: Jenkins, GitHub Actions, GitLab CI/CD, CircleCI, Spinnaker

4. 테스트 자동화 파이프라인

  • 정의: CI 과정에서 테스트를 자동으로 실행하는 절차를 파이프라인(Workflow) 형태로 구성한 것.
  • 목적: 사람이 개입하지 않아도 자동으로 테스트를 실행하고, 문제 발생 시 알림 제공.
  • 흐름 예시
    1
    2
    
    [코드 커밋] → [CI: 빌드 + 테스트 자동화] → [CD: 배포 자동화]  
             ↑------------------- 파이프라인 -------------------↑
    
  • 특징
  • 테스트 자동 실행
  • 실패 시 즉시 피드백
  • 배포 전 품질 보증
  • 테스트 커버리지, 코드 품질 보고서 자동 생성
  • 예시 도구: Jenkins, Travis CI, GitHub Actions, CircleCI
This post is licensed under CC BY 4.0 by the author.