개념
리그레션 테스트란
리그레션(Regression) 테스트 는 소프트웨어가 변경된 뒤에, 그 변경이 의도치 않게 새 결함을 만들지 않았는지, 시스템이 기존 요구사항을 여전히 충족하는지 확인하는 테스트다. "회귀 테스트"라고도 부른다. 앞 레슨들에서 본 재테스팅과 짝을 지어 두자.
| 재테스팅 | 리그레션 테스트 | |
|---|---|---|
| 묻는 것 | 고친 그 결함 이 없어졌나? | 고친 탓에 다른 곳 이 망가지지 않았나? |
| 쓰는 케이스 | 처음 결함을 검출한 케이스 | 기존에 통과하던 케이스들 |
변경이 생기면 각 레벨 순서대로 — 컴포넌트, 통합, 시스템 — 리그레션 테스트를 한다. 하향식 통합에서 스텁을 실물 모듈로 바꿀 때마다 리그레션을 하는 것도 같은 이유다.
유지보수의 네 유형과 비율
변경은 주로 유지보수 단계에서 생긴다. 가이드는 유지보수를 네 가지로 나눈다.
| 유형 | 영문 | 무엇을 하나 | 비율 |
|---|---|---|---|
| 기능 보강 | Perfective | 기능 추가, 성능 개선 | 50% |
| 적응 | Adaptive | 새 운영 환경에 맞춘다 | 25% |
| 결함 수정 | Corrective | 사용 중 발견된 결함을 고친다 | 21% |
| 예방 | Preventive | 문서 정비, 유지보수하기 쉬운 구조로 바꾼다 | 4% |
결함 수정이 가장 많을 것 같지만 실제로는 기능 보강이 절반 이라는 점이 출제 포인트다. 유지보수는 고장 수리라기보다 계속 키워 나가는 일이고, 그만큼 변경이 잦아 리그레션이 끝없이 필요하다는 뜻이기도 하다.
리그레션 비용은 쌓인다
기능 F1F4를 차례로 추가하는 시스템을 생각해 보자. 각 기능의 테스트 세트를 TS1TS4,
실행 시간을 T1~T4라고 하면 다음과 같다.
| 추가 기능 | 새 테스트 | 리그레션 대상 | 리그레션 시간 |
|---|---|---|---|
| F1 | TS1 | — | — |
| F2 | TS2 | TS1 | T1 |
| F3 | TS3 | TS1 + TS2 | T1 + T2 |
| F4 | TS4 | TS1 + TS2 + TS3 | T1 + T2 + T3 |
기능이 늘수록 리그레션 시간이 계속 쌓인다. 그래서 "전부 다시 돌린다"는 방식은 언젠가 감당할 수 없게 된다. 여기서 네 가지 전략이 나온다.
리그레션 전략 넷
| 전략 | 영문 | 방법 | 장점 | 위험·단점 |
|---|---|---|---|---|
| 전체 재실행 | Retest-All | 기존 케이스를 모두 실행 | 절차가 단순, 빠뜨림이 없다 | 시간과 자원이 너무 많이 든다 |
| 선택적 리그레션 | Regression Test Selection | 변경 영향 분석으로 결과가 달라질 수 있는 케이스만 고른다 | 변경과 관련된 것에 집중 | 영향 분석이 틀리면 빠뜨린다 |
| 테스트 최소화 | Test Minimization | 커버리지가 중복되는 케이스를 제거 한다 | 세트 자체가 작아진다 | 케이스가 실제로 지워지므로 변경 부분을 보던 케이스가 사라질 위험 |
| 테스트 우선순위화 | Test Prioritization | 결함을 빨리 많이 찾을 순서로 정렬, 높은 순위부터 | 시간이 모자라도 효과를 최대화 | 무엇이 결함을 잘 찾을지 미리 알기 어렵다 |
옛 판 그림에는 첫 번째 방식이 "Restest-All"로 잘못 적혀 있었다. 정식 이름은 Retest-All 이다.
선택적 리그레션의 변경 영향 분석에는 슬라이싱 기법 과 자료 흐름 분석 이 쓰인다. 슬라이싱이라면, 어떤 케이스가 실행한 문장 가운데 출력에 영향을 주는 부분을 추리고 그 안에 변경된 문장이 있으면 그 케이스를 리그레션 대상으로 고른다.
테스트 최소화는 커버리지 개념으로 중복을 찾는다. 케이스 t1이 실행한 문장이 t2가 실행한 문장을 모두 포함하면 t2를 지울 수 있다. 선택적 리그레션은 이번에만 고르는 것이고, 최소화는 세트에서 지우는 것이라는 차이가 핵심이다.
우선순위는 현실적으로 비즈니스 중요도, 리스크, 실행 시간, 커버리지, 과거 결함 검출 내역을 함께 보고 정한다.
APFD — 우선순위화가 얼마나 잘 됐나
APFD(Average Percentage of Faults Detected) 는 테스트 케이스 실행 순서가 결함을 얼마나 빨리 찾았는지를 0~100 사이 값으로 나타낸다. 높을수록 적은 케이스로 많은 결함을 일찍 찾았다는 뜻이다.
APFD = ( 1 − (TF1 + TF2 + … + TFm) / (n × m) + 1 / (2n) ) × 100
n : 테스트 케이스의 수
m : 결함의 수
TFi : 결함 i 를 처음으로 검출한 테스트 케이스의 실행 순서상 위치세 덩어리로 읽으면 쉽다. 가운데 분수는 "결함들이 평균적으로 얼마나 늦게 발견됐는가"이므로
작을수록 좋고, 1에서 빼니 클수록 좋은 값이 된다. 마지막 1/(2n) 은 면적을 계단 모양으로
계산하며 생기는 보정값으로, 케이스 수가 같으면 항상 같은 값이다.
손계산 예제
케이스 5개(AE), 결함 4개(f1f4)가 있고, 각 케이스가 검출하는 결함이 다음과 같다.
| 케이스 | f1 | f2 | f3 | f4 |
|---|---|---|---|---|
| A | × | |||
| B | × | × | ||
| C | × | × | ||
| D | ||||
| E | × |
n = 5, m = 4이므로 n × m = 20, 1/(2n) = 0.1 이다.
순서 1 — A, B, C, D, E
f1은 A(1번째), f2는 B(2번째), f3는 B(2번째), f4는 C(3번째)에서 처음 검출된다. TF의 합 = 1 + 2 + 2 + 3 = 8.
APFD = (1 − 8/20 + 0.1) × 100 = (1 − 0.4 + 0.1) × 100 = 70순서 2 — D, E, A, B, C
f1은 A(3번째), f2는 B(4번째), f3는 E(2번째), f4는 C(5번째). TF의 합 = 3 + 4 + 2 + 5 = 14.
APFD = (1 − 14/20 + 0.1) × 100 = (1 − 0.7 + 0.1) × 100 = 40순서 3 — C, B, A, E, D
f1은 C(1번째), f4도 C(1번째), f2와 f3는 B(2번째). TF의 합 = 1 + 2 + 2 + 1 = 6.
APFD = (1 − 6/20 + 0.1) × 100 = (1 − 0.3 + 0.1) × 100 = 80같은 케이스 다섯 개인데 순서만 바꿔서 40에서 80까지 달라졌다. 순서 3은 두 케이스(C, B)만 돌려도 결함 네 개를 모두 찾는다. 시간이 두 케이스 분량밖에 없다면 순서 2로는 결함 하나도 제대로 못 찾지만 순서 3으로는 전부 찾는다. 이것이 우선순위화의 가치다.
계산할 때 실수하기 쉬운 곳 두 가지. 첫째, TF는 결함마다 하나씩이다. 한 케이스가 결함 두 개를 찾으면 두 결함의 TF가 같은 값으로 각각 더해진다. 둘째, 결함을 하나도 못 찾는 케이스 (D)도 n에 포함 된다.
수험서 예제 검산 — 정오표로 바뀐 값
수험서 3장의 APFD 예제는 케이스 5개와 그들이 검출한 결함 5개 를 쓴다. 옛 판 본문에는 "검출한 4개의 결함"이라고 잘못 적혀 있었고, 정오표에서 5개로 정정되었다. 그래서 n = 5, m = 5다.
첫 번째 실행 순서(TC1~TC5 순서대로)에서 다섯 결함이 처음 검출되는 위치는 정오표가 적은 식에 따라 1, 2, 4, 3, 2다.
APFD = (1 − (1+2+4+3+2)/(5×5) + 1/(2×5)) × 100
= (1 − 12/25 + 0.1) × 100
= (1 − 0.48 + 0.1) × 100
= 62옛 판은 이 결과를 42 로 적고 있었다. 0.48을 빼고 0.1을 빼는 실수를 하면 42가 나온다 (1 − 0.48 − 0.1 = 0.42). 보정값은 더한다 는 것을 기억하자. 시험에서 이 예제가 변형되어 나오면 이 부호 하나로 정답이 갈린다.
변경 후 리그레션 절차
애플리케이션이 바뀌면 리그레션은 레벨 순서로 진행된다.
- 컴포넌트 테스트 — 변경이 올바른지 확인하고, 기존 컴포넌트 기능에 대해 컴포넌트 리그레션을 한다.
- 통합 테스트 — 변경된 컴포넌트와 연동하는 컴포넌트를 대상으로 통합 테스트를 하고, 새 기능이 있으면 그 기능의 통합 테스트도 한다. 기존 기능에 대해 통합 리그레션을 한다. 필요하면 시스템 테스트 전에 스모크 테스트 (핵심 기능이 기본적으로 돌아가는지 빠르게 확인)를 한다.
- 시스템 테스트 — 컴포넌트를 모두 합쳐 새 기능을 확인하고 GUI 끝단 간(end-to-end) 테스트를 한다. 시간과 비용에 따라 Retest-All이나 우선순위화로 부분 리그레션을 한다. 변경에 따라 성능·보안 같은 비기능 테스트도 한다.
- 테스트 유지보수 — 아래에서 따로 본다.
예를 들어 일반 택배만 있던 온라인 상점에 퀵서비스를 추가한다면, 컴포넌트 단계에서는 퀵서비스 배송지 입력 화면을 테스트하되 택배·퀵 API 서버는 모의 객체로 대신한다. 통합 단계에서는 실제 퀵서비스 API와 붙여 배송지가 제대로 넘어가는지 보고, 기존 택배 흐름에 대한 통합 리그레션을 한다. 시스템 단계에서는 GUI로 퀵서비스를 테스트하고, 시간이 모자라면 우선순위 1·2등급만 골라 기존 택배 GUI 리그레션을 한다.
테스트 유지보수 — 케이스도 늙는다
리그레션 세트는 그대로 두면 썩는다. 다음 일이 필요하다.
- 비즈니스에서 사라진 기능의 케이스는 제거 한다. 남겨 두면 엉뚱한 실패가 보고되어 테스트 전체의 신뢰를 떨어뜨린다.
- 요구사항이 바뀌어 입출력 관계가 달라진 케이스는 고친다.
- 필요하면 최소화 로 중복을 걷어 낸다.
- 새로 추가한 케이스는 자동화해 리그레션 세트에 넣는다. 리그레션은 많은 케이스를 자주 돌리므로 자동화하는 편이 효율적이다.
실무에서 왜 필요한가
리그레션은 테스터 시간의 가장 큰 덩어리다. 릴리스 직전 "전체 리그레션에 3일 걸리는데 일정은 하루"라는 상황은 흔하다. 이때 네 전략의 이름과 위험을 알면 선택지를 논리적으로 제시할 수 있다. "변경 영향 분석으로 결제·주문 관련 120건을 고르고(선택), 그 안에서 과거 결함이 많았던 순으로 돌리겠습니다(우선순위화). 남는 위험은 배송 조회 쪽이고 운영 모니터링으로 보완하겠습니다." 이렇게 말하면 일정 단축이 품질 포기가 아니라 위험을 관리한 결정이 된다.
APFD를 실무에서 직접 계산하는 일은 드물지만, 그 발상 — 같은 시간에 결함을 더 일찍 찾는 순서 — 은 CI 파이프라인 설계에 그대로 쓰인다. 최근에 실패했던 테스트, 최근 변경된 파일을 건드리는 테스트를 앞에 두면 실패 신호를 몇 분 일찍 받는다.
테스트 최소화의 위험도 실무에서 실제로 일어난다. 커버리지 도구가 "이 케이스는 중복"이라고 해서 지웠는데, 그 케이스만 쓰던 특이한 입력값(경계값 같은 것)이 있어 나중에 그 경계에서 결함이 새는 경우다. 커버리지가 같아도 입력값의 의미 가 다를 수 있다.
채용시장에서의 위치
자동화 엔지니어 공고에는 "리그레션 테스트 자동화 및 유지보수"가 거의 항상 들어간다. 면접에서 "리그레션 테스트 시간을 어떻게 줄였나요?"라는 질문에는 도구 이야기보다 전략 이야기를 먼저 하는 편이 좋다. "변경 영향으로 선택하고, 실패 이력으로 정렬했고, 중복을 걷어 냈다"는 답에 숫자 (실행 시간 몇 시간에서 몇 분으로)가 붙으면 강한 답이 된다. 신입이라면 수동 리그레션 체크리스트를 우선순위 등급으로 나눠 운영해 본 경험만으로도 충분히 이야깃거리가 된다.