테스트 공정관리

한국 SI의 단위테스트는 JUnit의 unit test가 아니다

같은 단어가 서로 다른 두 가지를 가리킨다. 이 글은 그 차이를 정리하고, 국내 테스트 공정에서 단위테스트가 실제로 어떻게 수행되는지를 다룬다.


SI 프로젝트에 처음 들어간 개발자가 “단위테스트 결과 제출해 주세요”라는 요청을 받는다. JUnit을 켜고 테스트 클래스를 작성한다. 그리고 돌려준 답은 이것이다.

“아니요, 화면 캡처요.”

이것은 오해가 아니다. 같은 단어가 두 가지를 가리키고 있을 뿐이다. 그리고 그 둘은 목적부터 다르다.


1. 두 개의 단위테스트

unit test (국제 표준)단위테스트 (국내 SI 현장)
대상함수 · 클래스 (코드 레벨)화면 · 기능 · 프로그램
수행 시점개발 중, 코드 작성과 동시개발 완료 후
수행 방식자동화 (JUnit, NUnit, pytest)수동
반복커밋마다 수백~수천 회원칙적으로 1회
의존성mock · stub 으로 격리실제 연동 상태 그대로
산출물CI 로그 · 커버리지 리포트시나리오 · 케이스 · 증적
목적회귀 방지완료 증명
읽는 사람개발팀발주처 · 감리 · 감사

마지막 행이 이 표의 핵심이다.

unit test는 코드를 볼 수 있는 사람을 위한 것이고, 국내 단위테스트는 코드를 볼 수 없는 사람을 위한 것이다.

그래서 한쪽은 CI 로그로 충분하고, 다른 쪽은 화면 캡처가 필요하다.

unit test는 개발팀이 읽는 회귀 방지 장치이고, 국내 SI 단위테스트는 발주처가 읽는 완료 증명 장치임을 계약 경계를 사이에 두고 대비한 개념도


2. 왜 이렇게 갈라졌는가

관행이라서가 아니다. 구조가 그렇게 만들었다.

발주처와 수행사가 분리되어 있다

국내 SI는 발주처(고객)와 수행사(개발)가 계약으로 나뉜다. 발주처는 소스 코드를 보지 않는다. 볼 권한이 있어도 읽을 인력이 없는 경우가 대부분이다.

발주처가 확인하고 싶은 것 : "요청한 기능이 실제로 동작하는가"
발주처가 확인할 수 없는 것 : 커버리지 87%, 테스트 통과 342건

커버리지 숫자는 발주처에게 아무것도 증명하지 못한다. 그래서 “이 화면에서 이 값을 넣으니 이 결과가 나왔다”는 이미지가 필요해진다.

검수와 감리가 산출물을 요구한다

공공·금융 사업에서 단위테스트 결과서는 대개 계약 산출물 목록에 명시된 항목이다. 제출하지 않으면 검수가 나지 않는다. 즉 이것은 기술 활동이면서 동시에 계약 이행 행위다.

자동화 인프라가 없던 시절에 굳었다

CI가 보편화되기 전, 테스트를 반복 실행할 수단이 없던 시기의 방식이 그대로 남았다. 지금은 인프라가 있지만 산출물 양식이 먼저 굳어 있어 쉽게 바뀌지 않는다.

정리하면 — 국내 단위테스트는 기술적으로 열등한 unit test가 아니라, 다른 문제를 푸는 다른 장치다. 문제는 이름이 같다는 것뿐이다.

이 글에서 “단위테스트”는 후자를 가리킨다.


3. 개발 요청은 두 갈래다 — SI와 SR

단위테스트를 이야기하기 전에 요청의 성격부터 나눠야 한다. 둘의 단위테스트는 같은 이름으로 불리지만 확인해야 할 것이 다르다.

SI (정보화사업)SR (변경개발요청)
성격신규 구축기존 시스템 변경
범위 결정요구사항 정의서영향도 분석
기준선없음 (처음 만든다)있음 (기존 동작)
단위테스트가 답할 질문요구대로 동작하는가바꾼 것이 동작하는가
+ 안 바꾼 것이 여전히 동작하는가

여기서 자주 무너진다

SR인데 SI처럼 테스트하는 경우다.

변경 요청 : 주문 화면에 할인 항목 추가
단위테스트 : 주문 화면에서 할인이 적용되는지 확인  ✅ 통과
운영 반영 후 : 정산 배치가 실패                    ❌

변경한 화면만 확인하고 끝냈기 때문이다. SR의 결함은 대부분 “건드리지 않은 곳”에서 나온다.

그래서 SR의 단위테스트 케이스는 두 종류로 구성되어야 한다.

① 변경 케이스   바꾼 것이 의도대로 동작하는가
② 영향 케이스   영향도 분석에서 식별된 범위가 여전히 동작하는가   ← 자주 누락된다

②가 없는 SR 단위테스트는 테스트가 아니라 확인이다.

SI는 요구 충족 케이스만 필요하지만 SR은 변경 케이스와 영향 케이스가 모두 필요하며, 영향 케이스가 자주 누락되어 건드리지 않은 곳에서 결함이 발생함을 나타낸 도식


4. 누가 하는가

책임 구조

PM  ─────────────────────  개발 요청 전체의 책임
 │                          범위 · 일정 · 품질에 대한 최종 책임

 ├── 단위 개발 A ── 단위 개발 책임자 ── 단위테스트 수행
 ├── 단위 개발 B ── 단위 개발 책임자 ── 단위테스트 수행
 └── 단위 개발 C ── 단위 개발 책임자 ── 단위테스트 수행

모든 개발 요청의 책임은 PM에게 있다. 요청은 단위 개발로 분할되고, 각 단위마다 책임자가 지정된다. 단위테스트의 수행 주체는 그 단위를 개발한 담당자다.

호칭은 현장마다 다르다. PL, 파트 리더, 담당 개발자, 단위 책임자 등으로 불린다. 조직에 따라 PL이 관리자를 뜻하는 경우도 있으므로, 문서에서 쓰는 호칭을 먼저 정의해 두는 편이 안전하다.

⚠ 만든 사람이 테스트한다는 것의 의미

이 구조에는 피할 수 없는 문제가 있다. 확증 편향이다.

만든 사람은
  · 자기가 생각한 사용 경로로만 테스트한다
  · "이건 이렇게 쓰는 거니까"라는 가정이 케이스에 그대로 들어간다
  · 실패를 찾으러 가는 것이 아니라 성공을 확인하러 간다

테스트의 목적은 원래 결함을 찾는 것인데, 만든 사람은 동작을 확인하는 것을 목적으로 삼기 쉽다. 같은 활동처럼 보이지만 결과가 다르다.

그럼에도 왜 개발자가 하는가

  • 단위 수준의 내부 동작은 만든 사람만 안다
  • 제3자가 단위마다 들어오면 비용이 몇 배가 된다
  • 통합 · 시스템 단계에서 제3자 검증으로 보완하는 구조를 전제한다

즉 개발자 단위테스트는 그것만으로 완결되는 장치가 아니라, 이후 단계와 묶여야 작동한다. 단위에서 다 잡았다고 가정하는 순간 이 구조는 무너진다.

보완할 수 있는 것

① 케이스를 코드가 아니라 요구사항에서 뽑는다

코드를 보고 케이스를 만들면, 코드가 하는 일만 확인하게 된다.

② 정상 경로 외 케이스를 의무화한다

경계값 · 필수값 누락 · 권한 없음 · 중복 · 취소.

③ 케이스 리뷰만이라도 다른 사람이 한다

수행은 개발자가 하되, 케이스 목록은 제3자가 본다. 비용이 가장 적게 들면서 효과가 큰 지점이다.


5. 무엇을 남기는가 — 시나리오 · 케이스 · 증적

세 산출물의 관계는 이렇다.

산출물답하는 질문
시나리오무엇을 확인할 것인가주문 등록 후 할인이 반영되어 저장된다
케이스어떤 입력에 어떤 결과를 기대하는가할인율 10% 입력 → 최종금액 9,000원
증적실제로 그랬다는 기록결과 화면 캡처

증적이 증명하는 것과 못 하는 것

증명한다      "그 시점에, 그 화면에서, 그 결과가 나왔다"

증명하지 못한다
  · 그 케이스가 충분했는가        ← 케이스 설계의 문제
  · 다른 입력에서도 그런가        ← 표본의 문제
  · 지금도 그런가                ← 시점의 문제

세 번째가 가장 중요하다. 증적은 그 시점의 스냅샷이다. 코드가 바뀌면 증적은 자동으로 낡는다. 그런데 증적은 스스로 낡았다고 알려주지 않는다.

이것이 국제 표준 unit test와 결정적으로 다른 지점이다. 자동화된 unit test는 커밋마다 다시 실행되므로 항상 현재를 증명하지만, 증적 이미지는 과거를 증명할 뿐이다.

증적 이미지는 캡처한 그 시점만 증명하고 이후 코드가 바뀌어도 갱신되지 않는 반면, 자동화 테스트는 매 커밋마다 실행되어 항상 현재를 증명함을 시간축으로 대비한 도식

그래서 증적 기반 단위테스트는 회귀 방지 수단이 될 수 없다. 회귀는 통합 · 시스템 단계 또는 별도의 자동화로 막아야 한다. 이 둘을 혼동하면 “단위테스트를 했는데 왜 회귀가 나느냐”는 질문이 반복된다.


6. 쟁점 — 실패한 케이스를 남길 것인가

현장에서 가장 자주 갈리는 지점이다. 그리고 어느 쪽이든 대가가 있다.

남기지 않는 쪽의 논리

· 단위테스트는 개발자 자체 검증이다.
  개발 중에 안 되던 것을 고치는 것은 "결함"이 아니라 개발 과정이다.

· 모든 시행착오를 기록하면 오버헤드가 산출물의 가치를 넘어선다.

· 발주처가 요구하는 것은 "최종 상태의 증명"이지 과정의 기록이 아니다.

· 실패를 남기게 하면 담당자가 방어적으로 굴어
  오히려 기록의 정직성이 떨어질 수 있다.

따라서 단위테스트 결과서에는 완성된 상태의 결과만 등록한다.

남기는 쪽의 논리

· 통과율이 항상 100%면 품질 지표가 성립하지 않는다.
  측정할 수 없는 것은 개선할 수 없다.

· 결함이 언제 발견되고 언제 수정됐는지 추적할 수 없다.
  결함 밀도 · 제거 효율 같은 지표가 만들어지지 않는다.

· 재발 방지 학습이 사라진다.
  같은 결함이 다음 프로젝트에서 그대로 반복된다.

· 감사 관점에서 "실패가 하나도 없는 테스트 기록"은
  오히려 신뢰도가 낮게 평가될 수 있다.

절충이 가능한 지점

두 논리는 사실 서로 다른 것을 “실패”라고 부르고 있다.

개발 중 시행착오        케이스를 확정하기 전, 만들면서 고친 것
                        → 기록 대상이 아니다

케이스 판정 실패        케이스를 확정한 뒤 실행했는데 기대와 달랐던 것
                        → 기록 대상이다

케이스를 확정한 시점을 기준선으로 삼으면 두 입장이 양립한다. 그 전은 개발이고, 그 후는 테스트다.

결정 기준은 하나다 — 무엇을 위해 남기는가

증적의 목적실패 기록이유
완료 증명 (계약 · 검수)불필요최종 상태만 증명하면 된다
품질 측정 (지표 · 개선)필수실패 없이는 어떤 지표도 만들 수 없다

둘 다 하려면 둘 다 남겨야 한다. 목적을 정하지 않은 채 관행으로 결정하면, 나중에 품질 지표를 만들려 할 때 데이터가 없다는 사실을 그때 발견하게 된다.


7. 이 글이 말하지 않는 것

  • 현장마다 용어와 절차가 다르다. 공공 · 금융 · 일반 SI가 다르고, 발주처 표준에 따라서도 다르다. 이 글은 널리 통용되는 형태를 정리한 것이지 표준을 규정하지 않는다.
  • 어느 방식이 옳다고 주장하지 않는다. 특히 6절의 쟁점은 조직의 목적에 따라 답이 달라진다.
  • 이 절차가 실제로 결함을 얼마나 잡는지는 다루지 않았다. 그것은 의견으로 답할 수 없고 측정이 필요하다. 단위테스트를 통과한 뒤 통합 단계에서 발견되는 결함의 비율(누수율)이 그 답이 될 수 있는데, 다음 글들에서 다룰 예정이다.

정리

① “단위테스트”는 두 가지를 가리킨다

국제 표준 unit test는 코드를 보는 사람을 위한 회귀 방지 장치이고, 국내 SI 단위테스트는 코드를 못 보는 사람을 위한 완료 증명 장치다.

② 요청이 SI인지 SR인지에 따라 확인할 것이 달라진다

SR에는 변경 케이스와 영향 케이스가 함께 있어야 한다.

③ 만든 사람이 테스트하는 구조에는 확증 편향이 있다

케이스 리뷰만 분리해도 상당 부분 보완된다.

④ 증적은 그 시점을 증명할 뿐 현재를 증명하지 않는다

회귀 방지는 다른 수단이 맡아야 한다.

⑤ 실패 케이스를 남길지는 “증적을 무엇에 쓸 것인가”로 결정된다

완료 증명이면 불필요하고, 품질 측정이면 필수다.


이 글은 「테스트 공정관리」 시리즈의 1편입니다.

다음 글 예정 2편 — SI와 SR, 개발 요청의 두 갈래와 테스트 성격의 차이 3편 — 테스트 공정의 역할 구조 4편 — 자기가 만든 것을 자기가 테스트할 때 생기는 일 5편 — 증적은 무엇을 증명하고 무엇을 증명하지 못하는가 6편 — 실패한 케이스를 남길 것인가 7편 — 단위테스트에서 새어나간 결함, 누수율을 재봤다


※ 이 글은 개인의 견해이며 소속 회사의 공식 입장이 아닙니다. 특정 고객사나 프로젝트의 정보를 포함하지 않으며, 일반적으로 통용되는 절차를 정리한 것입니다.

이 글은 개인의 견해이며 소속 회사의 공식 입장이 아닙니다. 특정 고객사나 프로젝트의 정보를 포함하지 않습니다.