임팩트: 팀 테스트 작성 가이드 — 외재화 사다리 최상위(위임 가능한 워크플로우)


AS-IS

  • 테스트 코드가 존재하지 않아, 리팩토링 한번에도 사이드 이펙트를 걱정하게 됩니다.

TO-BE

<details> <summary>조언 및 생각</summary>

  • 테스트 코드를 작성하기 전 명확한 코드의 목적성과 단위를 정하고, 툴을 정하는게 좋을 것 같습니다.
  • css 까지는 고려할 필요가 없습니다. jest의 스냅샷 테스트 만으로도 E2E 테스트는 충분하다고 봅니다. (그리고 시각적 회귀 테스트 cypress는 너무 느리고, 요구사항이 급격하게 들어오는 지금 상황에서는 테스트 코드를 수정하는 것 조차 큰 리소스일 수 있습니다.)
  • 그렇다면 스냅샷으로 side effect에 대한 검증이 이루어질 수 있나? ⇒ 있습니다. 이건 통합테스트에 대한 개념입니다.
  • 시각적 회귀 테스트를 사용할 수 없습니다. UI는 전적으로 퍼블리셔에서 관리하므로, css 보다는 DOM의 render에 초점을 두고 테스트를 작성하는 것이 우선입니다.
  • 한번 구현되고 잘 변경되지 않는 단위를 우선적으로 작성합니다. 자주 변경되는 메인 페이지 단위는 크게 유효하지 않을 것 같습니다.
  • 기획 요구사항이 크게 변경되지는 않지만, 조그만한 변경 건들로 리팩토링이 필요한 컴포넌트에 한해서 우선 작성합니다.
  • 체험단 리뷰, 일반 구매 리뷰는 그에 적합한 예제라고 봅니다.
  • 테스트코드를 짜기 어려운 컴포넌트라면 결합도가 너무 높지 않은지 의심해볼 필요가 있습니다.
  • given when then 전략

은정님 조언

  • 주어진 기획단위로 큼직큼직하게
  • 디스플레이, 데이터 검증, 사용자 반응 중 가장 중요한 feature의 요소가 뭔지 고민하고 짜기 </details>

테스트 목적

🛡️

리팩토링 안정성

수정 시 사이드 이펙트를 QA 의존 없이 즉시 확인, 적극적 리팩토링 가능

🔧

유지보수성 개선

변경 전후 렌더링 결과물 차이를 즉시 비교 가능

📋

히스토리 문서화

테스트 코드 자체가 요구사항 히스토리 역할 수행

리팩토링의 안정성

컴포넌트 수정이 요구될 때마다 코드만으로 히스토리를 모두 파악하기 힘들고, QA 의존도가 높습니다. 안정적인 리팩토링 환경을 통해 적극적인 리팩토링 시도를 할 수 있습니다.

유지보수성 개선

테스트 코드를 반영하기 전에 비해, 이전 코드와 변경된 코드의 요구사항에 따른 렌더링 결과물이 어떻게 바뀌는지 바로 확인 가능합니다.

히스토리 문서화

테스트 코드 자체로, 해당 요구사항에 대한 히스토리를 알 수 있습니다.

도입 방향

Cypress 시각적 회귀 테스트

장점

  • 브라우저 단에서 운영 API로 검증 가능
  • 실제 사용자 환경과 동일

고려할 점

  • 런타임이 매우 길어 자동화 시 개발 환경 영향
  • CSS 검증 우선순위 낮음
  • 퍼블리셔 관할 UI 변경이 잦아 유지 비용 높음

Jest 스냅샷 테스트 (채택)

장점

  • 실행 속도 빠름
  • 렌더링 결과물만 비교하여 가볍게 운용
  • 레퍼런스 풍부
  • vue-test-utils 공식 지원

고려할 점

  • CSS/시각적 변경 검증 불가
  • defineOptions 미지원으로 삭제 필요

스냅샷 테스트

cypress를 통한 시각적 회귀 테스트와 jest를 통한 스냅샷테스트에 대해 고민했습니다. 시각적 회귀 테스트를 하면 브라우저 단에서 직접 운영하는 api로 모든 서비스를 검증할 수 있다는 장점이 있지만, 시각적 회귀 테스트의 런타임 시간이 너무 길기 때문에 자동화까지 고려할 시 전체적인 개발 환경에 영향이 있을 것으로 판단했습니다. px 단위의 css에 관련된 검증의 우선순위는 높지 않다고 생각해 렌더링 결과물만 비교하고 테스트코드 실행이 빠른** **스냅샷테스트를 적용했습니다.

추후, UI 관련 테스트가 필요할 경우 해당 feature에 한하여, 시각적 회귀 테스트를 적용하는 것도 좋을 것 같습니다. ex) FAB

jest 사용 이유

스냅샷 테스트의 경우, ava, jest 두 가지를 활용할 수 있는데 jest가 ava보다 2년 전에 나온 것에 비해 버전이 17정도가 높아 업데이트를 더 자주하여 안정성이 높을 것이라 판단했습니다. jest는 1~2 달 간격으로 관련 라이브러리들이 업데이트되고 있고 무엇보다 대중적인 테스트 툴로 레퍼런스가 많고 관련 학습자료들이 많아 jest를 테스트 툴로 활용하였습니다.

snapshot을 지원하는 vue 라이브러리의 경우 vue-test-utils 가 vue의 공식 메서드를 모두 지원하고 있으면 snapshot 메서드를 제공해줍니다. (vue 공식문서에서 제공하지 않는 메서드는 테스트 시 에러가 발생합니다. 예. defineOptions)

통합테스트, E2E 테스트 우선 적용

단위테스트를 하기에는 주객이 전도되는 상황이 염려되었고, 최소한의 테스트 목적이 해소될 수 있는 코드만 구현하도록 통합테스트, E2E 테스트만을 고려하여 작성했습니다. 추후 테스트를 작성할 컴포넌트에서 UI, 데이터 검증, 사용자 반응 중 가장 중요한 feature의 요소에 대해 단위 테스트를 추가하는 방향이 좋을 것 같습니다.

공유할 내용

  • jest를 활용한 단위 테스트, 통합테스트, E2E 테스트를 할 수 있도록 환경세팅을 완료했습니다. cypress에 대한 환경설정은 하지 않았습니다.
  • jest에서 컴포넌트를 테스트할 경우 @vue-test-utils를 사용하는데, defineOptions가 vue3에서 공식적으로 지원하지 않는 함수로, @vue-test-utils에서도 지원하지 않습니다. 테스트하는 컴포넌트는 defineOptions 삭제 후, router가 필요할 때만 router에 name을 설정합니다.
  • 테스트 환경은 optinal, composition으로 작성된 컴포넌트 모두 테스트 가능합니다.

테스트 방법

테스트 방법은 스냅샷 테스트를 기준으로 설명 드리겠습니다. 스냅샷으로 단위, 통합, E2E 테스트 모두 가능합니다. (단위 테스트는 스냅샷이 아닌 jest만을 사용해 테스트하는 것을 권장합니다.)

추가적인 테스트코드 작성 방법은 Commit d9e348bf: [SCRUM-5267] 설명 주석 추가의 주석을 참고하시기 바랍니다.

테스트할 컴포넌트 선정

먼저 테스트할 컴포넌트를 선정합니다. 예제를 들어서 설명드리겠습니다.

Test.vue

저희 팀의 compostion 컴포넌트 작성 규칙에 맞게 작성한 코드입니다. state, props, vuex의 요소가 들어있습니다.

테스트 파일 생성

test 폴더 하위에 **[컴포넌트명].test.ts **으로 생성합니다.

Test.test.ts

운영 중인 store를 목업한 createMockStore를 사용하여 api 호출 등을 하는 필요한 actions만 mockActions로 선언해서 사용하시면 됩니다.

**expect(wrapper.html()).toMatchSnapshot()**을 사용해 snapshot을 추출할 수 있습니다.

테스트 실행

  1. npm run test 실행
  2. 스냅샷 생성 (.snap)
  3. 코드 변경
  4. 재실행 → diff 비교
  5. 의도된 변경이면 jest -u

npm run test or jest 실행

  1. snapshot 생성

  2. snapshot 요약

처음 snapshot을 실행하게 되면 [파일명].test.js.snap 라는 snapshot 파일이 생성됩니다.

Test.test.js.snap

두 번째 테스트(변경 X)

두 번째 테스트 부터는 기존에 생성된 snapshot과 변경된 사항이 있는지 비교합니다. 변경된 사항이 없으니 passed로 표시됩니다.

세 번째 테스트(변경 O)

Test.vue에서 data에 ref로 선언한 sampleData를 changeData로 변경해보겠습니다.

버전관리 플랫폼처럼 렌더링 결과물에서 어떠한 부분이 변경되었는지 확인할 수 있습니다.

여기서 중요한 점은 변경된 부분이 내가 요구했던 결과가 아니라면 기존 snapshot과 변경된 snapshot이 일치하도록 Test.vue 코드를 수정해야하고, 변경되어야하는게 맞다면 snapshot을 업데이트 해주어야합니다.

무작정 snapshot을 업데이트한다면 테스트 자체의 의미가 상실되니 주의해야합니다.

스냅샷 업데이트

**jest -u **실행

이런 방식으로 공통 컴포넌트 기능 추가, 변경 및 리팩토링 시 더욱 안전하게 코드를 구현할 수 있고, 테스트 코드를 통해 요구사항 히스토리에 대한 버전관리를 같이 수행할 수 있을 것이라 기대됩니다.

jest --updatejest -ㅇupdateSnapshotSnapshot

참조 https://lmiller1990.github.io/vue-testing-handbook/ko/#%EC%9D%B4-%EA%B0%80%EC%9D%B4%EB%93%9C%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94

https://heropy.blog/2020/05/20/vue-test-with-jest/

https://blog.canopas.com/vue-3-component-testing-with-jest-8b80a8a8946b#00b6

https://tech.kakao.com/2019/11/27/kakao-business-vue-component-test/