Atdd-Subway

ATDD란?

인수 받을 때 요구사항에 잘 맞게 개발하는 테스트

기술적인 용어없이 클라이언트가 읽기 좋은 문서로 만든다

  • BlackBox 테스트의 성질
  • 내부 구조의 동작원리를 테스트가 관여하지 않도록 한다
  • 그냥 요청과 응답으로 테스트가 잘 구현되었는지
  • 내부적으로 뭘 사용했는지 테스트한 것은 중요하지 않다

여러 직군의 이해를 돕기위한 테스트

  • 직군별로 이해관계가 다르다
  • 공통의 이해를 기반으로 하는 개발 방법론
  • 인수테스트
  • 공통적으로 이 기획을 우리가 모두 동의했으니 인수테스트를 진행하겠소

개발과정

  1. 인수조건 명시
    • 사용자스토리에 대한 설계가 이전에 있어야 한다 (여기서는 스킵)
    • 인수테스트가 만족하는 조건
    • 시나리오 기반의 표현방식을 사용 (보통의 사용법)
    • 체크 방식도 사용
    • Given When Then 사용
  2. 인수 테스트
    • 실제 요청 응답 환경과 유사하게 테스트
  3. 레거시 코드 리펙토링
    • 레거시에 대한 인수테스트를 작성하여 기존 기능을 보호
    • 그 상태에서 새로운 요구사항을 적용
    • 파악이 가능한 부분 먼저 단위테스트로 기능검증
    • 인수테스트 → 단위테스트
    • 무조건 이렇게 할 필요는 없지만 중요한 코드에 대해서는 보호를 하는것이 좋다

안수테스트가 만들어지는 과정

  • RestAssured가 요청 (클라이언트)
  • Mock으로 응답
  • 테스트 서버를 실행 (Random Port)
    • 테스트의 웹환경을 어떻게 구축할지 설정
  • RestAssured의 포트를 지정
  • 랜덤포트 사용
    • 여러 테스트가 실행되게 된다면 포트의 충돌이 생긴다.

RestAssured

  • 테스트 클라이언트 객체
  • 실제 웹서버에 요청을 보낸다.
  • 단점은 @Transactional 사용하지 못한다
  • 톰캣을 사용한다.
  • 인수 받을 때 요구사항에 잘 맞게 개발하는 ATDD의 목적 상 가장 바람직 하다.

다양한 인수테스트

MockMvc

  • webEnvironment.MOCK으로 사용
  • 가짜 요청을 보낸다
  • 실제 http를 분석하는것이 아니라 path의 값을 보고 매칭되는 컨트롤러를 찾아서 처리한다
  • 하나의 트랜잭션 내에서 동작할 수 있다
  • Rollback 사용가능하다
  • 이걸로 인수테스트 하기도 한다

WebTestClient

  • Netty를 기본으로 한다
  • Webflux가 포함된 패키지를 사용한다
  • dispatcherServlet가 아닌 Webflux의 webinder환경에 적합한 테스트 객체이다
  • tomcat을 사용하는 것이 아닌 netty를 사용한다
  • 문서화 할 때 Spring Rest Docs를 사용할 때 톰캣 환경에서 Webtestclient를 사용하여 docs를 만들기 위해서는 추가적인 설정이 필요하다

Database Cleanup

테스트의 격리를 돕는 기능

  1. @DirtiesContext
    • 컨텍스트를 초기화 해준다
    • 해당 컨텍스트를 새로 로드하도록 한다
      • 컨텍스트 캐싱을 막는다
      • 그래서 매번 컨텍스트를 구성하다보니 시간이 많이 걸림
  2. Repository의 초기화
    • 인수테스트에 사용하는 Repository를 알 수 밖에 없다
    • 해당 테스트가 특정 Repository에 강하게 결합되어 있다
  3. @Transactional
    • RestAssured에서는 Transactional 사용불가
  4. 쿼리를 이용한 초기화
    • 최대한 블랙박스에 가깝게 만드는 설정

ATDD 개발 순서

  1. 실패 인수 테스트 작성
  2. 실패 단위 테스트 작성
  3. 테스트 통과 되는 코드 작성
  4. refactor
  5. 2 3 4를 1번이 성공할 때 까지 반복

인수 조건을 테스트로

인수 조건 예시

Feature: 간략한 기능 서술
   Background: 각 시나리오 사전 조건
   Scenario: 시나리오 제목

   Given: 사전조건
   When: 발생해야하는 이벤트
   Then: 사후조건
   
   And: 앞선 내용에 추가적인 내용 기술 

인수 테스트 클래스

  • Feature 기준으로 인수 테스트 클래스를 나눈다.
  • Scenario 기준으로 하나의 인수 테스트 메서드를 작성한다.
  • Feature 내부에 있는 Scenario는 같은 테스트 픽스쳐를 공유한다.
  • 픽스쳐란?
    • setUp에 공통적으로 사용되는 given 절을 넣어줌
    • 가독성 증가
    • given절의 모임

간단한 성공 케이스 우선 작성

  • 간단한 성공 케이스 작성
  • 테스트가 동작하면 실제 구조에 대해 더 좋은 아이디어를 얻을 수 있음

When/Then/Given

  • When을 먼저 작성
    • 내가 무엇을 검증할지 명확하다
  • Then
    • 어떤 결과를 기대하는지
  • Given
    • 자연스럽게 Given이 도출된다

인수테스트 리팩터링

  • 각 테스트를 메소드로 묶어서 사용
    • 문서화 처럼 보일 수 있다
    • 재사용 가능
    • 너무 길면 ignore 혹은 Disable 처리하고 돌리게 된다
  • 테스트의 가독성은 중요하다
    • 가독성이 좋지않으면 방치될 수밖에 없음
    • 그러면 변경 사항에 대해 수정하기도 힘들다
    • 가독성이 좋으면 기능의 스펙을 나타낼 수 있다
    • 최대한 쪼개라
    • 그렇지 않으면 @Ignore과 @Disable로 범벅이 될 것이다
  • 중복 제거 방법
    • 메서드 분리
    • CRUD 추상화
    • 어떻게??
    • Cucumber 혹은 JBehave 사용