노트

자가 테스트 코드

Self-Testing Code

설계#testing · 연결된 개념 19개

쉽게 말하면

자가 테스트 코드는 답지가 붙은 문제집과 같아요. 문제를 풀고 답지를 넘겨 보면 맞았는지 바로 알 수 있듯, 사람이 출력을 들여다보지 않아도 명령 하나로 '모두 통과'를 알 수 있어요.

비유가 깨지는 곳 답지가 있어도 문제가 엉성하면 소용없어요. 일부러 코드를 틀리게 바꿔 테스트가 빨개지는지 확인하고, 커버리지 숫자는 테스트 안 한 곳을 찾는 데만 써요.

결과까지 스스로 판정하는 자동화된 테스트를 갖춘 코드. 사람이 출력을 눈으로 확인할 필요 없이 명령 하나로 "모두 통과"를 알 수 있어야 한다. 리팩터링의 전제 조건이다.

왜 가치 있나

  • 버그가 생기면 몇 분 전 변경에서 찾으면 되니 디버깅 시간이 크게 준다
  • 테스트가 쌓이면 잘 되던 기능이 깨지는 회귀 버그(Regression)를 바로 잡는다
  • 테스트를 먼저 쓰면 완료 시점이 분명해진다(테스트 주도 개발 (TDD))

테스트 구조

  • 준비-수행-단언(Arrange-Act-Assert), 또는 같은 뜻의 Given-When-Then: 필요한 데이터를 만들고, 동작을 실행하고, 결과를 검사한다
  • 픽스처(Fixture, 테스트에 필요한 데이터와 객체)는 테스트끼리 공유하지 않는다. 공유하면 한 테스트가 바꾼 상태가 다른 테스트를 깨뜨린다. 테스트마다 새로 만든다

무엇을 테스트하나

  • 실패해야 할 상황에서 정말 실패하는지 확인한다. 일부러 코드를 틀리게 바꿔 테스트가 빨개지는지 본다
  • 모든 걸 다 테스트하려다 하나도 못 쓰느니, 위험한 곳에 집중한다. 복잡한 처리, 경계 조건(빈 값, 음수, 범위 끝)이 우선이다
  • 외부에서 들어오는 입력은 검증 테스트가 필요하지만, 같은 코드베이스 안의 모듈끼리 서로 반복 검증할 필요는 없다
  • 버그 리포트를 받으면 그 버그를 드러내는 테스트부터 쓴다
  • 커버리지(Test Coverage)는 테스트하지 않은 곳을 찾는 데만 쓴다. 숫자 자체가 테스트 품질을 말해 주지는 않는다(굿하트의 법칙)

외부 API를 흉내 내는 데는 MSW로 API 모킹, 테스트 종류 사이의 비율은 테스트 피라미드, 나쁜 테스트의 신호는 테스트 냄새 참고. 코드 안에 가정을 남기는 어서션과도 통한다.

출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) 4장 · Self Testing Code

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 코드 냄새

    당장 버그는 아니지만 이해나 변경 비용을 높이는 구조적 신호. 리팩터링을 언제 시작하고 멈출지에 정확한 공식은 없어서, 냄새라는 어휘로 직관을 공유한다.

  • 섣부른 최적화

    "섣부른 최적화는 모든 악의 근원이다." 도널드 크누스(Donald Knuth)가 1974년 글 「Structured Programming with go to Statements」에서 쓴 말이다. 원문의 맥락은 작은 효율은 대부분(약 97%)의 경우 잊으라는 것이고, 정말 중요한 3%는 놓치지 말라는 말이 이어진다.

  • 코드 리뷰

    코드 리뷰는 작성자가 아닌 사람이 변경을 읽고 합칠지 판단하는 과정이다. 버그를 잡는 일 말고도, 팀 모두가 코드베이스를 알게 하고(collective-code-ownership) 설계 판단과 관례를 자연스럽게 퍼뜨리는 통로가 된다. 여러 사람이 모두 놓쳐야만 결함이 새어 나가게 만드는 장치이기도 하다 → growing-together

  • 보이스카우트 규칙

    코드를 처음 발견했을 때보다 조금이라도 나은 상태로 남겨 두라는 규칙. 캠핑장을 떠날 때 왔을 때보다 깨끗하게 하라는 보이스카우트 수칙을 로버트 C. 마틴(Robert C. Martin)이 소프트웨어에 옮겼다. 『리팩터링』도 같은 비유를 쓴다.

보기 옵션