E2E 테스트

디우·2022년 6월 24일
0

우아한테크코스 레벨2 기간에 학습한 E2E 테스트 강의 내용을 정리한다.


미션을 진행하면서 여러가지 의문이 들 수 있다.
Q. 컨트롤러는 어떻게 테스트할까?
Q. 웹 기반에서는 어떻게 테스트할까?

위와 같은 의문을 가지고 답을 고민하면서 글을 읽으며 본인만의 답을 찾아보자!

테스트 도구

  • JUnit
    JUnit은 자바에서 단위 테스트용으로 많이 사용하는 프레임워크로써,
    우리가 사용한 spring-boot-starter-test 안에는 junit에 대한 라이브러리가 존재한다.
  • 스프링 테스트 도구
    • @SpringBootTest
      -> 등록한 빈들을 테스트에서 사용할 수 있게 도와주는 어노테이션이다.
    • @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE
      -> 웹 서버를 활용한 테스트
      -> webEnvironment의 종류는 다음과 같다.
      • MOCK : Mocking된 웹 환경을 제공한다. MockMvc를 활용한 테스트를 진행할 수 있다.
      • RANDOM_PORT : 실제 웹 환경을 구성한다.
      • DEFINED_PORT : 실제 웹환경을 구성하지만 랜덤이 아닌 지정한 포트를 사용한다.
      • NONE : 아무런 웹 환경을 구성하지 않는다.
    • @WebMvcTest
      -> 웹에서 테스트하기 힘든 컨트롤러를 테스트하는데 적합한 어노테이션으로 @Controller, @ControllerAdvice, @JsonComponent, HandlerInterceptor, Filter 등과 같은 내용만 스캔한다.
      -> @SpringBootTest보다 가볍게 테스트할 수 있다.
      -> 요청과 응답에 대해서 테스트 할 수 있다.
      -> 즉 스프링 빈들중에 Controller와 관련된 것을 테스트할 때 사용하면 좋다.
    • @JdbcTest
      -> 스프링 빈들 중에 DB와 관련된 테스트를 할 때 사용한다.
      -> in-memory embedded database가 설정되어 테스트를 위한 JdbcTemplate을 생성해준다.
      -> 일반적인 빈들은 스캔되지 않는다.
      -> @Transactional 어노테이션을 포함하고 있기 때문에 기본적으로 각 테스트마다 Rollback된다.

테스트 종류

테스트들의 종류, 즉 테스트의 목적이 존재하지만 경계를 구분하기 어려운 경우도 존재한다는 것을 인지하고 가자

Unit Test (단위 테스트)

단위는 어떤 메소드 혹은 어떤 클래스가 될 수 있다.
단위에 대한 정의에서 공통적으로 이야기하는 것은 가장 최소한의 개념이다. (가장 작은 단위 혹은 범위)

@DisplayName("지하철역 정보를 수정한다.")
@Test
void updateStation() {
	// given
    Station station = new Station("강남역");
    
    // when
    station.updateStation("판교역");
    
    // then
    assertThat(station.getName()).isEqualTo("판교역");
}

위의 코드에 대해서는 이견이 없을 것이라고 생각한다. 하지만 협력 객체를 사용해야 하는 경우에는 개발자들마다 어떻게 단위 테스트를 수행할 것이냐에 대해서는 의견이 나뉠 수 있다.

@DisplayName("구간을 추가할 수 있다.")
@Test
void addSection() {
	// given
    Station station1 = new Station("강남역");
    Station station2 = new Station("잠실역");
    Station station3 = new Station("역삼역");
    
    Line line = new Line("2호선", "green", station1, station2, 10);
    
    // when
    line.addSection(station2, station3, 5);
    
    // then
    assertThat(line.getStations()).containsExctlyElementsOf(Arrays.asList(station1, station2, station3));
}

즉, 위와 같이 station 뿐 아니라 Line 그리고 그 안에서는 또 Section과 같이 여러 객체가 협력하는 경우에는 어떻게 단위 라는 개념을 나누고 단위 테스트를 진행할 것이냐 하는 고민이 있을 수 있다.

통합과 고립(Sociable & Solitary)

두 객체가 서로 연관된 객체라면 둘 다 실제 객체를 사용해서 테스트하자라는게 Sociable Tests이고, 연관된 객체를 고립시켜서 연관 객체에 대해서는 Mock과 같은 가짜 객체를 주입해서 테스트하자는 것이 Solitary Tests 이다.

출처 : Solitary or Sociable? Testing Events and Listeners using Laravel

무엇이 옳다고 이야기하는 것은 적절하지 않다고 생각한다. 단지 단위라는 개념을 어떻게 받아들이냐에서 차이가 존재한다고 생각한다.

통합 테스트 (Integration Test)

독립된 단위가 서로 연결될 때 올바르게 작동하는지를 확인하는 테스트이다.

통합 테스트는 요청부터 DB까지 갔다가 응답까지의 흐름(flow)를 모두 통합이라고 보는 넓은 의미에서의 경우가 있을 수 있고, 좁은 의미에서 통합 테스트는 애플리케이션과 DB 연결을 확인하거나 다른 서비스와 잘 연동되는지를 확인하는 경우를 말할 수도 있다.
하지만 독립된 단위가 서로 연결되어 잘 동작하는지를 확인하는 목적이라는 점에서는 공통된다.

통합 테스트 예시

E2E 테스트

E2E(End-to-End) Test의 목적은 끝(End)에서 끝(End)까지 다 검증하려는 것에 있다.

앞서 보인 지하철역을 생성하는 테스트의 경우가 E2E 테스트의 예시로도 볼 수 있다.
그리고 여기에서 보인 AcceptanFixture.post() 메소드는 사실 다음과 같은 코드이다.

RestAssured.given().log().all()
	.body(params)
	.contentType(MediaType.APPLICATION_JSON_VALUE)
    .when()
    .post("/stations")
    .then().log().all()
    .extract();

즉, RestAssured 라는 것을 활용하여 테스트한 것이다.

RestAssured는 REST Assured Java 라이브러리를 사용하여 애플리케이션의 HTTP EndPoint에 초점을 맞춘 테스트 도구이다.

즉, 우리는 RestAssured를 사용해서 애플리케이션으로 오는 요청과 응답에 대해서 테스트할 수 있는 것이다. 즉, 애플리케이션의 HTTP EndPoint에 초점을 맞춰서 테스트를 할 수 있게 된다.

profile
꾸준함에서 의미를 찾자!

0개의 댓글