[xUnit 테스트 패턴] 03장 - 테스트 자동화의 목표


03장 - 테스트 자동화의 목표

테스트를 하는 이유

테스트 자동화 경제학

  • 목표
    • 테스트 자동화가 소프트웨어 개발 비용을 늘리지 않는다는 걸 보장함으로써 테스트 자동화를 ‘당연한’ 것으로 만드는 것
  • 아래와 같은 상항에서 테스트 자동화 고려
    • 수동 단위 테스트와 디버깅/문제 해결, 프로그램 초기 제품 사용 단계에서 발견되지 않은 버그를 처리하는 비용 > 자동 테스트 구축, 유지 보수에 드는 추가 비용
  • 새로운 기술과 실천 방법을 배우는 비용 발생
    • 하지만 한번 ‘고비’를 넘고 나면 추가적으로 드는 비용 전부를 이득으로 상쇄 할 수 있는 안정적 상태 도달

테스트 자동화의 목표

  • 테스트는 품질 향상에 도움이 돼야 한다.
  • 테스트는 테스트 대상 시스템 - SUT(System Under Test) 을 이해하는데 도움이 돼야 한다.
  • 테스트는 위험을 줄여야 한다.
  • 테스트는 실행하기 쉬워야 한다.
  • 테스트는 만들고 유지하기 쉬워야 한다.
  • 테스트는 시스템이 발전해 나감에 따라 필요한 유지 보수 비용이 최소화 돼야 한다.

테스트는 품질 향상에 도움이 돼야 한다

  • 목표 : 명세로서의 테스트
    • 테스트는 여러 시나리오에 맞는 동작을 나중에 구현할 수 있는 형태로 정의할 수 있게 한다(실행 가능한 명세)
    • 테스트는 사용자가 SUT를 사용하는 방식을 실제 그대로 반영해야 함.
  • 목표 : 버그 퇴치
    • 자동 테스트는 버그 발생을 막아줌.
    • 회귀 테스트가 설치 된 코드에는 코드 체크인을 하기 전에 테스트가 버그를 찾아 줌
  • 목표 : 결함 국소화
    • 버그가 통합 빌드 과정에서 나타났을 때
      • 단위 테스트 크기가 작다면 어떤 테스트가 실패하는지를 보고 버그가 무엇인지 금방 잡아 낼 수 있다.
    • 고객 테스트
      • 고객이 원하는 동작 중 어떤 것이 잘 돌아가지 않는지 알려줌
    • 단위 테스트
      • 왜 잘 돌아가지 않는지를 알려줌
    • 고객 테스트는 실패했지만 단위 테스트는 성공 했다면 빠진 단위 테스트가 있는 것

테스트는 SUT를 이해하는 데 도움이 돼야 한다

  • 테스트는 코드가 어떻게 동작해야 하는지를 보여줄 수 있다.
  • 목표 : 문서로서의 테스트
    • 어떤 결과가 나올지를 테스트가 알려준다
    • 자동 테스트는 SUT의 문서 역할을 한다.

테스트는 위험을 줄여야(추가하지도 않아야) 한다

  • 목표 : 안전망으로서의 테스트
    • 레거시 코드 : 자동 회귀 테스트 스위트가 없는 코드
    • 회귀 테스트 스위트가 갖춰진 코드로 작업 시 훨씬 빠르게, 훨씬 실험적인 방식으로 소프트웨어를 변경 해 볼 수 있다
  • 목표 : 해를 끼치지 않을 것
    • 자동 테스트가 위험을 만들어낼 때
      • 테스트 관력 훅 hook을 SUT 안에 들어 있을 경우
    • 모든 테스트 관련 코드는 테스트와 테스트 환경에서만 플러그인 형태로 들어가야 하고 SUT의 제품 코드에 들어가면 안된다.

테스트는 실행하기 쉬워야 한다

  • 자동 테스트는 실해이 쉬워야 사람들이 자주 실행 할 수 있다.
  • 테스트를 돌려보기 쉽게 만드는 4가지 목표
    • 완전 자동 테스트
      • 따로 손 댈 것(수동 조정) 없이 돌려 볼 수 있는 테스트
      • ex) main()에서 코드를 실행시켜 결과를 콘솔에 출력만 하는 프로그램
    • 자체 검사 테스트
      • 직접 검사해보지 않고도 에러를 찾아내 알려줄 수 있는 테스트
      • 테스트가 통과하지 못했을 때에만 알려 준다.
    • 반복되는 테스트
      • 여러 번 돌려봐도 같은 결과를 얻을 수 있는 테스트
    • 독립적인 테스트
      • 테스트별로 따로 돌려볼 수 있는 테스트

테스트는 만들고 유지하기 쉬워야 한다

  • 테스트는 읽고 쓰기 쉬워야 한다.
  • 시스템의 일부 동작을 변경하면 그 결과로 일부 테스트가 영향을 받으리란걸 예상해야 한다.

테스트는 두 가지 이유로 복잡해 진다

  • 너무 많은 기능을 하나의 테스트에서 한꺼번에 검증하려 든다.
  • 테스트에서 표현하고자 하는 도메인 개념의 이전/이후 관계와의 ‘표현 간극’이 너무 크다
  • 목표 : 단순한 테스트
    • 테스트는 작아야 하고, 한 번에 하나만 테스트 해야 한다.
    • 예외 - 애플리케이션이 실제로 사용되는 시나리오를 나타내는 고객 테스트를 할 때
  • 목표 : 표현이 풍부한 테스트
    • 테스트 유틸리티 메소드 라이브러리를 구축해 도메인 전용 테스트 언어를 만들어 처리할 수 있다.
      • 테스트 개발자가 테스트하고자 하는 개념을 표현하기 위해 자신의 생각을 좀 더 상세한 코드로 번역하지 않아도 된다.
  • 목표 : 관심의 분리
    • 테스트 코드를 제품 코드로부터 떼어놓고 싶다.
    • 각 테스트는 한 가지 관심에만 집중해 애매한 테스트가 되는 걸 막고 싶다.

시스템이 발전하는 동안 테스트에 필요한 유지 보수 비용이 최소화해야 한다

  • 목표 : 견고한 테스트
    • 하나를 변경했을 때 영향 받는 테스트의 수가 최소가 될 수 있도록 테스트를 작성해야 한다.
    • 테스트끼리 최대한 적게 겹쳐야 한다.
    • 픽스처 설치, 해체 코드에 영향을 미칠 수 있는 시스템 변경을 테스트 유틸리티 메소드로 캡슐화