WebRTC 프로젝트를 진행하며 적용한 단위 테스트/통합 테스트 방법에 대한 내용이다.
최근 WebRTC 프로젝트와 오픈소스 컨트리뷰션에 참여하며, 테스트 코드에 대한 중요성을 많이 느끼게 되었다.
대학생 -> 개발자로 성장하는 데 있어 실제 배포 환경에서 문제가 발생하는 상황을 예방하는 것이 중요하다고 생각하게 되었으며, 테스트 코드의 작성이 CI 또는 변경 사항에 대한 유지 보수에 많은 도움이 될 것이므로 글을 작성하게 되었다.
추가적으로, 개발하며 테스트 코드를 비즈니스 로직과 함께 작성했어야 했지만, 촉박하게 기능을 개발하는 바람에 테스트 코드를 잘 작성하지 못했다.
그래서 부족한 부분을 프로젝트가 끝난 후에 보강 개념으로 단위 테스트/ 통합 테스트를 구현해보았다.
우선, 인프런, 유데미, 패스트 캠퍼스 등 여러 플랫폼에서 테스트 관련 강의들이 존재한다.
하지만 주관적인 관점에서 테스트 코드를 어떻게 짜면 좋을 지 생각해 보았다.
아마 범용적인 테스트 코드 구조나 구현 방식이 있을 것이라 생각되지만, 스스로 생각하며 "이렇게 짜면 좋겠다, 저렇게 짜면 좋겠다" 를 생각해보는 것이 많은 도움이 될 것이라 생각해서 개인적인 생각을 담아 테스트 코드를 구현하였다.
특히 이러한 테스트 코드에 대한 고민이 나중에 실무에서 테스트 코드를 작성하기 위해 적응해가는 과정에 큰 도움이 될 것이라 생각한다.
테스트 디렉토리 구조
우선, 내가 생각하는 테스트 디렉토리 구조는 위 그림과 같다.
프로젝트의 디렉토리 구조, 파일 단위를 일치시켜 헷갈리는 부분을 최소화 하는 것이 중요하다고 생각한다.
그리고 단위 테스트, 통합 테스트를 구현할 때 service, repository 등에 대해서는 단위테스트를 작성하고, controller를 통해 전체 API에 대해 통합 테스트를 작성하였다.
다만, controller에도 param, body 등 다양한 문제들이 발생할 수 있기 때문에 controller에도 API 인자를 처리하는 단위 테스트를 구현하면 좋을 것 같다.
테스트 코드 구조
단위 테스트
단위 테스트의 코드 구조는 위 그림과 같이 구성하였다.
ChatServiceTest(파일) -> 채팅 페이지네이션(기능/Nested Class) -> 정상, 오류 ...(테스트 조건, function)
기능과 테스트 조건을 위와 같이 구성한 이유는 하나의 기능에도 다양한 조건이 발생할 수 있으며 이를 포함하는 관계로 설정하는 것이 가독성을 유지하는데 좋을 것 같다고 생각했다.
그 예로 파일채팅 저장의 경우, 1)파일 변환에 실패한 경우, 2) 정상적으로 저장되는 경우로 예외상황에도 잘 처리하는 지를 확인할 수 있도록 하였다.
그리고 단위 테스트이므로, 다른 bean들과 상호작용하는 부분을 Mockito를 통해 의존성을 없애고 격리된 환경에서 테스트를 진행하였다. 하지만, 그만큼 통합 테스트도 철저히 작성해야 될 것이다.
통합 테스트
MockMvc로 API를 테스트 함으로써 통합 테스트를 작성하였다.
WebTestClient, MockMvc, TestRestTemplate 중 고민하였고, WebFlux를 사용하지 않았다는 점, 그리고 MockMvc는 서블릿 컨테이너를 구동하지 않기때문에 효율성이 좋다는 점에서 MockMvc를 사용하였다.
내 생각으로는 reactive 스택을 사용하는 경우 WebTestClient, 그리고 더욱 실제에 가까운 환경을 테스트 하려면 TestRestTemplate를 쓰지 않을까 싶다.
다시 본론으로 넘어와 코드의 구조는 이전 단위테스트처럼 Controller의 기능 - 테스트 조건으로 구성했다.
// #controller#ChatController#sendMessage
@Nested
class 채팅_전송{
@Test
void 정상_채팅_전송() throws Exception{
//given
ChatRequest chatRequest = new ChatRequest(1L, "sender1", "TEXT", "chat test");
String requestJson = jsonConverter.convertToJson(chatRequest);
//when
MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/chat/send")
.contentType(MediaType.APPLICATION_JSON)
.content(requestJson))
//then
.andExpect(status().isCreated())
.andExpect(jsonPath("$.result").value("SUCCESS"))
.andReturn();
String content = result.getResponse().getContentAsString();
System.out.println("result : " + content);
}
}
이런 식으로 구성했는데 요청에 대한 상태, json 데이터의 result 값을 통해 테스트 결과를 검증하였다.
하지만, response 데이터에 대해서도 assert를 통해 확인하면 더욱 좋을 것 같다.
단위 테스트/ 통합 테스트를 하며 아쉬운 점은 비즈니스 로직과 테스트 코드를 병행해서 개발했다면 더 높은 커버리지로 테스트를 작성할 수 있었을 것이라고 생각한다. 특히 예외 상황에 대한 부분을 테스트 코드로 잘 커버하는 것이 중요하다고 생각하는 데 그부분이 많이 아쉽게 느껴진다.
그리고, 테스트 조건에 대한 명명이 아쉬운 것 같다.
테스트 코드에 대해 게을러지지 않고 오히려 더 많은 노력을 기울여야 겠다는 생각이 매우매우 많이 들게 되었다.
결론
테스트 코드의 중요성을 항상 알고 있었지만 몸으로 와닿은 것은 얼마 되지 않은 것 같다.
그래서 테스트 코드를 작성해보았지만, 잘 작성하기 많이 어렵고 앞으로 어떻게 짜야할 지 더 많은 고민이 필요한 것 같다.
특히 글을 쓰며 느낀건데, 테스트 함수명에 대한 부분과 다양한 조건에 대한 코드 커버리지가 많이 떨어지는 것을 깨닫게 되었다.
앞으로는 테스트 코드를 상세히 작성하고 CI에 적용해보는 듯 더욱 성장하기 위해 노력할 것이다
'프로젝트 > WebRTC - studyhub' 카테고리의 다른 글
[WebRTC] 마이크로서비스 간 gRPC 통신 - 개발편(2) (0) | 2023.11.09 |
---|---|
[WebRTC] 채팅 서버 - 채팅 메시지 순서 보장(카프카 순서 보장) (2) | 2023.11.03 |
[WebRTC] 마이크로서비스 간 gRPC 통신 - 개발편(1) (0) | 2023.08.16 |
[WebRTC] 팀 프로젝트 개요 (0) | 2023.04.09 |