속성 기반 테스팅(Property-Based Testing, PBT)은 입력값을 수동으로 지정하지 않고 자동으로 생성된 무작위 데이터로 속성(불변 조건)이 항상 성립하는지 검증하는 테스팅 기법이다. Haskell의 QuickCheck에서 유래했다.
예제 기반 테스트 vs 속성 기반 테스트
| 항목 | 예제 기반 | 속성 기반 |
|---|
| 입력 | 개발자가 수동 지정 | 자동 생성 (수백~수천 케이스) |
| 검증 | 특정 출력값 일치 | 성질(property) 항상 성립 |
| 발견력 | 생각한 케이스만 | 엣지 케이스 자동 발견 |
| 재현성 | 항상 동일 | Seed 기록으로 재현 가능 |
typescript
import fc from 'fast-check';
// 속성 1: 정렬 후 길이 보존
fc.assert(
fc.property(fc.array(fc.integer()), arr => {
const sorted = [...arr].sort((a, b) => a - b);
return sorted.length === arr.length;
})
);
// 속성 2: 정렬 후 단조 증가
fc.assert(
fc.property(fc.array(fc.integer()), arr => {
const sorted = [...arr].sort((a, b) => a - b);
return sorted.every((v, i) => i === 0 || sorted[i-1] <= v);
})
);
// 속성 3: 멱등성 (두 번 정렬 = 한 번 정렬)
fc.assert(
fc.property(fc.array(fc.integer()), arr => {
const once = [...arr].sort((a, b) => a - b);
const twice = [...once].sort((a, b) => a - b);
return JSON.stringify(once) === JSON.stringify(twice);
})
);
// 속성 4: 가역성 (인코딩 후 디코딩 = 원래 값)
fc.assert(
fc.property(fc.string(), s => {
return Buffer.from(Buffer.from(s).toString('base64'), 'base64').toString() === s;
})
);
주요 라이브러리
Shrinking (축소)
PBT의 핵심 기능: 반례 발견 시 최소 재현 케이스 자동 탐색
예) [5, -3, 0, 7, -8] 에서 실패
Shrinking: [-3] 또는 [-1] 로 최소화하여 보고
→ 개발자가 버그 원인 파악 용이
관련 문서