tdd

어떻게 프론트엔드 테스트를 작성할 것인가?

어떻게 프론트엔드 테스트를 작성할 것인가?

단위 테스트

단일 함수의 결괏값 또는 단일 컴포넌트의 상태나 UI나 행위를 검증하는 테스트

무엇을 검증하는가? 공통 컴포넌트를 검증하며 이때 검증하는 컴포넌트는 다른 컴포넌트와의 상호 작용이 없어야 하며 해당 컴포넌트의 내부 비즈니스 로직을 기능 단위로 나눠서 검증한다.

단위 테스트 전략

  • 별도 로직처리 없이 UI만 그리는 컴포넌트는 검증하지 않는다. 컴포넌트의 실제 렌더링 결과를 확인할 수 있는 것이 아니기 때문에 단위 테스트로 검증해도 크게 얻을 수 있는 장점이 없기 때문이다. 따라서 UI 검증은 스토리북과 같은 도구를 통해 검증하자.
  • 간단한 로직 처리만 하는 컴포넌트는 상위 컴포넌트의 통합 테스트에서 검증한다.

한계

  • 여러 모듈이 조합되었을 때 발생하는 이슈는 찾을 수 없다.
  • 앱이 요구사항에 맞게 동작하는지 보장할 수 없다.

통합 테스트

두 개 이상의 모듈이 상호작용하여 동작하는 기능을 검증하며 조합된 컴포넌트의 비즈니스 로직이 올바르게 실행되는지 검증하는 테스트

무엇을 검증하는가? 상태나 데이터를 관리하는 컴포넌트는 앱의 비즈니스 로직에 대한 책임을 갖고 있기 때문에 통합 테스트로 검증하기 좋고 단순 UI 렌더링 및 간단한 로직을 실행하는 컴포넌트까지 한 번에 효율적으로 검증할 수 있다.

통합 테스트 전략

  • 가능한 한 모킹을 하지 않고 실제와 유사하게 검증한다
  • E2E 테스트와 다르게 JSDOM 환경에서 테스트가 진행되므로 외부 모듈이나 API 호출에 대한 모킹이 필요한데 이런 것들을 상위 컴포넌트로 응집한다.
  • 비즈니스 로직이 크고 복잡한 경우 변경 가능성을 고려하여 한 컴포넌트에 모두 작성하는 것이 아니라 나누어 작성하는 것이 좋다.

한계

  • 일부 컴포넌트가 조합되었을 때의 동작만 검증하기 때문에 통합 테스트로 전체 워크 플로우를 검증하긴 어려우며 만약 검증하더라도 외부 모듈이나 API에 대해 굉장히 많은 모킹(또는 스텁)에 의존해야 한다.

스냅샷 테스트

UI 컴포넌트의 렌더링 결과나 함수의 결과를 직렬화해 기록하여 이전의 스냅샷과 비교하는 테스트

무엇을 검증하는가? 스냅샷을 비교해 기존과 다른 변경점을 알아차리고 의도하지 않은 변경을 빠르게 찾는다.

한계

  • 의도하지 않은 스냅샷 업데이트의 가능성이 존재한다.
  • 실제로 렌더링하는 것이 아니기 때문에 스타일이나 레이아웃이 제대로 반영되는지 알 수 없고 CSS가 수정되었을 때 변경 사항을 감지할 수 없다.
  • 스냅샷 업데이트 과정이 필요하기 때문에 TDD 사이클과는 다르게 작성될 수 있다.

시각적 회귀 테스트

실제 컴포넌트를 브라우저에 렌더링 한 후 이미지로 기록하여 비교하는 스냅샷 테스트

무엇을 검증하는가? 스타일이나 레이아웃 변경 사항까지 모두 감지해 검증한다. 스토리북과 같은 컴포넌트 UI 개발 도구를 연동해 좀 더 편리하게 실행할 수 있다. Github Actions를 사용해 워크플로우를 자동화하면 UI 리뷰까지 빠르게 피드백 받을 수 있다.

시각적 회귀 테스트 전략

  • 실제 UI만 렌더링하는 컴포넌트를 대상으로 실행하는 것이 좋다.
  • 크로스 브라우징 또는 스타일 변경으로 UI가 자주 틀어지는 컴포넌트를 검증하자.

한계

  • 대부분 유료 도구가 많아 비용 부담이 존재
  • 직접 구축할 경우 관리 부담이 존재
  • 어떤 이유로 변경 사항이 발생했는지 추론하는 데 많은 시간 소요
  • 실행 시간이 매우 오래 걸리기 때문에 빠른 피드백 받기 어려움
  • CI 연동은 필수이며 개발 단계에서 도입할 수 없어 TDD 사이클 불가능

E2E 테스트

실제 앱을 구동해 전체 소프트웨어 시스템 전반의 흐름을 검증하는 테스트

개발이 완료되어 전반적인 기능 테스트가 가능한 시점에 도입할 수 있다.

유관 부서의 협력이 필요하며 도입을 위한 일정 확보가 필요하다

무엇을 검증하는가? 사용자가 앱을 사용하는 다양한 시나리오를 검증해 프론트엔드부터 백엔드 전반의 상태를 확인한다.

E2E 회귀 테스트 전략

  • 가능한 한 모킹을 하지 않고 테스트를 실행한다.
  • API 호출이 어렵거나 서드파티 라이브러리 또는 외부 앱을 사용하는 특정 상황에서만 스터빙한다.

한계

  • 실행 시간이 오래 걸려 개발 생산성이 저하될 수 있다.
  • 외부 환경 요소로 인해 테스트가 깨질 수 있어 테스트 실행을 위한 관리 비용이 많이 들어간다.
  • 디버깅 시간이 오래 걸린다.
  • 테스트에 영향을 미칠 수 있는 범위가 크고, 이슈의 원인을 찾아 수정하는 데 많은 시간이 소요된다.

단계 별 적합한 테스트

  • 개발 단계 : 단위 테스트, 통합 테스트 (독립적인 모듈이나 비즈니스 로직 검증하며 TDD를 도입할 수 있다. 이때 UI 검증은 스토리북을 사용하면 된다.)
  • 전반적인 기능과 UI 개발 마무리 : E2E 테스트 (워크 플로우 검증)