개념
단위(Unit)란 무엇인가
"단위"는 보통 함수 하나, 또는 클래스의 메서드 하나처럼 더 이상 쪼개기 애매한 가장 작은 코드 조각을 뜻한다. 단위 테스트(Unit Test)는 이 작은 조각 하나를, 다른 코드나 외부 시스템과 분리한 채 독립적으로 검증한다.
function calculateDiscount(price, rate) {
return price - (price * rate)
}
// 단위 테스트: 이 함수 하나만 떼어내서 검증
test("10% 할인율이면 가격이 10% 줄어든다", () => {
expect(calculateDiscount(10000, 0.1)).toBe(9000)
})통합 테스트(Integration Test)와의 범위 차이
단위 테스트가 함수 하나를 검증한다면, 통합 테스트는 여러 단위가 서로 맞물려 실제로 잘 동작하는지를 검증한다.
단위 테스트: calculateDiscount() 함수 하나만 검증
통합 테스트: 장바구니 API가 실제 데이터베이스와 연결돼서
주문 생성→할인 계산→저장까지 전체 흐름이 맞는지 검증| 단위 테스트 | 통합 테스트 | |
|---|---|---|
| 범위 | 함수/클래스 하나 | 여러 컴포넌트의 상호작용 |
| 속도 | 매우 빠름(밀리초 단위) | 상대적으로 느림(DB·네트워크 관여) |
| 외부 의존성 | 모듈 9(레슨 9)에서 배운 것처럼 분리·대체함(레슨 3에서 다룬다) | 실제(또는 실제에 가까운) 의존성을 그대로 씀 |
| 실패 시 원인 파악 | 매우 명확함(그 함수 자체의 문제) | 상대적으로 넓음(여러 컴포넌트 중 어디인지 확인 필요) |
AAA 패턴 — 거의 모든 테스트 코드의 공통 구조
프레임워크가 무엇이든(레슨 2에서 다룬다), 테스트 코드는 대부분 이 세 단계로 구성된다.
test("VIP 회원은 배송비가 무료다", () => {
// Arrange — 테스트에 필요한 상황을 준비한다
const cart = { total: 10000, memberLevel: "VIP" }
// Act — 실제로 검증하려는 동작을 실행한다
const result = isEligibleForFreeShipping(cart.total, cart.memberLevel)
// Assert — 결과가 기대한 대로인지 확인한다
expect(result).toBe(true)
})- Arrange(준비) — 모듈 3에서 배운 사전조건과 같은 개념
- Act(실행) — 실제 테스트 대상 동작
- Assert(확인) — 모듈 3의 기대 결과와 같은 개념
이 구조를 알면, 문법이 낯선 언어로 짜인 테스트 코드를 봐도 "이 부분은 준비, 이 부분은 실행, 이 부분은 확인이구나"를 짚어낼 수 있다.
왜 QA가 이걸 읽을 줄 알아야 하는가
개발자가 "이 기능은 단위 테스트로 이미 커버돼 있어요"라고 말할 때, QA가 그 테스트 코드를 열어 실제로 어떤 케이스를 검증하고 있는지 읽을 수 있으면, "이 경계값은 테스트에 없네요"처럼 구체적인 피드백을 줄 수 있다. 이건 모듈 7(레슨 5)에서 배운 TDD/BDD 워크숍에서의 QA 역할과 정확히 이어진다.
실무에서 왜 필요한가
"단위 테스트를 다 통과했다"는 말이 "이 기능이 완벽하다"는 뜻은 아니다 — 단위 테스트는 각 조각이 개별적으로 맞다는 것만 보장하고, 조각들이 실제로 맞물렸을 때의 문제(통합 테스트의 영역)나 사용자 관점의 문제(수동 탐색적 테스트의 영역, 모듈 5)는 못 잡는다. QA가 단위 테스트의 범위와 한계를 정확히 이해하면, "이미 테스트됐으니 괜찮다"는 막연한 안도감 대신 "이 부분은 단위 테스트로 커버되지만, 저 부분은 별도로 확인해야 한다"는 구체적인 판단을 할 수 있다.
실습 과제
과제 1 — AAA 구조 짚어보기 (10분)
다음 테스트 코드에서 Arrange, Act, Assert에 해당하는 부분을 각각 표시한다.
test("재고가 0이면 구매 버튼이 비활성화된다", () => {
const product = { name: "한정판 텀블러", stock: 0 }
const isDisabled = isPurchaseButtonDisabled(product)
expect(isDisabled).toBe(true)
})과제 2 — 단위 vs 통합 판단하기 (10분)
다음 두 테스트가 각각 단위 테스트인지 통합 테스트인지 판단하고 이유를 적는다.
- "할인율 계산 함수에 0.2를 넣으면 20% 할인된 값을 반환한다"를 확인하는 테스트
- "회원가입 API를 호출하면 실제 데이터베이스에 사용자가 생성되고, 환영 이메일 발송 큐에 작업이 들어간다"를 확인하는 테스트
자가 체크리스트
- 단위 테스트가 검증하는 범위를 설명할 수 있다
- 단위 테스트와 통합 테스트의 속도·범위·실패 원인 파악 차이를 설명할 수 있다
- AAA(Arrange-Act-Assert) 패턴을 테스트 코드에서 식별할 수 있다
- "단위 테스트를 통과했다"는 말의 한계를 설명할 수 있다
흔한 실수
- "단위 테스트를 다 통과했으니 이 기능은 완벽하다"고 오해한다. 단위 테스트는 조각 하나하나의 정확성만 보장할 뿐, 통합 시나리오나 사용자 경험까지 보장하지 않는다.
- 단위 테스트와 통합 테스트를 속도나 이름만으로 구분하고 실제 범위를 확인하지 않는다. 파일 이름에 "test"가 들어있다고 전부 같은 성격의 테스트는 아니다.
- 테스트 코드를 아예 읽지 않고 "테스트가 있다"는 말만 믿는다. AAA 구조만 알아도 어떤 케이스가 실제로 검증되는지 확인할 수 있다.
참고 자료
- Kent Beck, Test-Driven Development: By Example — 단위 테스트와 AAA 패턴의 고전적 정의
- ISTQB Glossary — Unit Testing, Integration Testing — 두 테스트 레벨의 공식 정의