Archive

React.js Test

|

React.js Test


  1. Test Rules

    • Don’t test the library : 라이브러리 자체를 테스트하지 마라 예를 들어, axios를 사용하는 경우 HTTP Request Fail이 일어난 경우 인터넷의 문제이지 axios 라이브러리의 문제가 아니라는 것
    • Don’t test complex connections : 복잡한 컴포넌트 관계를 테스트하지 마라 하나의 컴포넌트가 제대로 렌더링이 되는지, props가 잘 전달되는지 등을 테스트하되, 복잡하게 연결된 연결고리 자체를 테스트하지 말라
    • Do test isolated units : 고립된 유닛들을 테스트하라 리듀서의 function, 컴포넌트의 function 등을 테스트해라
    • Do test your conditional outputs : 조건부 산출물을 테스트하라 조건부로 화면이 나왔다 들어갔다 하는 것들을 테스트해라
    • 테스트에는 명확한 규칙이 없고 상황과 때에 따라 언제든 바뀔 수 있음을 명시


  2. Testing

    • AirBnB에서 배포한 enzyme, create-react-app에 내장된 jest 등 테스트 툴들이 있다
    • jest는 react만을 위한 테스트 툴이 아니라 javascript 테스트 툴이다
    • react-test-renderer 패키지는 react 컴포넌트를 순수 js 객체로 렌더링하는데 사용할 수 있는 렌더러를 제공한다. act export로 브라우저 환경과 비슷하게 테스트를 진행할 수 있다
    • enzyme-adapter-react-16 : enzyme을 사용하기 위한 라이브러리, react 17 공식 adapter는 아직 안나온듯하다
    • npm install –save-dev enzyme, react-test-renderer, enzyme-adapter-react-16
    import React from 'react';
    import { configure, shallow } from 'enzyme';
    import Adapter from 'enzyme-adapter-react-16';
    import NavigationItems from './NavigationItems';
    import NavigationItem from './NavigationItem/NavigationItem';
       
    configure({ adapter: new Adapter() });
       
    describe('<NavigationItems />', () => {
      let wrapper;
       
      beforeEach(() => {
        wrapper = shallow(<NavigationItems />);
      });  
           
      it('인증되지 않은 사용자 접속시 2개의 <NavigationItem />이 렌더링 되어야함', () => {
        expect(wrapper.find(NavigationItem)).toHaveLength(2);
      });
           
      it('인증된 사용자 접속시 3개의 <NavigationItem />이 렌더링 되어야함', () => {
      	// wrapper = shallow(<NavigationItems isAuthenticated />)와 같다
        wrapper.setProps({ isAuthenticated: true });
        expect(wrapper.find(NavigationItem)).toHaveLength(3);
      });
    });
       
    
    • configure 메소드로 react 버전16을 사용하고 있음을 명시한다. enzyme은 react 15와 16에서 다르게 동작하기 때문
    • describe와 it은 jest의 메소드이다. describe는 하나의 테스트 그룹이고, it은 그 안의 작은 단위 테스트이다.
    • describe와 it의 첫번째 항목에 적은 문자열이 테스트 항목이 된다
    • enzyme에는 크게 3가지 메소드가 있다
      • shallow : 얕은 수준의 컴포넌트를 메모리 상에 렌더링, shallow, 단일 컴포넌트 테스트
      • mount : HOC나 자식 컴포넌트까지 전부 렌더링, deep, 다른 컴포넌트와의 관계
      • render : 컴포넌트를 정적 html로 렌더링, 브라우저에서 html로 어떻게 되는지 테스트
    • expect jest의 메소드로 테스트값과 예상값이 일치하는지 여부를 판단한다
    • 위의 코드의 첫번째 it은 NavigationItems가 2개의 NavigationItem을 갖는지를 판단했다
    • beforeEach() 메소드는 테스트 전 수행할 내용을 적는다. afterEach() 메소드도 있다
    • setProps(), setState()로 props나 state를 세팅하는 것도 가능하다


  3. Test Reducer

    • Redux의 action, connect, action creator의 모든 관계를 test하는 것은 비효율적이다
    • 라이브러리의 실행 자체는 테스트 대상이 아니다
    • 리듀서는 pure한 javascript function이므로 jest로 테스트가 가능하다
import reducer from './auth';
import * as actionTypes from '../actions/actionTypes';

describe('auth reducer', () => {
  it('should return initial state', () => {
    // 리듀서의 초기 state값 테스트
    expect(reducer(undefined, {})).toEqual({
      token: null,
      userId: null,
      error: null,
      loading: false,
      authRedirectPath: '/',
    });
  });

  it('should store token upon login', () => {
    // 로그인시 리듀서의 token 저장 여부 테스트
    expect(
      reducer(
        {
          token: null,
          userId: null,
          error: null,
          loading: false,
          authRedirectPath: '/',
        },
        { // 로그인 성공시 token,id 저장
          type: actionTypes.AUTH_SUCCESS,
          idToken: 'some-Token',
          userId: 'some-userId',
        }
      )
    ).toEqual({
      token: 'some-Token',
      userId: 'some-userId',
      error: null,
      loading: false,
      authRedirectPath: '/',
    });
  });
});


위는 간단한 사용법 예시이고 언제나 그렇듯, 공식문서를 참고하자

  • Jest Docs: https://facebook.github.io/jest/
  • Enzyme API: http://airbnb.io/enzyme/docs/api/



참고 자료


reactjs.org - 공식홈페이지

Udemy - React The Complete Guide

React 테스트 - zerocho