본문으로 바로가기

3주차 - 인수 테스트 주도 개발

3주차 미션은 인수 테스트 주도 개발이다. 처음 인수 테스트 주도 개발(이하 ATDD)는 참 어려운 말이 었던 것 같다,, 인수는 Acceptance를 번역한 말로 흠,, 인수인계할 때 그 인수.. ATDD는 뭔가 알 것 같으면서도 어려운 느낌.. 거의 대부분의 개발 방법론이 그렇게 느껴진다. 아무튼 내가 이해한 인수 테스트는 사용자가 프로그램을 실행 했을 때 수행되는 전체 로직을 테스트를 하는 것이라고 머릿 속에 저장했다.
TDD가 도메인의 단위 기능 하나하나를 테스트하는 것이라고 하자. 그럼 그 단위 테스트가 모여서 한 기능의 비즈니스 로직을 수행할 수 있게 된다. 그럼 사용자 입장에서 그 기능을 수행했을 때 처리되는 비즈니스 로직이 정상적으로 이루어 지는지 여부를 테스트 하는 것!
그래서 제일먼저 ATDD 기반의 실패하는 테스트 코드를 작성하고 TDD로 도메인 서비스 개발을 진행한다. 모든 TDD가 성공하는 테스트코드가 되었을 때 ATDD는 성공이 된다! 라고 생각한다.

TDD의 단점을 보완하기 위해 인수 테스트(acceptance test)를 먼저 구현한 후 이후 단위 테스트를 통해 기능을 완성해 가는 과정으로 애플리케이션을 개발할 수 있다 - 우테캠 포비 -

추 후에 ATDD에 대해 좀 더 다루는 정리 글을 작성해봐야겠다,,
이번 미션은 총 4단계 이고 지하철 노선도 관리 서비스를 구현하는 것이다.

1단계 - 지하철 노선 관리

1단계는 간단했다! 지하철 노선을 생성하고 조회 그리고 삭제와 수정이 가능하도록 구현하는 것! 근데 인수 테스트를 연습하는 단계 이기 때문에 또 그렇게 간단하지만은 않았던 것 같다
1단계의 리뷰어님은 kingbbode 님!! 아마 아실만한 분은 다 아실 것 같은 리뷰어님,, 실력도 좋으시고,, 이번 미션에서도 많이 배워서 너무 감사드립니다😀😀😀
  • Optional은 값이 있으면 NullPointException을 방지하기 위해 Opional<T>로 감싸주지만 바로 get()메서드를 사용하는 것은 코드 스멜이다

  • 코드스멜 은 프로그램 상에서 뭔가 심오한 문제를 발생시킬 수 도 있는 코드를 말한다.

  • 테스트 코드를 작성해서 테스트를 하는 방법은 정말 여러가지가 있다,, 눈에 보이는 테스트가 다가 아니라 좀 더 Document를 읽어보면 다양한 방법이 나올 것이다

  • DynamicTest.dynamicTest 를 이용해서 시나리오 테스트를 진행하는 것으로 수정했다

2단계 - 인수 테스트 리팩터링

2단계는 이미 구현되어 있는 인수 테스트 코드를 리팩토링을 하는 단계이다. 노선에 상행역과 하행역을 추가하여 구간을 가지고 있는 노선을 CRUD 할 수 있도록 코드를 리팩토링을 하는 것.
  • 2단계 JPA에서 다뤘던 내용이다. 2단계에서 받은 피드백을 또 받은 건 아니고, 킹뽀대님의 피드백을 듣고 2단계를 정리한 것 PK는 추상화하지 않기

  • 영속성 객체와 연관관계를 가지고 있는 Entity에 대해서도 아직 잘 모르는 상황이었다,, 구간을 가지고 있는 노선을 저장하고 구간의 상행성 하행선을 또 저장을 해줘서 받은 피드백,,, 흐어어 CASCADE의 옵션에 대해서도 공부를 해야된다.

  • 표현계층은 Response는 Domain의 변경에 민강하기 때문에 노출 시키지 말기!

  • Section Domain을 제거하고 SectionRespose라는 구간 표현객체를 만들어주었다.

  • 2단계 마지막 피드백은 의존관계의 방향성에 대한 피드백. 이 의존관계의 방향성이 굉장히 중요하다는 것을 7주차 미션을 하면서 배웠는데 의존 관계의 방향성을 생각하지 않고 구현하다보면 의존 사이클이 발생할 수 도있음.. 이 부분은 7주차 때 다시 다루는 걸로

3단계 - 구간 추가 기능

3단계는 구간 추가 기능,, 꽤나 힘들었던... 구간을 등록할 수 있는 조건에 대해서 한 4~5가지가 있다. 기존 구간의 길이와 같으면 안되고 상행선, 하행선 둘 중 하나는 꼭 있어야 되는 역이고.. 등등 근데 이런 조건들이 들어가서 인수테스트 개발을 하고 Java 컨벤션을 지키다 보니 뭔가 재밌었던 미션이었다.

"Happy Path"는 '아무것도 잘못되지 않는 사용자 시나리오'를 의미한다 (All-Pass Scenario / Positive Test). 이는 사람의 실수, 엣지 케이스, 의도를 벗어난 행동을 포함하지 않기 때문에 이 시나리오 대로 테스트를 수행하면 이슈나 버그가 발생할 가능성이 현저히 낮아진다.

먼저 행복회로의 코드를 작성하고 불행회로 하나하나 추가하는데... 왜케 오류가 많던지... 흐어어엉
  • 3단계 첫번 째 피드백은 Layer간의 참조(의존) 관계를 잘 생각해야한다. 실제로 그냥 필요하니까 참조해야지 하고 딱 서버를 구동시키는데 순환참조 오류가 발생했다,,

  • 이 피드백도 아직 연관관계에 대해서 어려움을 겪었었던 피드백,, 다대다 양방향 매핑을 지양하기 위해 일대다 : 다대일의 중간 객체를 만들어 사용햇는데 Entity 두개를 저장하고 중간객체도 따로 저장을 해줘야하는 건가.. 에 대한 고민.. 이 부분은 한쪽에서 한쪽으로 참조가 가능한 상태로 만들어 부모 엔티티 저장시 자식 엔티티도 같이 저장되도록 보완했다

Layer들의 각 기능과 관계들은 더 공부할 필요가 있을 것 같다.
3단계 까지 끝!

4단계 - 구간 제거 기능

3단계 까지가 좀 어려웠던 것 같고 4단계는 구간 제거 기능이라 그렇게 어렵진 않았다. 금방 끝났던 단계였다.
아 따로 피드백이 없는 단계네... ㅎㅎ,, 바로 merge 된 단계 였다..

마치며..

인수테스트 주도 개발에서 제일 좋았던 건 인수테스트를 작성하고 단위테스트 기반으로 도메인을 구현한 다음 인수테스트를 딱 실행시켰을때.. 초록불이 들어오는 느낌..ㅎㅎ 이게 사용자입장, 통합테스트, 모듈테스트, 시나리오 테스트가 아닐까 싶다 이렇게 보면 인수테스트가 딱 무엇이겠다! 하는 느낌은 오는 듯한 느낌적인 느낌이랄까..