등가분할로 테스트 케이스를 설계하는 방법

등가분할과 동등 클래스를 이용해 명세 기반 테스트 케이스를 설계하고, 경계값 분석과 조합 테스트로 한계를 보완하는 방법

2026-08-14 · 최초 발행 2025-12-15

입력 도메인을 대표값으로 다루는 테스트 설계

등가분할(동등분할)은 입력값 또는 출력값의 도메인을 서로 독립적인 동등 클래스(Equivalence Class)로 나눈 뒤, 각 클래스에서 대표값을 골라 테스트 케이스를 만드는 명세 기반 테스트 기법이다. 같은 클래스에 속한 값은 같은 동작을 유발한다고 가정하므로, 클래스마다 대표값 1개를 선택해 테스트 범위를 압축할 수 있다.

입력 검증뿐 아니라 출력 도메인에도 적용할 수 있으며, 단위·통합·시스템·인수 테스트 등 모든 테스트 레벨에서 사용할 수 있다. 사용자 입력, API 파라미터, 요금제·등급·상태 전이처럼 규칙이 명확한 영역에서 특히 유용하다.

핵심은 테스트 수를 줄이는 데만 있지 않다. 클래스가 상호 배타적이고 전체 도메인을 완전하게 덮도록 설계하는 과정에서, 명세의 누락이나 모호한 경계를 드러낼 수 있다.

동등 클래스를 만들 때 확인할 조건

우선 입력과 출력 도메인에서 유효(Valid) 클래스와 무효(Invalid) 클래스를 분리한다. 필요하면 클래스를 더 세분화한다. 이때 한 값이 여러 클래스에 동시에 속하지 않는 상호 배타성과, 어느 값도 빠지지 않는 완전성을 확보해야 한다.

대표값은 보통 각 클래스의 전형적인 값, 즉 중간값을 택한다. 경계 부근의 값은 경계값 분석(BVA)으로 별도 설계한다. 특수 포맷, 로케일, 인코딩처럼 형식 제약이 있는 입력은 그 제약을 반영하고, 비즈니스 규칙상 의미가 있는 값을 우선한다.

기본적으로 클래스별 1개 테스트 케이스를 두되, 입력 조건의 조합이 중요한 경우에는 Pairwise나 결정 테이블을 함께 적용한다. 무효 클래스와 경계 인접 클래스는 리스크에 따라 더 비중 있게 다룬다. 요구사항→클래스→테스트 케이스의 추적성을 남겨두면 명세가 바뀌었을 때 클래스를 다시 평가하기 쉽고, 데이터 팩토리나 파라미터라이즈 구조로 대표값을 재사용할 수 있다.

명세에서 테스트 세트까지 이어지는 흐름

명세에서 입력·출력 변수와 제약을 추출한 뒤, 변수별 범위·형식·규칙을 정리한다. 이를 바탕으로 유효·무효 동등 클래스를 만들고, 상호 배타성과 완전성을 검토해 모호한 부분을 해소한다. 각 클래스의 대표값을 정한 다음 경계값은 BVA로 분리하고, 클래스별 1건을 기본으로 필요 시 조합 전략을 적용한다. 마지막으로 커버리지를 검토하고 테스트 데이터를 관리할 수 있도록 자동화한다.

입력/출력 변수 식별유효/무효 동등 클래스 정의상호 배타성/완전성 검사경계값 분석 연계 결정케이스 최소화·조합 전략 적용결과/커버리지 확인명세 수집도메인 분해클래스 검증대표 선정테스트 케이스 도출리뷰 자동화테스트 세트 확정

폼, API, 요금 규칙에 적용하는 방식

폼 입력에서는 나이(age)를 [0–120] 유효, 음수 무효, 121 이상 무효로 나눌 수 있다. 이때 대표값은 30, -1, 200이다. 이메일(email)은 RFC 형식 유효, 형식 위반 무효, 국제도메인/IDN 별도 클래스로 구분하고 user@example.com, user@@x, 사용자@도메인.kr을 대표값으로 둘 수 있다.

비밀번호(password)는 길이 8–64 유효, 미만·초과 무효, 금칙어 포함 무효로 나누며 대표값은 Passw0rd!, short, verylong...!, admin123이다. 비밀번호 정책과 계정 상태(잠김/만료)가 함께 작동한다면 Pairwise를 병용한다.

REST API에서는 pagination.size를 [1–100] 유효, 0/음수/101+ 무효, null로 나누고 20, 0, 200, null을 대표값으로 사용할 수 있다. sort{asc, desc} 유효와 기타 무효로 구분해 asc, invalid를 검증한다. date는 ISO8601 유효와 시간대 누락·형식오류 무효로 구분하며 2025-01-31T10:00:00Z, 2025/01/31을 사용할 수 있다. 출력은 200 정상 목록, 400 유효성 실패, 401 인증 실패, 429 한도 초과를 각각 1케이스씩 커버한다.

배송비 계산은 주문금액 <3만, 3만–5만, ≥5만으로 분할하고 20,000 / 40,000 / 60,000을 대표값으로 둔다. 쿠폰 상태는 {유효, 만료, 이미 사용, 조건 불충족}에서 각 1건을 선택한다. 출력도 {무료, 유료(3,000원), 오류코드별 메시지}처럼 클래스로 나눌 수 있다.

테스트 범위 축소와 명세 검토 효과

조합을 고려하지 않는 영역에서는 테스트 케이스 수를 40–70% 축소할 수 있으며, 실제 범위는 조직과 도메인에 따라 다르다. 클래스 기반 추적성을 두면 요구사항 커버리지를 더 명확히 볼 수 있다.

클래스 경계와 누락을 확인하는 과정은 명세의 모호성을 이르게 발견하게 한다. 테스트 데이터가 표준화되어 재사용성이 높아지고, 신규 기능이나 결함 수정 시 영향 범위를 파악하기도 쉬워진다.

대표값만으로 놓치는 영역

클래스별 케이스가 1개뿐이라는 특성상 클래스 내부의 분포 편향이나 특수 케이스를 놓칠 수 있다. 또 입력 조건 사이의 조합을 직접 고려하지 않으므로 상호작용 결함이 남을 위험도 있다.

경계 주변 결함은 경계값 분석(BVA)으로 보완한다. 조건 조합은 Pairwise, 결정 테이블, 원인-결과 그래프로 다룬다. 로케일·인코딩·타임존처럼 고위험인 클래스에는 리스크 기반 가중치를 적용해 복수의 대표값을 선택할 수 있다.

기법 효율성(케이스 수) 조합 커버리지 경계 민감도 운영 편의
등가분할 높음 낮음 중간(BVA 필요) 높음
경계값 분석 중간 낮음 높음 중간
Pairwise 중간 높음(2-way) 중간 중간
결정 테이블 낮음(상세) 높음 중간 낮음(모델 관리 필요)

파라미터화한 대표값 테스트

Python 3.10+와 pytest 7+ 환경에서 나이(age), 등급(tier), 주문금액(amount)의 클래스별 대표값을 파라미터로 전달하는 예시다.

# test_equivalence.py
import pytest

valid_age = [30]
invalid_age = [-1, 200]

tier = ["basic", "pro"]            # {basic, pro, enterprise} → 대표 2개만 선택(리스크 기반)
amount = [20000, 40000, 60000]     # <3만, 3만–5만, ≥5만

@pytest.mark.parametrize("age", valid_age + invalid_age)
@pytest.mark.parametrize("t", tier)
@pytest.mark.parametrize("amt", amount)
def test_checkout_validation(age, t, amt):
    # 시스템 호출 전 간단 유효성 가정
    is_valid_age = 0 <= age <= 120
    # 유효/무효 클래스별 기대 결과
    if not is_valid_age:
        # 무효 클래스 → 400 기대
        assert simulate_checkout(age, t, amt).status == 400
    else:
        # 유효 클래스 → 금액 클래스별 기대 배송비/승인 로직 검증
        resp = simulate_checkout(age, t, amt)
        assert resp.status == 200
        assert resp.shipping_fee in (0, 3000)

def simulate_checkout(age, tier, amount):
    # 테스트 더블/스텁 대체
    class Resp: pass
    r = Resp()
    if not (0 <= age <= 120):
        r.status, r.shipping_fee = 400, None
        return r
    r.status = 200
    r.shipping_fee = 0 if amount >= 50000 else 3000
    return r

이 구조에서는 동등 클래스별 대표값만 주입해 케이스 수를 통제한다. 0, 120, 29999, 30000, 49999, 50000 같은 경계값은 별도의 BVA 테스트로 분리한다.

등가분할테스트 설계명세 기반 테스트경계값 분석테스트 케이스