비주얼 테스트: 화면을 구성하는 컴포넌트들을 독립적으로 관리하고 변화를 관찰하고 테스트하기 위한 방법. ->
예시에 사용한 코드는 교재와 해당 레포 에서 참조.
create-react-app
보일러플레이트로 리액트 프로젝트 생성 후,
yarn add --dev @storybook/react
로 루트 폴더에 storybook 을 설치합니다.
package.json 의 script 부분에 storybook 을 실행시킬 script 를 추가합니다.
...
"scripts": {
"storybook": "start-storybook -p 9001 -c .storybook",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test" "eject": "react-scripts eject"
},
...
-p 9001
은 포트넘버 9001 을 사용하여 서버를 실행시키는 설정입니다.
컴포넌트를 import 해 storybook 에서 테스트할 수 있도록 하는 스토리 파일을 생성합니다. 예제 코드 레포는 위의 링크에 있습니다.
src
안에 stories
폴더를 만들어 스토리 파일들을 관리합니다.
import React from 'react';
import { storiesOf } from '@storybook/react';
import Input from '../Input';
storiesOf('Input Component', module)
.add('First setting', () => <Input name='name' />)
.add('label example', () => <Input name='name' label='이름' />);
storiesOf()
의 첫번째 string 인자는 해당 컴포넌트를 지칭합니다 => 컴포넌트 목록의 타이틀.
.add()
의 첫번째 string 인자는 해당 스토리의 타이틀이 됩니다. 두번째 인자인 콜백을 통해 import 해온 실제 컴포넌트와 테스트하고 싶은 프로퍼티를 추가해서 각각 다른 스토리를 확인할 수 있습니다.
config.js
와 스토리를 연결하기 위해서 먼저 프로젝트 루트 폴더에 .storybook
이라는 폴더를 생성 후, 그 안에 아래와 같은 내용의 config.js
을 작성합니다.
import { configure } from '@storybook/react';
function loadStories() {
require('../src/stories/InputStory');
}
configure(loadStories, module);
package.json 에 설정한 대로 script 를 실행시킵니다.
yarn storybook
Input Component
아래 추가한 두 개의 스토리 First setting
과 label example
을 확인할 수 있습니다.
만약 새로운 컴포넌트를 테스트하기 위해 storybook 에 추가하려면 이전처럼 config.js
수정해야 합니다.
import { configure } from '@storybook/react';
function loadStories() {
require('../src/stories/InputStory');
require('../src/stories/NewCounterStory');
}
configure(loadStories, module);
하지만 매번 일일히 config.js
를 수정하는 것은 너무나 비효율적인 과정이므로, 일관된 파일명 (~Story.js) 를 이용해 자동으로 storybook 에 추가되도록 수정합니다.
import { configure } from '@storybook/react';
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
function loadStories() {
const context = require.context('../src/stories', true, /Story\.js$/);
context.keys().forEach((srcFile) => {
interopRequireDefault(context(srcFile));
})
}
configure(loadStories, module);
먼저 requre.context()
를 통해 stories
폴더 안에서 끝이 Story.js
인 파일들을 받고, 그 파일들(의 배열)을 forEact()
메서드를 이용해 각 파일들에 interopRequireDefault()
를 실행시킵니다.
interopRequireDefault()
는 context(scrFlie)
, 즉 context
함수로 임포트 해온 파일 중 default 항목을 임포트 합니다.
이렇게 config.js
를 수정하면 테스트 하고 싶은 컴포넌트를 stories
파일에 추가해주면 자동으로 storybook 에도 추가됩니다.
addon-actions
는 storybook 에서 특정 이벤트가 발생했을 때 로그를 출력하게 해줍니다.
먼저 yarn add --dev @storybook/addons @storybook/addon-actions
로 패키지를 설치합니다.
그리고 .storybook
폴더 안에 addons.js
를 추가해 storybook 이 인식하도록 합니다.
//addons.js
import '@storybook/addon-actions/register';
addon-actions
를 import 하여 적용시킨 컴포넌트를 스토리로 추가합니다.
// InputStory.js
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import Input from '../Input';
storiesOf('Input Component', module)
.add('First setting', () => <Input name='name' />)
.add('label example', () => <Input name='name2' label='이름' />)
.add('onChange example', () => <Input name='name3' onChange={action('onChange event has occured')} />);
onChange
이벤트가 일어났을 때 로그를 출력하도록 설정한 스토리를 예시로 추가했습니다.
위 이미지를 통해 onChange
마다 로그가 출력되는 것을 확인할 수 있습니다.
이렇게 storybook 에 컴포넌트들을 구현해 본 후 실제 프로젝트에 적용하면 컴포넌트 단위로 수정 및 재활용이 가능하단 편의성이 있습니다.