본문 바로가기
Spring

ATDD, 클린 코드 with Spring 과정을 통해 배운 인수 테스트(Acceptance Test)

by bkuk 2024. 3. 8.

인수 테스트(Acceptance Test)

본 포스팅은 ATDD, 클린 코드 with Spring에서 경험한 E2E(API) 테스트 기반의 인수 테스트에 대한 내용을 소개합니다.

독자분들에게 미리 말씀드립니다.

  • 인수 테스트가 만능이다?
  • 인수 테스트를 무조건 작성해야 한다?

절대 아닙니다!!!


인수 테스트란?

인수 테스트에 대해 이야기하기 전, 먼저 테스트가 무엇인지 스스로 고민해볼 필요가 있을 것 같습니다.

어떤 사람은 아래와 같이 생각할 수 있을 것 같습니다.

코드를 작성하고 검증하는 것

인수 테스트를 작성하기 시작한다면, 아래와 같이 생각해볼 수 있을 것 같습니다.

코드를 작성하기 전, 어떤 코드를 작성해야 하는지 TODO 리스트를 작성하는 것

이는 TDD(Test Driven Development)에서 실패하는 테스트를 작성하고 기능을 구현하는 접근법과 유사하다고 볼 수 있을 것 같습니다.
(그래서 인수 테스트 + TDD의 결합으로 ATDD 라는 개념이 도출되었다고 알고 있습니다.)

TDD 사이클
참고: https://i0.wp.com/hanamon.kr/wp-content/uploads/2021/04/TDD-%E1%84%80%E1%85%A2%E1%84%87%E1%85%A1%E1%86%AF%E1%84%8C%E1%85%AE%E1%84%80%E1%85%B5.png?w=1024&ssl=1


다시 본론으로 돌아와서, 인수 테스트의 개념에 대해서 알아보겠습니다.

인수 테스트 사전적 정의
참고: https://en.wikipedia.org/wiki/Acceptance_testing

위키 백과를 참고하자면, 명세나 계약의 요구 사항이 충족되는지 확인하기 위해 수행되는 테스트 라고 합니다.

그렇다면, 작업을 완료해도 되는지를 검증하는 테스트라고 볼 수 있을 것 같은데요.
반대로 생각해본다면, 테스트가 성공하면 해당 작업이 완료되었다고 간주된다는 의미라고 볼 수 있을 것 같습니다.

일반적으로 인수 테스트는 프론트 엔드 기반에서 검증하는 경우가 많다고 볼 수 있을 것 같은데요.
필자가 경험했던 인수 테스트는 아래와 같이 정리해볼 수 있을 것 같습니다.

E2E 테스트

백엔드 개발자가 단독적으로 진행할 수 있는, API 접점에서 진행하는 E2E 테스트


이와 관련하여, 린 애자일 기법을 활용한 테스트 주도 개발에서 더 자세히 다루고 있으니, 참고해주시면 좋을 것 같습니다.

인수 테스트의 개념은 테스트 의도에 따라 정해지는 것이지 테스트를 어떻
게 구현하는지에 따라 정해지는 것이 아니다.
유닛 레벨이나 통합 레벨, 사용자 인터페이스 레벨에서 인수 테스트를 적용할 수 있다.
… 더 나아가, 인수 테스트를 유닛이나 컴포넌트가 의도한 동작을 하는지 확인하는 설계 검증 테스트로 사용할 수 도 있다.
어떤 경우든 인수 테스트는 사용자에게 애플리케이션이 인도될 수 있는 지를 확인한다.

린 애자일 기법을 활용한 테스트 주도 개발 (저자: 케네스 퍼그)


여기까지 읽으셨다면,

그래서 인수 테스트를 어떻게 작성한다고?

라고 생각하실 수 있으실 것 같아요.

지금부터는, ATDD, 클린 코드 with Spring에서 경험했던 미션 내용을 기반으로 인수 테스트를 작성하는 방법에 대해서 설명해드려 볼게요.

우선, 앞으로 설명할 도메인에 대해서 확인해 주세요.

지하철 도메인 설명

지하철 도메인
참고: ATDD, 클린 코드 with Spring 강의 자료 中 ...

위 그림에서 표현된, 지하철 관련 도메인은 지하철 역(Station), 지하철 노선(Line), 지하철 구간(Section)으로 총 3가지 정도로 구분해 볼 수 있을 것 같습니다.



인수 테스트 없이 기능 구현

우선, 인수 테스트 없이 지하철 역생성(Create)하는 기능을 구현해본다고 가정해보겠습니다.

그렇다면, 각 기능에 대해서 domain -> Repository -> Service -> Controller 계층을 순차적으로 설계해볼 것 같아요.(개발자에 따라 순서가 상이할 수 있을 것 같아요.)

그리고 나서, 모든 코드 다 작성했다면 아래와 같은 흐름으로 테스트를 진행할 것 같습니다.

  1. Spring Application 실행
  2. API 요청 기반 테스트 진행
  3. 응답 코드 및 응답 Body 확인

2번에 대해서 그림으로 표현한다면, 아래와 같은 화면에서 요청 및 검증을 진행할 것 같네요.

테스트코드_없이_검증

인수 테스트를 작성한다면, 위 모든 내용을 테스트 메서드 실행 한 번으로 자동화 할 수 있습니다.

얼마나 쉽고 편할지 ... 예상이 되실까요?

또, 사전에 어떠한 시나리오로 테스트하는지, 이해당사자(기획자, 프론트 개발자, 우리 팀원들)와 함께 논의 혹은 인지시킬 수 있다면 얼마나 좋을까요?


인수 테스트 작성하기

인수 테스트에서는 기능을 구현하기 전, 이해당사자와 충분한 시간을 가지고 인수 조건 혹은 인수 테스트 시나리오를 정의합니다.

아래와 같이 정의했다고 가정해보겠습니다.

인수 테스트 시나리오


그렇다면, 해당 시나리오대로 생성(Given)하고, 조회(When)하고, 검증(Then)하는 코드를 작성하면 됩니다.

테스트 진행 시, 실제 Spring Application 환경에서 주입되는 Spring Bean 을 기반으로 진행하기 때문에, Spring Cotainer를 구동시켜줘야 하는데요.

이에, Spring에서는 @SpringBootTest 어노테이션을 제공하며, webEnviroment 속성을 통해 Web 설정을 진행할 수 있습니다.
이는, 테스트 서버의 구동 환경을 설정하는 것인데요. 간단하게 짚고 넘어가도록 하겠습니다.


인수_테스트_설정

  • MOCK: Mocking 된 웹 환경 제공
  • RANDOM_PORT: 랜덤으로 설정된 포트 기반으로 실제 웹 환경을 구성
  • DEFINED_PORT: 지정한 포트를 기반으로 실제 웹 환경을 구성
  • NONE: 아무런 웹 환경을 구성하지 않음.

서버를 구동시킨 후, 어떻게 테스트 코드에서 HTTP 기반 API 요청을 할 수 있을까요?

REST API 기반의 테스트를 할 수 있는 REST-assured 라이브러리를 사용해볼 수 있을 것 같습니다.

지하철 역을 생성 요청하는 코드를 통해 살펴볼게요.

지하철_역_생성요청

각 단계에 대한 설명은 아래 내용을 참고해주시면 좋을 것 같습니다.

  • Given : 테스트 수행 전 사전 조건 설정
  • When : REST API 호출과 같은 동작 설정
  • Then : 테스트의 결과 검증

지하철 역이 생성이 되었다는 것을 어떻게 검증하는 것이 좋을까요?
아무래도, HTTP 응답에서 상태 코드를 기반으로 검증하는 것이 좋아보입니다.

그렇다면, 아래와 같이 검증할 수 있을 것 같아요.

지하철_역_생성_요청_검증

여기서 몇가지 질문을 해볼 수 있는데요. 생성 요청에 대한 검증은 Status Code로 충분할까요?

위에서 인수 테스트 시나리오를 정의할 때 지하철 역 목록 조회 시 생성한 역을 확인할 수 있다. 라는 검증 시나리오가 있기 때문에 한 번 더 검증이 필요합니다.

그렇다면 목록 조회 요청에 대한 응답 Body의 데이터를 어떻게 검증할 수 있을까요?

Rest-Assured 라이브러리에서는 응답 Body를 JsonPath 객체로 반환할 수 있는 메서드를 제공하는데요.

그렇다면 반환된 객체 즉,Json을 파싱할 수 있다는 뜻이겠죠?

지하철_역_목록_조회_검증

지금까지 인수 테스트에 대해서 설명해 드려보았는데요.

어떠셨을까요? 괜찮으셨다면, 아래 내용도 끝까지 읽어주시면 좋을 것 같습니다.


테스트 코드 리팩토링

테스트 코드도 프로덕션 못지않게, 유지보수 관리 대상이기 때문에 제대로 관리하지 않으면 방치되거나 삭제되는 코드가 됩니다.

아래와 같이 고민이 들 것 같아요.

  • 반복되는 코드를 재사용 가능하도록 분리해볼까?
  • 테스트 코드를 가독성 좋게 리팩토링 해볼까?

인수 테스트를 작성하다가 이러한 부분이 고민이 든다면, 언제든지 댓글을 남겨주시면 좋을 것 같습니다.

제가 ATDD, 클린 코드 with Spring에서 경험한 테스트 코드 리팩토링은 아래와 같이 진행했었습니다.
(cucumber 라이브러리 기반으로 리팩토링 하는 방법도 있는데요. 추후 기회가 된다면 포스팅해보도록 하겠습니다.)

인수_테스트_리팩토링

마무리

요근래 깔끔하고 읽기 좋은 프로덕션 코드와, 테스트 코드를 작성하려는 노력을 하게되면서, 정말 많이 성장한 것 같다고 느낍니다.

아직 의도적인 훈련이 매우 많이 필요하지만, 꾸준하게 노력한다면 언젠간 더 많이 성장했을 거라고 믿습니다.(저는 어제의 나보다 지금의 내가 성장했다는 것에 만족하며 살아갑니다.)

아무쪼록 평소 인수 테스트를 작성해보시지 않았다면, 이번 기회에 작성해보시는 것을 추천드립니다.

제대로 한번 배워보고 싶으시다면, ATDD, 클린 코드 with Spring 강력 추천드립니다.

좋은 경험하게 해주신 류성현 강사님과 모든 리뷰어님들께 감사드립니다.

참고하면 좋은 코드와 영상

댓글