Cometin'

E2E 테스트 시 API mocking이 필요할까?

2023-03-12 at Project category

E2E 테스트 시 API mocking이 필요할까? w/ 영감탱

종단간(이하 E2E) 테스트에서 API mocking이 필요할까? 에 대한 고민의 결과와 배경을 공유합니다.

API mocking?

배경을 설명하기 전에

본문에서 다루는 API mockingMSWCypress의 intercept 등을 이용해 네트워크 리퀘스트를 가로채어 API가 반환하는 값을 사용하는 것이 아닌 클라이언트 개발자 정한 값을 반환하도록 하는 행위를 뜻한다.

배경

디프만 과정에서 개발하고, 과정이 끝난 후 약 1년이 지난 지금까지 운영, 개발하고 있는 영감탱 프로젝트에서 발생한 문제가 고민을 떠올린 배경이다.

영감탱에는 Cypress를 사용한 E2E 테스트 케이스가 존재한다.

배경의 배경

영감탱을 지속적으로 운영할 수 있었던 이유 중에 하나가 사용자의 관심인데, 우연치 않게 바이럴이 되어 (내 기준에서) 많은 사용자들이 사용하는 것을 우리 모두가 알게 되었다.

영감탱 사용자 지표

이것과 함께 신년 버프(?)가 도화선이 되어 미뤄두었던 대대적인 개선을 진행하게 되었다.

많은 개선 지점 중의 하나가 프로덕션 환경과 개발 환경의 API 분리였는데, 질문의 배경은 이때 떠오르게 되었다.

API 의존

E2E 테스트 케이스 실패

API 이중화가 완료된 이후 클라이언트의 CI에서 통과하지 못하는 E2E 테스트 케이스가 생겼다.

확인한 결과 개발 서버가 잠시 내려간 상태여서 발생한 이슈였고

이 지점에서 API mocking을 할까? 라는 생각이 떠올랐다.

장단점

물론 서버의 의존성을 갖는 것이 부정적이기만 하다면, 그냥 mocking을 하면 된다.

하지만 트레이드오프가 있는 선택이라고 생각되었기에 그 자리에서 떠오른 장단점을 팀원들과 의논해 보았다.

영감탱 슬랙 스레드

팀원들과 의논하고, 여러 가지 검색해 본 결과를 정리하자면 다음과 같다.

API mocking의 장점

  • 서버 상태에 의존하지 않는다.

이후 단점으로도 기술하겠지만, 장점의 측면만 보자면 의존하지 않아 테스트 케이스의 신뢰도가 전적으로 클라이언트에 있게 되는 것이다.

좋은 테스트 케이스를 판단하는 지표 중 하나가 신뢰도라고 생각되는데, 그 신뢰도가 클라이언트에 집중되어 있으면 테스트 케이스가 통과하지 못하였을 때 확인과 변경에 쉽게 대처할 수 있을 것이라 생각되었다.

  • 빠르다.

Cypress 공식 문서에서 소개하는 것처럼 API를 mocking하게 되면 실제 서버의 응답을 기다릴 필요가 없어 테스트 케이스가 더욱 빨리 실행되게 된다.

  • 데이터베이스가 오염되지 않는다.

만약 E2E 테스트에서 글을 작성하거나, 삭제하는 등의 데이터베이스 조작이 존재한다면, 테스트가 실행될 때마다 필요 없는 데이터들이 적재되게 된다.

하지만 API mocking 시에는 필요 없는 데이터들이 적재되지 않는다.

API mocking의 단점

  • 서버 상태에 의존하지 않는다.

장점과 동일하게 단점으로도 작용되며, 가장 큰 단점이라고 생각되었다.

의존하지 않는다는 것을 다른 말로 풀어보자면 '실제 API와 일치한다는 보장이 없다.' 이기 때문이다.

E2E 테스트가 의미하는 최종 사용자의 행위를 테스트한다는 것에 반하는 단점이라 생각되었다.

  • 변경에 대응할 지점이 늘어난다.

만약 API 인터페이스에 변경이 생겼다면, 해당 API를 mocking한 코드에도 변경이 필요해진다.

API 인터페이스에 변경이 생겼을 때부터 클라이언트에 변경이 필요해지는 것은 맞지만, 변경에 대응해야 할 지점이 늘어나는 것은 추가적인 리소스의 소모라고 생각되었다.

  • 상대적으로 빠르지 않고, 데이터베이스가 오염된다.

위 장점에서 언급한 것과 정확히 반대의 이유이다.

선택

팀원들의 다양한 경험과 의견을 바탕으로 의논한 결과 우리는 mocking을 하지 않기로 결정했다.

선택의 이유는 다음과 같다.

E2E 테스트의 이유

우리가 E2E 테스트를 사용하는 이유는 '최종 사용자의 행위를 점검한다'라는 것에 있는데, API를 mocking하게 되면 그 이유가 퇴색된다고 판단하였다.

그렇기에 서버 상태에 의존하면서 실제 API를 사용하는 것이 더욱 최종 사용자와 비슷한 행위를 테스트할 수 있는 방법이라 생각되었다.

이중화

테스트 환경에서 프로덕션 API를 사용하는 것이 아닌, 개발 API를 사용함으로써

API mocking의 장점으로 꼽았던 '데이터베이스의 오염'이 우리 애플리케이션에서는 필요한 장점이라 생각되지 않았다.

물론 개발 API를 사용하는 것이 위에서 꼽은 이유에 반하는 선택이라고 생각할 수 있을 것 같다.

하지만 실제 최종 사용자의 행위의 비슷함과 트레이드오프를 고려했을 때 최적의 선택이라고 판단하였다.

리소스

해당 고민의 결과를 반영해야 하는 '영감탱'은 사이드 프로젝트로써,

나를 포함한 모든 개발자, 디자이너분들이 풀타임으로 참여하는 것이 아닌 여가 시간을 활용해서 운영하고 있다.

이런 상황에서 변경에 대응해야 할 지점을 늘려 추가적인 리소스가 소모되는 방향은 지양하는 것이 좋을 것 같다고 의견이 모아졌다.

하지만

설계, 기술의 도입 등 소프트웨어를 다루는 많은 부분에서 트레이드오프를 고려해야 하듯

API mocking을 도입하지 않는 것이 꼭 좋은 선택은 아니라고 생각된다.

참조한 문서들에서 부분적으로 도입하는 것도 제시하며, 분명히 필요한 상황이 있을 것이라 생각되기 때문에

이 글을 읽는 분들에게 본인의 상황에 맞는 방향을 선택하길 추천하고 싶다.

참조

부록 - Playwright

다른 사이드 프로젝트인 아맞다에서 사용하고 있는 Playwrighttest generator를 통해 상당한 DX를 제공하고, Cypress에 비해 상당히 빠른 실행 시간을 보여주어 마이그레이션을 고민하고 있었다.

원래는 위 장점들에 비해 Cypress의 장점을 체감하지 못했는데, 이번 고민의 과정에서 돌이켜 생각해 본 결과

다소 무겁긴 하지만 Cypress가 제공하는 CI와 플랫폼이 강력하다는 것을 체감하게 되었다.

cypress 동영상 녹화 기능

그중에서 테스트 케이스의 실행 동영상을 제공해 주어 시각적으로 어떤 부분이 잘못되었는지 확인할 수 있는 것이 크게 장점으로 생각되었다.

느린 실행 속도는 Sorry cypress라는 cypress의 유료 기능을 제공하는 도구가 있어 부분적으로 해결할 수 있을 것이라고도 생각되니 도입 혹은 마이그레이션을 생각하고 있는 분들에게 도움이 되길 바란다.

이후에

글을 작성한 지 약 한 달이 지난 지금, API 상태에 따라 테스트 케이스가 실패한 것을 배경으로 서버 개발자님과 다시 이야기를 해보았다.

버그가 없는데 테스트가 깨진다는 어색한 상황에 대해 어떻게 대처해야 할지 의논해 보았는데,

Mocking을 하는 환경과 하지 않는 환경 두 가지 모두를 테스트하면 좋겠다는 결론이 나왔다.


develop 브랜치에 합병할 때 클라이언트에서 작업한 내용이 사이드 이펙트를 불러 일으키는지 확인하기 위해 mocking을 하고,

본문에서 언급한 '최종 사용자의 행위를 점검'을 하기 위해 main 브랜치에 합병할 때 실제 API 환경에서 테스트를 하도록 구분하여 수행하는 것이 우리가 바라는 테스트 범위와 테스트의 신뢰도를 높일 수 있다고 판단되었다.


글을 작성할 때는 두 가지 환경을 분리하여 테스트하는 방법을 생각하지 못했었는데, 이번 의논을 통해 시야가 넓어진 느낌이 들었다.

리소스의 트레이드오프를 고려하지 않는다면 최적이고 최선의 방법이라고 생각된다.

hyesungoh

Personal blog by hyesungoh.

I like to share my knowledge for those who wandering in issue.