별 개수: 50
속도: 2

JavaScript

웹 개발의 필수 언어

동적인 웹 페이지 구현을 위한 핵심 프로그래밍 언어.

Java

객체지향 프로그래밍

안정적이고 확장성 있는 백엔드 개발의 대표 언어.

HTML

웹의 기초

웹 페이지의 구조를 정의하는 마크업 언어.

React

현대적 UI 라이브러리

효율적인 사용자 인터페이스 구축을 위한 JavaScript 라이브러리.

CSS

웹 디자인의 핵심

웹 페이지의 시각적 표현을 담당하는 스타일 언어.

Spring

자바 웹 프레임워크

기업급 애플리케이션 개발을 위한 강력한 프레임워크.

JavaScript

웹 개발의 필수 언어

동적인 웹 페이지 구현을 위한 핵심 프로그래밍 언어.

Java

객체지향 프로그래밍

안정적이고 확장성 있는 백엔드 개발의 대표 언어.

HTML

웹의 기초

웹 페이지의 구조를 정의하는 마크업 언어.

React

현대적 UI 라이브러리

효율적인 사용자 인터페이스 구축을 위한 JavaScript 라이브러리.

CSS

웹 디자인의 핵심

웹 페이지의 시각적 표현을 담당하는 스타일 언어.

Spring

자바 웹 프레임워크

기업급 애플리케이션 개발을 위한 강력한 프레임워크.

JavaScript

웹 개발의 필수 언어

동적인 웹 페이지 구현을 위한 핵심 프로그래밍 언어.

Java

객체지향 프로그래밍

안정적이고 확장성 있는 백엔드 개발의 대표 언어.

HTML

웹의 기초

웹 페이지의 구조를 정의하는 마크업 언어.

React

현대적 UI 라이브러리

효율적인 사용자 인터페이스 구축을 위한 JavaScript 라이브러리.

CSS

웹 디자인의 핵심

웹 페이지의 시각적 표현을 담당하는 스타일 언어.

Spring

자바 웹 프레임워크

기업급 애플리케이션 개발을 위한 강력한 프레임워크.

TDD/JEST+React Test

JEST, React Testing Library 실제 해보기

lamarcK 2025. 4. 17. 06:23

그렇다면 이제 본격적으로 3,6,9 게임을 하는 컴포넌트를 만들어 보려고 한다.

그렇다면 규칙을 명확하게 세워야한다.

  • 숫자에 3, 6, 9가 들어가는 경우 박수를 친다.
  • 3, 6, 9 가 여러번 들어가면 그 n개 만큼 박수를 친다.

결과적으로 말하자면 3, 6, 9가 들어갔나 판별하기

3, 6, 9의 개수 만큼 박수치기를 해야한다.


1. 1. 3, 6, 9가 들어갈 경우 true 반환하게 하기

typescript
클릭하여 코드 펼치기
  const shouldShowClap = (num: number): boolean => {
    return num.toString().includes('3')|| 
           num.toString().includes('6')|| 
           num.toString().includes('9');
  };
클릭하여 코드 복사

3이나 6이나 9가 들어갈 경우 true를 반환하도록 한다.

혹은 검사해야 하는 숫자가 많다면 some을 사용해서 조건을 확인하는 것이 좋다.

some을 사용할 경우 배열의 요소가 true가 되면 즉시 true를 반환한다.

typescript
클릭하여 코드 펼치기
  const shouldShowClap = (num: number): boolean => {
    return  ['3','6','9'].some((digits) => num.toString().includes(digits))
  };
  
  const shouldShowClap = (num: number): boolean => {
//                     ^매개변수타입^  ^반환타입^
클릭하여 코드 복사

예를 들어 13이라면 이렇게 과정을 거쳐서 boolean을 반환하게 된다.

예: num이 13일 경우
typescript
클릭하여 코드 펼치기
num.toString() // "13"
"13".includes('3') // true
"13".includes('6') // false
"13".includes('9') // false
// 하나라도 true이므로 최종적으로 true 반환
클릭하여 코드 복사
some의 구조
typescript
클릭하여 코드 펼치기

array.some((element) => 조건)

// 둘 다 같은 동작
.some(a => ...)      // 작동하지만 의미가 불분명
.some(digit => ...)  // 이 변수가 숫자의 자릿수를 검사한다는 의미가 명확

// 다른 예시들
.some(item => ...)   // 일반적인 항목을 검사할 때
.some(fruit => ...)  // 과일 배열을 검사할 때
.some(user => ...)   // 사용자 배열을 검사할 때
클릭하여 코드 복사

2. 2. 3, 6, 9가 총 몇개인지 확인하기

결과적으로 박수를 n번 쳐야한다면 이 방식이 더 간단하다. 결국 3, 6, 9의 숫자가 몇개인지 세야하기 때문

typescript
클릭하여 코드 펼치기
const Clap = (num:number) => {
    return num.toString().split('')
              .filter(digit => ['3','6','9'].includes(digit)).length;
}
클릭하여 코드 복사
  1. 받은 숫자를 문자열로 만들기
  2. split으로 문자열을 배열로 만들기.
    • 나누는 기준을 빈 문자열(empty string)로 하면 글자 사이사이를 기준으로 따져서 1글자씩 분리
    • 나누는 기준을 ' ' 공백이나 '/', 'a' 같은 케이스를 사용할 수도 있음
  3. filter가 실행되면서 만들어진 배열을 각각 3, 6, 9만 포함된 배열로 전환함
  4. length로 배열의 길이를 반환함
    • 예를 들어 ['3','6']이 반환됐다면 2

만약 456를 넣는다면 어떻게 될까? 실제로 테스트를 해보면 된다.

 

해당 컴포넌트를 작성해서 export하고

typescript
클릭하여 코드 펼치기
// ClapCounter.tsx
'use client'

export const Clap = (num:number) => {
  return num.toString().split('')
            .filter(digit => ['3','6','9'].includes(digit)).length;
}
클릭하여 코드 복사

테스트 파일에서 임폴트해서 함수를 넣고 사용해본다.

typescript
클릭하여 코드 펼치기
import '@testing-library/jest-dom';
import {Clap} from '@/components/ClapCounter';

describe('Clap 함수 테스트', () => {
  test('숫자 3을 넣었을 때 1을 반환해야 함', () => {
    expect(Clap(3)).toBe(1);
  });

  // 다양한 케이스 테스트
  test('숫자 36을 넣었을 때 2를 반환해야 함', () => {
    expect(Clap(36)).toBe(2);
  });

  test('숫자 5를 넣었을 때 0을 반환해야 함', () => {
    expect(Clap(5)).toBe(0);
  });

  test('숫자 369를 넣었을 때 3을 반환해야 함', () => {
    expect(Clap(369)).toBe(3);
  });
});
클릭하여 코드 복사

 실제 동작이 기대와 동일한지 확인이 가능했다.

혹시 아주 큰 수의 경우 오류가 날수 있는지도 검증 할 수 있다.

만약에 성공 조건을 다르게 한다면 어떻게 될까?

typescript
클릭하여 코드 펼치기
describe('Clap 함수 테스트', () => {
  test('숫자 3을 넣었을 때 1을 반환해야 함', () => {
    expect(Clap(3)).toBe(2);
  });
});
클릭하여 코드 복사

일부러 다른 숫자를 넣었을 경우 fail이 반영된 것을 알 수 있다.

이처럼 다양한 값을 테스트하면서 그 조건까지 사용자가 선택할 수 있다.

만약에 3, 6, 9 를 따지지만 개수가 필요없을 경우엔 최초의 불리안 반환 방식으로 확인을 하면 될 것이다.


3. React Testing Library

하지만 jest 부분만으로는 DOM요소에 대한 검증이 불가능하다. 만약에 실제로 DOM 요소에 대한 검증도 있어야한다면 React Testing Library를 사용해서 DOM 요소를 검증해야한다.

React Testing Library는 실제 브라우저 화면에 시각적으로 렌더링하지 않고, JSDOM(JavaScript로 구현된 가상 DOM 환경)을 사용하여 DOM 노드 트리를 메모리에 생성한다.

 

간단한 얘를 들자면 실제로 버튼을 화면상에서 보여주진 않지만 DOM 구조는 그려서 보여준다.

typescript
클릭하여 코드 펼치기
// 컴포넌트
function Button() {
  return <button className="btn">Click me</button>;
}

// 테스트
test('버튼이 DOM에 존재하는지 확인', () => {
  render(<Button />);
  
  // 이 시점에서 메모리상에 다음과 같은 DOM 트리가 생성됨
  // <button class="btn">Click me</button>
  
  const button = screen.getByText('Click me');
  // button은 실제 DOM 노드를 참조
  console.log(button.nodeType); // 1 (ELEMENT_NODE)
  console.log(button.textContent); // "Click me"
});
클릭하여 코드 복사

앞서 말한 JEST와 리액트 테스팅 라이브러리를 사용한 테스트를 하면 다음과 같다.

typescript
클릭하여 코드 펼치기
// ClapCounter.test.tsx

// React Testing Library 관련 임포트
import { render, screen, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom';
import ClapCounter, { Clap } from '@/components/ClapCounter';

// Jest: 테스트 그룹화
describe('ClapCounter 컴포넌트 테스트', () => {
  // Jest: 개별 테스트 케이스 정의
  test('ClapCounter 컴포넌트 렌더링 확인', () => {
    // React Testing Library: 컴포넌트 렌더링
    render(<ClapCounter num={369} />);
    // React Testing Library: DOM 요소 찾기
    // Jest: 결과 검증 (expect)
    expect(screen.getByText('3')).toBeInTheDocument();
  });

  // Jest: 개별 테스트 케이스 정의
  test('다양한 숫자에 대한 박수 횟수 표시 확인', () => {
    const 테스트케이스 = [
      { input: 369, expected: '3' },
      { input: 123, expected: '1' },
      { input: 555, expected: '0' },
      { input: 936, expected: '3' },
    ];

    // Jest: 반복 테스트
    테스트케이스.forEach(({ input, expected }) => {
      // React Testing Library: 이전 렌더링 정리
      cleanup();
      // React Testing Library: 컴포넌트 렌더링
      render(<ClapCounter num={input} />);
      // React Testing Library: DOM 요소 찾기
      // Jest: 결과 검증 (expect)
      expect(screen.getByText(expected)).toBeInTheDocument();
    });
  });
});

// Jest: 테스트 그룹화
describe('Clap 함수 테스트', () => {
  // Jest: 개별 테스트 케이스 정의
  test('3, 6, 9 개수를 정확히 세는지 확인', () => {
    const 테스트케이스 = [
      { input: 369, expected: 3 },
      { input: 123, expected: 1 },
      { input: 555, expected: 0 },
      { input: 936, expected: 3 },
      { input: 33366, expected: 5 },
    ];

    // Jest: 반복 테스트 및 결과 검증
    테스트케이스.forEach(({ input, expected }) => {
      expect(Clap(input)).toBe(expected);
    });
  });
});
클릭하여 코드 복사

 

그럼 이렇게 작성한 테스트를 직접 터미널에서 실행시켰다. 결과 모두 passed로 기능상 이상이 없음을 알 수 있었다.

실제 컴포넌트를 웹에서 사용해도 정상 작동하는 것을 알 수 있다.

이동