-
인수테스트 (Acceptance Test) ① 환경 구축 및 작성Spring 2022. 2. 8. 20:10
지난 주, 미션 진행으로 인수테스트 코드를 작성하는 방법을 배웠다.
인수테스트에 대해서 알아보고 미션 수행 후 작성한 코드를 통해서 작성 방법을 정리한다.
인수테스트란 시스템이 예상대로(요구사항대로) 동작하는지 확인할 수 있는 테스트로
개발자 - 테스터 - 고객간의 협업을 기반으로 이루어진다.
인수테스트가 통과되면 우리가 원한대로 기능이 구현되었다는 것을 알 수 있다.
테스트 종류에 따른 의미
테스트 의도 단위 테스트 소프트웨어 설계의 최소 단위(모듈, 컴포넌트)에 맞춰 작성된 테스트 인수 테스트 소프트웨어가 사용자 요구사항을 만족하는지에 맞춰 작성된 테스트 (자동화된 인수테스트는 비용이 저렴) (BLACK BOX) 통합 테스트 단위테스트가 완료된 모듈들을 결합하여 하나의 시스템을 완성하는 과정에 맞춰 작성된 테스트 (GRAY BOX) 시스템 테스트 소프트웨어가 해당 시스템에서 정상적으로 작동하는지 확인하는 테스트 인수테스트 (Acceptance Test)
인수조건 -> 인수테스트 작성 -> 문서화(Mock서버 & DTO 정의) -> 구현 및 단위테스트 -> API 개발 -> 테스트 리팩토링
작업의 요구사항(인수조건 Acceptance Criteria -> 사용자 스토리를 시나리오로 표현 (given-when-then)을 만족 및 작업의 끝을 테스트 하여 사용자의 시나리오를 검증한다. 인수테스트 주도 개발을 통하여 TDD의 단점( 작은 단위로 구현됐지만 아무데서도 호출하지 않거나 시스템의 나머지 부분과 통합이 불가능)을 보완하여 요구 사항을 사전에 정의하고 충족 검증하여 보다 명확하게 필요 기능을 구현한다. 빠른 피드백을 받을 수 있으며 기존 기능을 망가뜨리지 않고 새기능을 구현할 수 있다. ( + 회귀오류 방지 ) 인수테스트는 내부 구현이나 기술의 의존적이지 않도록 블랙박스 테스트 임을 잊지 말자. ( 내부기능이나 기술보다 표면적 요소로 검사 )
테스트 환경 구축
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class AcceptanceTest { @LocalServerPort int port; @Autowired private DatabaseCleanup databaseCleanup; @BeforeEach public void setUp() { if (RestAssured.port == RestAssured.UNDEFINED_PORT) { RestAssured.port = port; databaseCleanup.afterPropertiesSet(); } databaseCleanup.execute(); } }
- SpringBootTest(webEnvironment = ) : 테스트 할 웹 서버 환경 지정
- MOCK : Mocking된 환경제공, MockMvc 를 사용한 테스트 진행
- RANDOM_PORT : 실제 웹 환경 구성
- DEFINE_PORT : 지정된 포트로 실제 웹 환경 구성
- NONE : 아무것도 하지 않음
- 인수테스트 객체
- MockMvc : Mocking 된 웹 환경에서 테스트
- RestAssured : REST API의 테스트 및 검증을 단순화, HTTP 검증을 위한 API 활용 가능 (실제 웹 (Apache Tomcat) )
- WebTestClient : Netty를 기본으로 사용 (RANDOM_PORT, DEFINE_PORT)
- @DirtiesContext : 테스트가 실행하고자 하는 컨텍스트에 이미 bean이 올라가 있으면 Dirties를 확인하고 컨텍스트를 새로 로드하도록 설정 가능 (스프링 테스트에서는 context caching을 제공, 매번 Context를 새로 구성하면 시간이 오래걸리므로 않도록 설정도 가능)
- DatabaseCleanup : 엔티티 메니저를 통해서 @Entity 어노테이션 붙은 테이블을 조회하고 삭제(truncate), ID 자동 증가 숫자를 1로 복귀
테스트 코드 작성 전에 먼저 테스트 환경 구축을 해주자. 여기서는 RANDOM_PORT를 사용해서 지정된 포트로 실제 윕 환경을 구성하도록 하고 RestAssured를 통해서 검증을 수행하도록 설정하였다. 테스트 격리를 위해서 여기서는 DatabaseCleanup을 사용하였다. 인수테스트는 블랙박스테스트로( 내부코드 몰라야 한다 ) 시스템 외부에서 호출하여 검증하도록 한다.
테스트 코드 작성
@DisplayName("지하철 노선 관련 기능") public class LineAcceptanceTest extends AcceptanceTest { private static final String URL = "/lines"; @DisplayName("지하철 노선을 생성한다.") @Test void createLine() { // when // 지하철_노선_생성_요청 //... Map<String, Object> params = body(name, color, upStationId, downStationId, distance); ExtractableResponse<Response> response = RestAssured.given().log().all() .body(params) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post(path) .then().log().all() .extract(); // then // 지하철_노선_생성됨 assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); }
테스트 환경 구축 클래스를 상속받아 환경을 사용하도록 설정한다. RestAssured 를 이용하여 해당 API로 요청 정보를 보내고 response를 받아 정상적으로 이루어졌는지 확인할 수 있다. 여기서 RESTAPI mapping 에 따라서 get/post/put/delete 등을 설정해주도록 한다.
인수테스트 환경 및 시나리오를 작성하였으니 기능을 구현하고 기능 단위테스트작성이 이루어지면 된다. (이후 필요부분을 리팩토링)
( 참고한 사이트 )
https://tecoble.techcourse.co.kr/post/2020-09-15-test-isolation/
https://velog.io/@banjjoknim/%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC
https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/
https://www.hibri.net/2019/06/10/the_testing_pyramid/
'Spring' 카테고리의 다른 글
@ParameterizedTest사용할 때 java.lang.NoSuchMethodException 발생 시 (0) 2022.02.16 existsBy, countBy (JPA) (0) 2022.02.13 테스트를 위한 Mock과 그 외의 Test Double (0) 2022.02.03 Service Layer의 단위테스트 작성 : (2) Fake 객체 (0) 2022.02.03 Service Layer의 단위테스트 작성 : (1) Mockito ② (0) 2022.02.03 - SpringBootTest(webEnvironment = ) : 테스트 할 웹 서버 환경 지정