유닛 테스트가 꼭 필요한가?

test

Vitest 도입 전 고민… 유닛 꼭 테스트가 필요한가?

유닛 테스트가 필요한지에 대한 생각을 하게 된 이유는, 프로젝트에서 E2E 테스트만 작성하던 중 프로젝트 UI/UX 자체 개편이 예정되었다. UI/UX 개편을 앞둔 상황이라 E2E 테스트 작성 진행을 중단 하게 되었고, 만약 이때 유닛 테스트가 있었더라면 이라는 아쉬움이 생겼다.



유닛 테스트 도입에 대한 우려

React 컴포넌트로 구성된 프로젝트에서 유닛테스트는 유의미한 도움이 될까라는 생각이 항상 들었던 것 같다.

그리고 컴포넌트 내에 구성된 로직들을 별도로 어떻게 분리하는 게 좋은지도 쉽지 않은 포인트였던 것으로 기억한다.

많은 프로젝트들이 대부분 유닛 테스트 없이 잘 운영되고 있고, 테스트를 작성하고 관리하는 리소스에 대한 불안감도 존재한다.

unit-test-necessary-3.png



유닛 테스트 도입 장점

프로젝트 내에 테스트가 있다면 안정성을 포함하여 여러 가지 도움이 되는 부분을 우리는 알고 있다. 코드 수정 시 간단한 실수로 인한 문제를 감지, 리팩토링 시 기존 기능에 대한 검증이 하나의 예로 생각된다.

개인적으로 장점이자 단점이 될 수도 있다고 생각되는 부분은 코드를 자연스럽게(?) 모듈화를 시켜 기능 혹은 관심사를 분리하여 작성하게 된다. 장점이라고 생각한 이유는 기능, 관심사 형태로 코드를 분리하여 로직에 대한 복잡성을 줄여 코드 이해도 및 수정 시 영향을 최소화할 수 있을 것이다. 단점이라고 생각한 부분은 코드를 자연스럽지 못하게 유닛 테스트를 위한 모듈화를 고집하며 작성하게 될 수도 있지 않을까에 대한 우려이다.



유닛 테스트 도입 단점

가장 큰 장벽으로 생각되는 부분은 테스트 작성 및 관리에 대한 시간적 여유로 생각된다. 기획으로 시작된 작업 일정이 밀려있고 진행하다 보면 테스트가 있는 로직과 없는 로직이 섞이고 이후에는 테스트 작성에 대한 우선순위가 점점 밀려나는 상황들도 있었던 것 같다. 이 부분은 돌이켜보면 개인적으로는 나의 귀찮음…도 한 몫 하지 않았나 하는 생각도 든다.

다음은 React 컴포넌트 내에 존재하는 상태 관리, 훅, 이벤트를 포함한 로직들을 유닛 테스트로 어떻게 분리해야 할지에 대한 고민도 있다. 예로 컴포넌트 간 의존성이 존재하는 경우 컴포넌트 설계부터 다시 고민을 하여 테스트를 만들어야 하는데… 테스트를 위해 컴포넌트를 다시 구성하는 것이 배보다 배꼽이 큰 느낌이 들기도 한다.

마지막은 테스트에 대한 믿음인 것 같다. 유닛 테스트를 작성하다 보면 테스트가 정말 성공에 대한 보장인지, 유의미한 테스트인지를 고민하게 되는 상황도 발생하는 것 같다. 예로 a + b 기능 함수를 테스트하는 경우 1, 1 데이터를 넣고 2가 나오는 것을 확인하는 것이 과연 의미가 있는 것인가라는 생각이 들었던 적도 있었다.



유닛 테스트가 필요할까?

위 작성한 내용들을 정리하며 든 생각은 유닛 테스트는 꼭! 필요한 것은 아니지만 프로젝트 내에서의 보험 정도로 생각이 된다. 완벽한 프로젝트는 없듯이 문제를 위한 장치들을 마련해 두는 것이 필수는 아니지만 문제를 최소화하고 대비를 해두는 것은 좋지 않을까?

그리고 요즘 React 프로젝트를 진행하며 컴포넌트들을 조합하여 페이지를 생성해 내는 과정만 반복하다 보니 컴포넌트의 동작에만 초점을 맞추어 개발하고 있진 않았나 하는 생각이 든다. 작업을 진행하는 부분에서 유닛 테스트 작성이라는 옵션이 있다면, 동작을 세분화하여 모듈화하고 로직의 기능을 고민하여 진행하지 않을까(?)라는 개인적인 바램도 생긴다.



어떤 유닛 테스트?

React 프로젝트 내에서 유닛 테스트를 작성한다면 생각되는 요소는 상태 관리, 훅, API 요청 그리고 유틸 함수를 대상으로 유닛 테스트 작성을 목표로 한다. 컴포넌트 랜더링은 빈번한 변경이 가능한 영역으로 생각되고 이벤트 처리와 같이 제어가 쉽지 않은 부분들로 인해 유닛 테스트로 처리하기 쉽지 않을 것으로 예상된다. 랜더링과 이벤트 처리 부분들은 E2E 테스트로 검증한다면 유닛 테스트에서의 아쉬움을 해소 할 수 있을 것 같다.

unit-test-necessary-4.png



Vitest?

프로젝트에 Vitest를 도입하여 유닛테스트를 작성하는 것으로 결정하였고, 여러 장단점과 라이브러리들 비교도 있었지만 여기에서는 Vitest를 도입하게된 이유에 대하여 간단히만 정리해 보겠다.

vite 기반 프로젝트라면 프로젝트 내 vite 설정을 그대로 사용하여 테스트 도입에 대한 오버헤드를 감소시킬 수 있다. 사용 중인 vite 플러그인이 그대로 테스트 환경에서 작동하며 개발 서버와 테스트 환경의 일관성으로 컨텍스트 전환 비용 감소를 노릴 수 있다. 그리고 ESM 기반 실행, 파일 단위 병렬 처리, HMR 지원으로 성능적인 이점을 가져갈 수 있다.



Vitest vs Jest

Vitest 도입전 간단하게 두 가지 테스트라이브러리를 현재 프로젝트에 적용하며 비교해 보았다.

Jest 도입과정 자체는 어렵지 않았지만 적용하며 추가적인 디펜던시 추가가 필요했다.

  • jest
  • ts-jest
  • @jest/globals
  • @types/jest

그리고 Jest 동작을 위한 jest.config.json 설정 추가를 필요로 한다.

vite를 사용하고 있는 프로젝트에서 vitest 도입 자체는 단순히 vitest 모듈 설치 후 테스트를 실행하는 것으로 아주 간단했다. 추가 설정이 필요한 경우 vite.config에서 tests 옵션으로 필요한 설정을 추가할 수 있다.

마지막으로 간단한 함수로 cache를 사용하지 않게 설정 후, 100번 수행하는 테스트로 시간을 확인하였을 때 대략 3배 이상 시간 차이가 나는 것으로 확인하였다.



Jest

unit-test-necessary-1.png

Vitest

unit-test-necessary-2.png

JestVitest
dependencyts-jest @jest/globals @types/jestvite에 설정된 플러그인 함께 사용
configjest.config 파일 추가 필요vite.config 함께 사용
time (동일한 함수)1.429s427ms


In conclusion

아직 프로젝트 내 Vitest를 도입하고 유닛테스트를 작성하기 전이라 결론이라는 항목을 쓴다는 것이 조금은 어색한 느낌이 든다. 테스트에 관해서는 위에서 나의 좁은 견해를 정리한 것보다 훨씬 더 많은 생각과 고민이 필요하다. 한 번씩 주변 개발자분들과 얘기를 나누었을 때도 정확한 정답을 찾을 수 없이 함께 미로에서 길을 찾기 위한 토론 같은 기분이 들었다. 하지만 앞으로도 정답이 아니더라도 그 상황에 최선을 찾기 위해 함께 얘기를 나누는 것만으로도 지금처럼 새로운 도전을 해보고 더 좋은(?) 프로젝트를 만드는 것에 다가갈 수 있지 않을까 한다.

unit-test-necessary-5.png

-How do you approach testing?-