Post

TDD란?

예전에는 프론트엔드가 복잡하지 않아 프론트엔드 테스트를 잘 진행하지 않았다.

그러나 프론트엔드의 중요성이 강조되고, 백엔드의 다양한 기능들이 프론트엔드로 옮겨오면서 프론트엔드가 점점 더 중요해지고, 프론트엔드를 관리 할 필요성이 생기기 시작했다.

이렇게 프론트엔드 관리와, 프론트엔드 코드의 퀄리티의 중요성이 대두 되면서 프론트엔드 테스팅도 같이 주목받기 시작하였다.

TDD란?

TDD란 Test Driven Development의 약자로 ‘테스트 주도 개발’이라고 한다. 테스트 주도 개발(TDD)은 소프트웨어를 개발하는 여러 방법론 중 하나이다.


제품이 오류 없이 정상 작동하는지 확인하기 위해 모든 코드는 프로그래머가 작성하고 나서 테스트를 거치게 된다.

TDD에서는 제품의 기능 구현을 위한 코드와 별개로, 해당 기능이 정상적으로 움직이는지 검증하기 위한 테스트 코드를 작성한다.

이를 통해 테스트가 실패할 경우, 테스트를 통과하기 위한 최소한으로 코드를 개선한다. 최종적으로 테스트에 성공한 코드를 리팩토링 하는 과정을 거친다.

TDD의 3가지 단계

image

TDD 사이클

  • Red: 실패하는 테스트 코드를 작성한다. 이 때, 컴파일 조차되지 않을 수 있다.
  • Green: 가능한 빠르게 테스트 코드가 통과하게끔 수정한다. 이 때 어떠한 죄악을 저질러도 좋다.
  • Refactor: 이전 단계를 거치며 발생한 코드의 중복, 매직 넘버 등을 제거한다.




테스트 유형

1. Static Test

정적 테스트(Static Test)는 코드를 실행시키지 않고 테스트를 하는 것을 말한다. 정적 테스트를 하면 Type 에러나 Reference 에러와 같은 개발자의 실수로 인해 발생하는 에러를 미연에 방지할 수 있다.

프론트엔드의 Static Test ESLint 를 활용하여 사용하지 않는 변수를 찾거나 Typescript 로 함수의 인자로 받는 파라미터의 타입 검사를 하는 것이 정적 테스트에 포함된다.

2. Unit Test

단위 테스트(Unit Test)는 각 모듈을 단독 실행 환경에서 독립적으로 테스트하는 것을 말한다.

프론트엔드의 Unit Test 단일 컴포넌트나 단일 서비스가 될 수 있습니다. 특정 컴포넌트를 렌더링해서 깨지지 않는지 확인하는 것을 예로 들 수 있다.

3. Integration test

통합 테스트(Integration test)는 두 개 이상의 모듈이 실제로 연결된 상태를 테스트하는 것을 말한다.

그리하여 모듈 간의 연결에서 발생하는 에러를 검증할 수 있으며, 단위테스트보다 비교적 넓은 범위에서 테스트하기 때문에 리팩토링에 쉽게 깨지지 않는 장점이 있다.

프론트엔드의 Integration Test UI와 API 간의 상호작용이 올바르게 일어나는지, 또는 state에 따른 UI의 변경이 올바르게 동작하는지를 확인하는 것으로 생각해볼 수 있다.

4. E2E Test

E2E 테스트는 실제 사용자의 입장 및 환경에서 테스트하는 것을 말한다.

프론트엔드의 E2E Test 실제 브라우저를 실행해서 테스트하는 것을 말하며, 커버리지가 높고 실제 상황에서 발생할 수 있는 에러를 검출할 수 있단 장점이 있다.




프론트엔드 관점의 테스트

1. 테스트 대상

프론트엔드에서 테스트의 대상은 다음과 같이 크게 3가지(시각적 요소, 사용자 이벤트 처리, API 통신)를 생각해 볼 수 있다.

테스트 대상 1) 시각적 요소

프론트엔드 개발자는 디자이너로부터 전달받은 디자인을 보고 HTML로 마크업을 한 뒤 CSS로 컴포넌트에 스타일을 입히는 작업을 수행한다.

  • 스냅샷 테스트: HTML 구조가 의도한 대로 나타나는지를 테스트 대표적인 도구: Jest

  • 시각적 회귀 테스트: HTML에 CSS를 더해 컴포넌트가 실제로 브라우저에서 렌더링 되는 모습이 의도한 대로 나타나는지를 테스트 대표적인 도구: Chromatic

테스트 대상 2) 사용자 이벤트 처리

프론트엔드 개발자는 사용자의 마우스, 키보드 등의 입력 이벤트를 적절한 이벤트 핸들러로 처리하는 작업을 담당한다.

  • 자바스크립트 API 또는 React와 같은 라이브러리에서 제공하는 테스트 유틸리티를 활용하여 이벤트를 시뮬레이션하여 테스트

  • E2E 테스트를 통해서 실제로 브라우저상에서 이벤트를 발생시킬 수 있다.

테스트 대상 3) API 서버 통신

프론트엔드 개발자는 브라우저 API 또는 라이브러리를 활용하여 API 서버와 통신하고 애플리케이션 상태를 동기화하는 작업을 수행한다.

  • 실제 API 서버를 이용하는 방법이 있으며 이 방법은 E2E 테스트에서 주로 사용된다.

  • 테스트 API 서버를 구축하거나 API client를 모킹하는 방법으로 Jest를 활용하면 모듈을 간단한 방법으로 모킹할 수 있다.


2. 테스트 환경

프론트엔드 환경은 테스트 코드가 어디에서 실행되는지에 따라서 브라우저 환경과 Node.js 환경으로 구분된다.

테스트 환경 1) 브라우저 환경
  • 브라우저 환경에서 테스트 코드를 실행하면 모든 Web API에 접근할 수 있단 것이 가장 큰 장점이다. 또한 서로 다른 브라우저에서 테스트 할 수 있기 때문에 브라우저 호환성 및 기기 호환성 테스트도 진행할 수 있다.

  • 브라우저의 프로세스가 Node.js 프로세스보다 무겁기 때문에 실행 속도가 느리다는 단점이 존재한다.

  • 브라우저를 실행해야 하므로 대부분의 경우 브라우저 런처를 별도로 설치해야 한다는 제약이 있다.

테스트 환경 2) Node.js 환경
  • 테스트 코드를 Node.js 환경에서 실행하는 것은 브라우저 환경보다 속도가 빠르다는 장점이 있습니다.

  • 브라우저에서 제공하는 Web API, DOM 접근 API를 사용할 수 없다는 단점이 존재한다. 이러한 문제를 극복하기 위해 Jest와 같은 테스트 도구들은 jsdom처럼 DOM을 가상으로 구현하는 라이브러리를 활용한다.

  • 여전히 페이지 내비게이션이나 레이아웃과 같은 것들은 테스트할 수 없다는 제약이 있다.


렌더링, 내비게이션 등 브라우저의 실제 동작을 테스트해야 하는 경우 브라우저 환경에서 테스트하고, 그 외의 경우 Node.js 환경에서 테스트하는 것을 권장하고 있다.



3. 테스트 도구

Node.js 환경에서 실행할 수 있는 여러 자바스크립트 테스트 도구를 찾아보았고 React 공식 문서에서 권장하는 테스트 도구인 testing-library와 Jest 중 더 많이 사용되고 있는 Jext에 대해 알아보았다.

Jest

Jest는 페이스북에서 개발한 자바스크립트 테스팅 프레임워크이다.

Jest를 활용하면 프론트엔드 뿐만 아니라 Node.js 환경에 구축된 백엔드 애플리케이션도 테스트할 수 있고 단언(assertion)뿐만 아니라 모킹, 스냅샷 테스팅, 코드 커버리지 등 다양한 API를 제공한다.

Jest를 활용한 테스트 방법은 –게시글을 통해 게시글을 통해 확인할 수 있습니다.




📑 참고 자료

[간단정리] CSR vs SSR 특징 및 차이

서버사이드 렌더링 (개발자라면 상식으로 알고 있어야 하는 개념 정리 ⭐️)

Next.js의 Hydrate란?

[한글 번역] React Query - SSR (Using Next.js)

This post is licensed under CC BY 4.0 by the author.