React.js Test
21 Feb 2021 | ReactReact.js Test
-
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 : 조건부 산출물을 테스트하라 조건부로 화면이 나왔다 들어갔다 하는 것들을 테스트해라
- 테스트에는 명확한 규칙이 없고 상황과 때에 따라 언제든 바뀔 수 있음을 명시
-
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를 세팅하는 것도 가능하다
-
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/