3 minute read

이 글은 프론트엔드 크루 엽토가 작성했습니다.

서론

프로젝트를 진행하며 개발에 들어가기 앞서, 저희 하루스터디 프론트엔드 팀은 테스트 진행을 어떻게 할지 논의했습니다. 여러 테스트 도구가 있지만, 우리는 storybook, jest 기반으로 react-testing-librarymsw를 사용하기로 했습니다.

먼저 도구를 정하기 전에 논의한 것이 있습니다. 저희는 무엇을 테스트 할지(테스트 대상), 어떻게 테스트를 할지, 그리고 언제 어디서 테스트할지에 대해 논의했습니다. 테스트 코드 또한 리소스이기 때문에 스프린트 단위로 프로젝트를 진행하는 우리 팀은 테스트 커버리지를 높혀 전 범위를 테스트하면 좋겠지만 시간적인 여유가 많이 없기 때문에 테스트 우선순위를 정해야만 했습니다. 어떤 범위까지 테스트할지를 정해야 우리 팀 테스트 전략에 적합한 도구를 고를 수 있다고 판단했습니다. 현재 나와 있는 테스트 툴들이 관심사가 각기 다릅니다. 예를들어 jest는 단위 테스트에 조금 더 적합하고, Cypress는 E2E 테스트에 좀 더 친화적이고 등등 각자의 관심사가 다르기 때문에 이런 논의를 먼저 진행했습니다.

본론

그래서 저희는 무엇을 테스트 할지 이야기했고, 첫 번째 테스트 대상은 유저가 원하는 것을 테스트 하기로 결정했습니다. 즉, 유저의 행위를 중점적으로 테스트 하기로 했습니다. 테스트 코드를 작성하는 이유는 서비스의 안정성을 평가하기 위함이기 때문에, 저희 서비스가 제공하는 기능에 대해 제대로 동작하는지에 대한 테스트가 가장 중요하다고 저희는 생각했습니다. 예를 들어 유저가 하루스터디 Header에 있는 내 스터디란 버튼을 클릭했을 때 내 스터디에 관련된 내용이 뜨게 하는 기능 자체를 테스트하는 것이 중요한 것이지 유저가 관심 없는 부분 즉, 이 버튼을 눌렀을 때 상태가 어떻게 되는지나 버튼이 button 태그로 만들어 졌는지에 대해서는 빠르게 프로덕트를 출시해야하는 입장에서 당장 우선순위가 높지 않다고 판단했습니다.

유저의 행위를 중점적으로 테스트하려면 단일 컴포넌트를 테스트하는 것이 아닌 여러 컴포넌트들이 묶여 서로 상호작용하는 것을 테스트하게 될 것이므로 우리는 페이지 단위의 통합테스트(Integration Test)를 하기로 결정했습니다. 하나의 페이지에서 유저가 할 수 있는 행동을 기준으로 테스트를 작성하면 실제로 내부 구현이 바뀌고, 데이터를 다루는 방식이 바뀌더라도 테스트 코드의 변경 없이 유저에게 일관된 기능 제공을 보장할 수 있기 때문입니다.

사용자 이벤트 처리 중심으로 테스트가 이뤄질테고, 이에 가장 적합한 테스트 도구인 Jest 기반의 React-testing-library를 사용하기로 결정했습니다. React-testing-library는 사용자 관점에서 애플리케이션 테스트하는 것을 강조하고 있고, DOM에 대한 접근을 getByText, getByTestId와 같은 메서드로 쉽게 DOM에 접근하여 테스트 코드를 작성할 수 있다는 장점이 있기에 우리 프로젝트에 적합한 테스트 도구라 생각했습니다.

기능 중에 어떤 버튼을 클릭하면 데이터를 받아와서 화면에 렌더링 시키는 경우가 있을겁니다. 이 경우엔 API와 통신하는 로직을 테스트해야 해야합니다. React-testing-library를 사용하면서 jest를 사용하기 때문에 jest를 이용하여 fetch를 간단하게 모킹하여 테스트 코드를 작성할 수 있지만 Kent C. DoddsStop mocking fetch란 글을 보고 저희는 msw를 사용하기로 결정했습니다. 저희가 생각할 때 Kent C가 말하는 것 중 가장 와 닿은것은 msw가 응답을 mocking하고 설정하기 위한 작업이 fetch mocking하는 것보다 훨씬 간단하고, 실제 서버 응답과 일치시키는 작업도 편리하다는 것이었습니다. 즉, API mocking에 대한 테스트 코드 리소스가 확실히 줄어드는 것이었습니다. 또, msw를 도입하여 API 통신 로직 테스트가 가능하다면 유저의 행위를 테스트할 때 E2E 테스트까지 가능하기 때문에 추후 테스트 커버리지를 넓힐 경우에도 유용하다고 생각했습니다.

msw는 위에 서술한 장점 외에도, 백엔드 팀원들과 병렬적으로 작업을 진행할 때 유용하다는 장점을 가지고 있습니다. 서버측에서 API 개발이 완료되지 않더라도, 명세만 있다면 클라이언트 측에서 mock Data와 mock API를 만들어 간단하게 테스트하며 개발을 병렬적으로 진행할 수 있습니다. 서버측 작업을 기다리지 않아도 명세대로 데이터를 요청하고 받을 수 있기 때문에 작업 시간을 효율적으로 사용할 수 있습니다.

마지막으로 UI 테스트는 어떻게 하는 것이 좋을지 이야기했는데 이 또한 마찬가지로 jest를 이용하여 할 수 있었지만, 시각적으로 UI를 직접 볼 수 있고, 컴포넌트 단위로 스토리를 작성하여 UI 테스트 및 공유할 수 있는 StoryBook을 사용하기로 했습니다. 지금 하루스터디는 프론트엔드 3명과 백엔드 4명이서 협업하고 있습니다. 개발만 하는 것이 아닌 기획도 같이하고 있기 때문에 이런 상황에서 기획한 디자인에 따라 개발한 컴포넌트를 스토리별로 문서화하고 백엔드 팀원들에게 직관적으로 보여줄 수 있다는 장점 또한 있어서 저희는 StoryBook을 사용하기로 했습니다.

이렇게 우리는 무엇을 테스트 하고, 어떻게 테스트 할지 정했습니다. 남은 것은 언제 어디서 테스트를 할지 입니다. 저희 하루스터디 프론트엔드에서는 CI 파이프라인에서 PR 생성 시 github action을 활용해 github가 제공하는 클라우드에서 테스트가 진행될 수 있도록 스크립트를 작성했고, 배포 전 CD 파이프라인에서도 하루스터디 jenkins 서버에서 테스트를 진행하여 테스트 성공여부에 따라 빌드될 수 있도록 스크립트를 작성했습니다. PR 생성 시 테스트를 진행해서 테스트 실패 시 코드가 Merge 되지 않도록 하고 배포 전에는 테스트 실패 시 빌드가 되지 않도록 하여 오류가 있는 상태라면 빌드를 막아 배포되지 않도록 해주었습니다.

결론

지금까지 하루스터디 프론트엔드의 테스팅 도구 선택 과정과 테스팅 전략에 대해 알아보았습니다.

이 외에도 테스트할 범위들은 더 많을겁니다. 성능 테스트라던지 접근성 테스트, 그리고 브라우저 호환성 테스트 등 많은 영역에서 테스트를 할 수 있습니다. 일단 개발에 들어가기 전에는 이 정도만 수립하고 들어가도 괜찮다고 저희는 판단했습니다. 나중에 프로젝트를 진행하면서 위의 서술한 테스트들을 추가하게 된다면 또 포스팅할 예정입니다. 이상 포스팅을 마치겠습니다.