LabHub
배우기 러닝패스 코스

테스트 도구 실전 · 경계값 테스트로 실제 결함을 잡는다 · 이론

경계값 테스트로 실제 결함을 잡는다의 설계 원리

LabHub 에서 이어서 보기

한 줄 요약

좋은 경계값 테스트는 그럴듯하게 틀린 구현과 올바른 구현을 구별한다.

개념 지도: 한 줄 요약 · 왜 이게 필요했나 · 어떻게 동작하나 · 현장에서 만나는 모습

왜 이게 필요했나

열 줄짜리 요금 계산기도 경계 하나가 틀리면 모든 주문에 잘못된 금액을 청구한다.
price(3)이 1050임을 확인하는 테스트는 할인 임계값의 >=가 >로 바뀌어도 통과한다.
많은 중간값을 반복하기보다 조건이 바뀌는 바로 전·그 지점·바로 뒤를 선택해야 한다.
이 실습은 커버리지 보고서의 숫자를 읽지 않는다. 작성한 테스트를 정상 코드에서
실행한 뒤 조건 하나가 틀린 코드에서 다시 실행하여 차이를 실제로 관찰한다.

어떻게 동작하나

| 입력 | 계약 |
|---|---|
| 정수 0 | 0원 |
| 정수 1~9 | 개당 350원 |
| 정수 10~100 | 전체 수량에 개당 300원 |
| 범위 밖 정수 | ValueError |
| 정수 아닌 값·bool | TypeError |

할인은 10번째 항목 이후만 적용하는 누진 방식이 아니라 전체 수량의 단가를 바꾼다.
이 문장 없이 테스트를 작성하면 서로 다른 정책을 두고 어느 구현이 맞는지 논쟁하게 된다.
테스트 이름과 예상 금액에는 정책의 의미가 드러나야 한다.

현장에서 만나는 모습

Python에서 bool은 int의 하위 클래스라 isinstance(True, int)가 참이다. 업무에서
수량 True를 1개로 받아도 되는지 언어가 정해 주지 않는다. 이 계약은 명시적으로
거절하므로 bool을 별도 반례로 둔다. 반면 구현의 변수명이나 if 문 개수를 검사하면
같은 동작의 리팩터링을 버그로 오인한다. 입력·결과·예외를 관찰해야 한다.

다음 실습에서 할 것

0, 1, 할인 직전·경계·직후, 최대값, 음수, 잘못된 타입의 여덟 테스트를 누적한다.
정상 구현에서 실패하면 테스트의 예상값부터 고친다. 결함 구현에서 실패하더라도
문법 오류나 임포트 오류는 결함 검출로 인정하지 않는다. 실행된 테스트의 assertion이
실패하거나 예상과 달리 실행 중 예외가 나야 한다. 이 결함 표본을 모두 잡는 것은 검증한 계약에 대한 증거이지 모든 버그가
없다는 증명은 아니다.

참고: [pytest 시작하기](https://docs.pytest.org/en/stable/getting-started.html)