TDD

Test-Driven Development

2 minute read

단위 테스트 기초

단위 테스트 하네스

  • 테스트 케이스를 표현하기 위한 공통 언어
  • 일부나 전체 테스트 사례를 구동하기 위한 메커니즘
  • 테스트 슈트의 성공이나 실패를 자세히 보고하지만 로그는 남기지 않는다.
  • TOF(True or False)

테스트 픽스쳐

  • 테스트 대상 코드를 수행하는 일련의 테스트 케이스를 위한 적절한 환경을 제공하는 코드
  • 양상 코드를 수행하기 위한 일반적인 설정과 환경을 수립하기 위해 도움을 준다.

테스트와 해당 테스트의 SUT 범위

  • SUT: 테스트 대상 시스템(System Under Test)으로 테스트하려는 대상 모두를 의미
  • DOC: 의존 컴포넌트로 SUT에서 호출하거나 SUT를 실행하는데 필요한 데이터를 미리 설정하는 컴포넌트이다.
  • SUT와 DOC 모두 테스트 픽스쳐의 일부이다.

단위 테스트

  • 결함 국소화를 위해 하나의 시나리오 안에서 하나의 메소드나 객체만 실행하는 단일 조건 테스트로 만들어야 한다.
  • 단위 테스트는 크기가 작으므로 테스트 실패를 보면 문제를 금방 확인할 수 있다. 고객 테스트(E2E)에 비해 우월한 이유가 여기에 있다.
  • 특성 테스트(비기능적 테스트)는 단위테스트가 아니다.

테스트 자동화의 목표

  • 테스트는 테스트 대상 시스템을 이해하는데 도움이 되어야 한다.
  • 자동화된 테스트 진행 과정에서 SUT에 없는 문제를 일으키게 해선 절대 안된다.
  • 테스트는 실행하기 쉬워야 한다. CI/CD 시스템의 일부가 되어야 한다.
  • 테스트 코드도 단일 책임 원칙을 따라서 한가지 기능만을 테스트해야한다.
  • 테스트를 먼저 작성해야 한다. 코드 작성에 앞서 테스트를 작성하면 저절로 테스트하기 쉽게 설계하게 된다.

테스트 자동화의 철학

  • 상태주의자: SUT를 특정 상태에 두고 실행한 후 SUT가 원하는 상태인지 검증한다.
  • 동작주의자: SUT의 시작과 끝 상태 뿐만 아니라 SUT가호출하는 것까지 검증한다.

테스트 자동화의 원칙

  • 절대 SUT를 고쳐서는 안된다. 테스트 코드가 사용 코드와 달라지기 때문이다.
  • 테스트를 독립적으로 유지해서 순서에 영향을 받지 않도록 해야한다. 자동화 과정에서 순서를 고려하면 어려워지기 때문이다. 신선한 픽스쳐(teardown)를 사용해서 독립적인 테스트를 유지하자.
  • 테스트 로직을 상용 코드에 넣어서는 안된다. if testing then…
  • 실행에 0.1초가 걸리는 테스트는 매우 느린 단위 테스트이다. 클래스가 3000개가 있고 각각 10개의 단위테스트가 있다면 3000초가 걸리며 약 한시간이 걸린다. 네트워크 연동, 데이터베이스 연동, 파일 시스템 접근 등 DOC를 격리하지 못하여 시간이 오래걸리는건 아닌지 의심해봐야 한다.

TDD 기초

TDD

  • Test the program before you write it - Kent Beck
  • XP(eXtream Programming)의 실천 방식 중 하나이다.
  • 개발자가 자신을 위해 처음으로 수행하는 테스트이다.

Kent Beck의 5단계

  • 작은 테스트를 추가한다.
  • 모든 테스트를 돌리고, 새로운 실패를 보거나 컴파일 오류를 본다.
  • 테스트를 통과하기 위해 필요한 가장 작은 변경을 만든다.
  • 모든 테스트를 돌려서 새로운 테스트가 통과하는지 본다.
  • 중복을 제거하고 표현력을 높이기 위해 리팩토링을 수행한다.

Test Double

  • 스턴트맨은 콩글리시이다. 스턴트 더블이라는 용어가 맞고, 테스트 더블 역시 스턴트맨과 같은 의미로 쓰이는 녀석이다.
  • Stub, Dummy, Spy, Mock, Fake Object가 있다.

  • Duumy object: 테스트의 일부로 어떤 인자를 전달해야 하지만인자를 사용하지 않는다는 사실을 알고 있을 경우에 사용하며, 인터페이스의 모든 메소드들의 NULL을 반환하도록 구현한다. 예를 들어 DOC가 DOC를 인자로 받는 경우 등에 사용한다.

  • Test Stub : 더미의 일종으로 NULL대신 테스트가 필요로 하는 특정 값을 반환한다. 예를 들어 로그인이 필요한 시스템의 경우 로그인 검증이 아닌 경우에 로그인을 항상 동작하도록 미리 구성할 수 있다.

  • Test Spy: Stub의 일종으로 자신이 호출된 사실을 기억하고 테스트에 이런 사실을 보고하는 목적으로 사용한다. 어떤 함수가 언제 몇 번 어떤 인자로 호출되었는지를 보고 받을 수 있지만, 테스트 코드와 양산 코드 사이의 결합도가 높아지는 단점이 있다. 주의할 점은 Mock과는 달리 Spy에서는 자체적으로 Verify를 하지 않는다는 점이다.

  • Mock Object: Spy의 일종으로 어떤 일이 있어났는지를 아는 스파이이다. 호출이 있어났는지 알려주는 verify() 메소드를 제공해야 한다. 호춣이 성공했는지에 대해서는 관심을 갖지 않으며 호출이 이루어졌는지만을 관심으로 가진다. 따라서 DOC는 검증할 수 없으며 DOC는 다른 테스트에서 SUT로서 테스트해야한다. Mock에 너무 비지니스 로직을 많이 넣으면 테스트가 어려워진다. 전체적은 흐름만을 검증하자. 행동주의자적 검증에 해당한다.

  • Fake Object: 일종의 시뮬레이터로 복잡한 작동 상황을 컴퓨터를 사용해 실제와 같이 재현한다. Stub이 아니며 실제 비지니스 행위를 구현한다.