[코드숨] 리액트 3주차 회고-TDD

Dae-Hee·2022년 5월 22일
0

CodeSoom

목록 보기
3/8
post-thumbnail

생소한걸 학습할때, 처음부터 복잡한 생각보단 개념부터 가볍게 접근하자


▪︎ 회고


이번주의 주제는 테스트 코드 작성이였다.
항상 기능개발에 집중하고 테스트 코드 작성을 해볼 기회가 없었다보니,
생소하게 느껴졌고 크게 과제를 풀면서 잘 흡수하지 못한 것 같다.

틈틈히 테스트 코드 작성을 연습할 필요를 느꼈고
이번에 배운 내용을 더 찾아보며 확실하게 정리해야겠다!

* Point
무엇을 어떻게 해야 할까 싶을 땐 테스트 대상을 사용하면 
이런 결과가 나온다부터 시작해 보세요.
복잡한 것 보다는 단순하고 쉬운 것 부터 시작해 보세요. 
그 후에 만약에 이러한 경우라면? 
만약 ~ 이 없다면 테스트를 추가하여 점진적으로 만들어 보세요.

▪︎ Test Rule


  • 자동화된 테스트에서 실패하지 않는 한 새로운 코드를 작성하지 않는다.
  • 테스트 코드에서 중복을 제거한다.

✱ G-W-T

 처음에는 통과하지 못할(RED) 테스트를 작성하고, 
 이 테스트를 통과하게끔(Green) 코드를 작성하고, 
 결과 코드를 최대한 깔끔하게 리팩터링 하는 짧은 주기로 반복
  • Given : 테스트에서 구체화하고자 하는 행동을 시작하기 전에 테스트 상태를 설명하는 부분
    ( 만약 할 일이 있을 때 )
  • When : 구체화하고자 하는 그 행동
    ( List컴포넌트를 렌더하면 )

  • Then : 어떤 특정한 행동 때문에 발생할거라고 예상되는 변화에 대한 설명
    ( 할 일 목록이 렌더링 된다 )


✱ 어떤식으로?

  • Jest, React testing library, plugin context 사용
 npm i -D jest @types/jest babel-jest
 npm i -D @testing-library/react @testing-library/jest-dom
 npm i -D jest-plugin-context

  1. 리액트 테스트 코드 작성 시 바깥쪽 컴포넌트 부터 순차적으로

  2. 컴포넌트의 역할을 파악한 후 알맞는 테스트 코드 작성
    ( 상태관리의 역할인지, 통합의 역할인지... )

  3. describe - context - it 분리 처리

  • describe : 주체 컴포넌트별
  • context : 상황별
  • it : 기능별
 위와 같은 계층 구조로 작성했을때, 
 npx jest --wachAll --verbose 테스트 결과를 문서의 방식으로 확인이 가능하다.
  1. Expect : 테스트를 작성할 때 값이 특정 조건을 충족하는지 확인
 관련 Methods Doc
 https://runebook.dev/ko/docs/jest/expect#expectassertionsnumber

▪︎ Example


할일 목록을 보여주는 컴포넌트에 대한 테스트 코드 작성

작성 전 해당 컴포넌트의 상황과 기능을 먼저 나열하고 작성
  1) 상황 : 목록이 존재함 / 목록이 존재하지 않음
  2) 기능 : 목록 출력 / 단일 행 삭제
import React from 'react';

import { render, fireEvent } from '@testing-library/react';

import List from './List';

// * 리스트 컴포넌트에 대한 Test
describe('List', () => {
  // * jest에서 제공해주는 예시 함수
  const handleClickDelete = jest.fn();

  // * 상황, 기능별 반복되는 렌더 수행 함수화 (리펙터링 단계에 작성)
  function renderList(tasks) {
    return render((
      <List
        tasks={tasks}
        onClickDelete={handleClickDelete}
      />
    ));
  }
  
  // * context 계층-상황 (목록이 존재하는 상황) 
  context('with tasks', () => {
    const tasks = [
      { id: 1, title: 'Task-1' },
      { id: 2, title: 'Task-2' },
    ];
    
    // * it 계층-기능 (목록 출력 기능 확인)
    it('renders tasks', () => {
      const { getByText } = renderList(tasks);

      expect(getByText(/Task-1/)).not.toBeNull();
      expect(getByText(/Task-2/)).not.toBeNull();
    });
    
    // * it 계층-기능 (데이터 삭제 기능 확인)
    it('renders "완료" button to delete a task', () => {
      const { getAllByText } = renderList(tasks);
      
      // * 키워드가 중복되는 다수의 Element는 getAllByText 사용
      const buttons = getAllByText('완료');

      fireEvent.click(buttons[0]);

      expect(handleClickDelete).toBeCalledWith(1);
    });
  });

  // * context 계층-상황 (목록이 존재하지 않는 상황)
  context('without tasks', () => {
    it('renders no task message', () => {
      const { getByText } = renderList([]);

      expect(getByText(/할 일이 없어요!/)).not.toBeNull();
    });
  });
});

References

https://marocchino.net/2016/12/04/about-rspec/
https://ko.javascript.info/testing-mocha#ref-888

지금 마음가짐을 유지하고 끝까지 최선을 다해서 성장하길!🔥

0개의 댓글