Be-Developer

UnitTesting 03 단위 테스트 구조

03 단위테스트 구조

구성 방법

  1. AAA 패턴 사용
    • 단순하고 균일한 구조를 갖는 데 도움된다.
    • 준비 구절 : 테스트 대상 시스템과(SUT, System Under Test) 의존성을 원하는 상태로 만든다.
    • 실행 구절 : 메서드를 호출하고 준비된 의존성을 전달하며 출력값을 캡처한다.
    • 검증 구절 : 반환값이나 SUT와 협력자의 최종상태, SUT가 협력자에 호출한 메서드 등 검증.
    • GivenWhenThen 패턴
      • AAA와 차이는 없다. Given-When-Then이 더 읽기쉽다.
    • TDD 시에는 기능동작을 알지못하므로, 실행-검증구절을 먼저 작성해도 좋다.
  2. 복수개의 준비-실행-검증 구절 피하기
    • 복수개의 실행구절이 있는것은 여러개의 동작단위를 검증하는 테스트를 뜻한다. = 통합테스트이다.
  3. 테스트 내 if문 피하기
    • 단위테스트든 통합이든 분기가 없는 간단한 일련의 단계여야한다.
    • if문은 테스트가 너무 많은것을 검증한다는 표시이다.
  4. 각 구절은 얼마나 커야하는가
    • 준비구(given)이 가장 큰 경우 :
      • 테스트 내 private 메서드, factory class로 분리하는것이 좋다.
      • 코드 재사용 패턴 : Object Mother , Test Data Builder
    • 실행구절이 한줄 이상인 경우를 경계하라.
      • 절대 두줄 이상 두지말라고 할수는 없지만, 캡슐화가 깨져있는 경우라고 볼수있다.
  5. 검증 구절은 검증문이 얼마나 있어야하는가
    • 단위테스트는 코드의 단위에 따라 분리되는것이 아니므로, 검증문이 하나만 있어야한다는 말은 옳지 않다.
    • 모든 속성 검증 대신, 적절한 필드만 equal 테스트를 하는것이 좋다.
  6. 테스트 대상 시스템 구별하기
    • 테스트 대상을 의존성과 구분하는것은 중요하다. 준비구절에서 다른것들과 구분하기위해 변수명을 sut로 해보자.
  7. 준비.실행.검증 주석 제거하기
    • AAA 패턴을 따르고 준비 및 검증 구절에 빈줄을 추가하지 않아도 되는 테스트라면 구절 주석을 제거하고, 그렇지않으면 주석을 달자.

      xUnitTest 프레임워크 살펴보기

      .Net 전용 프레임워크이며 다른 언어 프레임워크도 비슷하다. 그냥 검색해서 살펴보자

      testFixture 재사용

      • 테스트에서 언제 어떻게 코드를 재사용하는지 아는것이 중요하다.
      • 준비구절에서 재사용하는것이 가장 효율적.
      • TestFixture은 테스트 실행 대상 객체이다. SUT로 전달되는 인수.
        • 각 테스트 실행 전에 알려진 고정 상태로 유지하기때문에 동일한 결과를 생성한다.
      • 테스트 클래스 생성자 혹은 setup 단계에서 testFixture을 사용하는것은 잘못된 방법.
        • 테스트간 결합도가 높아지고 가독성이 덜어진다.
  8. 테스트간의 높은 결합도는 안티패턴이다.
    • 테스트 클래스에 공유상태를 두지말자.
  9. 테스트 가독성을 떨어뜨리는 생성자 사용
    • 준비구간이 짧더라도 테스트메서드내에서 하는것이 좋다.
  10. 더 나은 테스트 픽스처 재사용법
    • private factory method를 두고 재사용해도좋다.
    • 테스트용 db연결 처럼 테스트 전부 또는 대부분에 사용되는 픽스처를 생성자에 인스턴스화하는것은 좋은 방법이다.

      단위테스트 명명법

       - 좋지 않은 예 : sut_sinario_result -> `Sum_TowNumbers_ReturnsSum`
       - 쉽고 잘 읽히는 영어제목을 하자 -> `Sum_of_two_numbers`
       - 엄격한 명명 정책을 따르지는 않는다.
       - 단어를 밑줄 표시로 구분한다.
       - 테스트 클래스 명을 지정할때는 보통 ClassNameTest 라고 짓지만, 꼭 Class가 동작단위는 아니므로, 여기서 Class는 동작단위로 검증할수있는 진입점으로 여긴다.
       - **SUT의 메서드 이름은 테스트명에 포함하지말라.**
         - 코드를 테스트하는것이 아니므로!! 이는 test suite의 유지보수성에 부정적인 영향을 미친다.
       - sould be -> is 사실을 서술할때는 소망이나 욕구가 들어가지않아야한다. ### 매개변수화된 테스트 리팩터링하기
       - 동작이 너무 복잡하면 매게변수화된 테스트를 사용하지 마라.
       - 매개변수만으로 테스트결과를 예측할수있다면, 하나의 메서드로 두고 boolean결과를 매개변수에서 같이 넘기자. ### 검증문 라이브러리를 사용한 테스트 가독성 향상
       - 가독성이 높은 라이브러리를 사용하자. (책에서는 Fluent Assertions)