프로필사진


2020.07.30

Cypress로 React Unit Test 회고

반응형

Cypress로 React Unit Test 하는 방법과 간단한 회고를 기록합니다.


Step. 0 :: 회고

Cypress를 사용하지 않고 Selenium을 이용해서 E2E Test를 진행할 수 있지만 FE 중점으로 특화된 테스트 방법을 도입하는 것이 더 좋지 않을까 생각하게 되었습니다.

 

Cypress로 React기반 프로젝트를 테스트해야 할 때, Cypress + Storybook 형태로 진행할지, 아니면 Cypress + React 형태로 진행할지 고민을 하게 되었습니다.

 

이번 포스트에서는 Cypress + React 방식은 어떻게 진행하는지 이야기해보려고 합니다. 더 나은 방법, 더 나은 코드가 있다면 언제든지 댓글로 알려주세요. (저도 배우는 입장이라...)

 

React 프로젝트를 Cypress로 테스트하게 될 때, 가장 중요한 부분 Webpack이라고 생각합니다.

 

Storybook을 사용하게 되면 빌드된 웹 위에서 테스트를 하는 것이라 큰 설정 없이 진행할 수 있지만 Storybook 없이 React를 테스트하게 될 경우에는 어떤 상태로 빌드를 했는지 cypress에도 알려줘야 제대로 테스트가 가능해집니다.

 

즉, 이 React 컴포넌트 혹은 페이지가 어떤 의존성을 가지고 있는지 알아야 mount를 할 수 있습니다. 

 

우리는 다행스럽게도 이런저런 고민을 먼저 해결한 분들이 있었고 이 포스팅은 `cypress-react-unit-test`를 바탕으로 Cypress로 React를 테스트하는 방법에 대해 소개하고자 합니다.


Step. 1 :: Cypress 설치

테스트하려는 React 프로젝트에 cypress, cypress-react-unit-test를 설치합니다.

npm install --save-dev cypress cypress-react-unit-test
npx cypress install # cypress 설치
npx cypress verify # cypress 동작 확인 

 

Step. 2 :: Cypress 설정하기

Cypress는 Selenium처럼 웹페이지에 접속하고 정해진 명령에 따라 동작하고 그 결과를 확인하는 기능을 합니다. 즉, 웹페이지를 빌드하는 것은 별도로 테스트 이전에 작업을 해야하고 접속이 가능한 상태로 만들어야합니다.

 

cypress-react-unit-test에서는 몇 가지 유용한 설정 도구를 제공합니다. 프로젝트에 적용하는 것은 큰 문제가 없었지만 아래와 같은 아쉬운 점도 있었습니다. 

 

cypress-react-unit-test 프로젝트에 대해 더 알아봐야 할 사항이지만, webpack / babelrc / cra / react-script 형태로 구분되어있습니다. 프로젝트 당 하나의 plugin만 사용 가능하므로 webpack + babelrc 형태로 설정이 어려운 것 같습니다.

( 이 부분은 명확하지 않습니다.  하지만 내부 코드를 보았을 때에는 그렇게 이해를 했고 실제로도 동작하진 않았습니다. 더 좋은 의견이 있으면 댓글 부탁드립니다. 👍)

 

이번 포스트에서 다룰 plugin은 webpack입니다.

프로젝트의 최상단에 아래와 같은 폴더 구조를 생성합니다.

( 파일은 내용이 빈 상태로 놔둡니다. 이미 파일이 있는 경우 비울 필요는 없습니다.

cypress
  - plugins
    - index.js
    - webpack.config.js
  - support
    - index.js
cypress.json 

 

Step. 2-1 :: cypress.json
{
  "fixturesFolder": false,
  "testFiles": "**/*.spec.*",
  "experimentalComponentTesting": true,
  "componentFolder": "./src",
  "nodeVersion": "system"
}
fixturesFolder : 정적 파일 사용 여부를 지정합니다. (Mock API 사용할 경우 사용)
testFiles: 테스트 파일을 찾는 규칙을 지정합니다.  ( 테스트 파일을 어떤 규칙으로 식별하는지 지정합니다. 필자는 *. spec.js입니다. )
experimentalComponentTesting: 컴포넌트 테스트 사용 여부를 지정합니다. 
componentFolder: 컴포넌트 폴더를 지정합니다.  ( 컴포넌트나 페이지가 존재하는 경로를 지정하면 됩니다. )
nodeVersion: 노드 버전을 지정합니다

이 외에도 더 다양한 옵션들이 있습니다. 원하는 옵션을 추가해 사용하면 됩니다.

 

Step. 2-2 :: support/index.js

cypress에서 React Unit Test 할 수 있도록 등록합니다. 아래 내용으로 채웁니다.

require('cypress-react-unit-test/support');

 

Step. 2-3 :: plugins/index.js
// load Webpack file preprocessor that comes with this plugin
// https://github.com/bahmutov/cypress-react-unit-test#install
const preprocessor = require('cypress-react-unit-test/plugins/load-webpack');

module.exports = (on, config) => {
  // point at the webpack config file at the root of the project
  config.env.webpackFilename = './cypress/plugins/webpack.config.js';
  preprocessor(on, config);
  // IMPORTANT to return the config object
  // with the any changed environment variables
  return config;
};

cypress/plugins/index.js 내용에 위와 같은 내용으로 채웁니다.

 

webpack의 경우에는 특정 라이브러리를 제외하는 경우도 있고, ".babelrc"로 분리해서 처리한 부분도 있기 때문에 cypress 테스트용 webpack를 별도로 분리해서 사용하는 게 좋을 것 같다는 생각 했습니다.

 

하지만 필수는 아니고 위와 같은 상황이 아니라면 `config.env.webpackFilename` 부분에 프로젝트의 webpack.config.js를 넣으면 됩니다.

 

Step. 2-4 :: plugins/webpack.config.js
const baseConfig = require('../../webpack.config');

function isBabelLoader(rule) {
  return rule.use && rule.use.loader === 'babel-loader';
}

function setBabelLoader(rule) {
  if (!rule || !rule.use || rule.use.loader != 'babel-loader') {
    return {};
  }

  const options = rule.use.options || {};
  const presets = [...(options.presets || []), '@babel/preset-env', '@babel/preset-react'];

  rule.use.options = { ...rule.use.options, presets };
  return rule;
}

const babelLoader = setBabelLoader(baseConfig.module.rules.find((rule) => isBabelLoader(rule)));
const rules = [babelLoader, ...baseConfig.module.rules.filter((rule) => !isBabelLoader(rule))];

baseConfig.module.rules = rules;
baseConfig.externals = {};
module.exports = baseConfig;

제가 작업하던 프로젝트에서는 babel의 presets이 babelrc형태로 분리되어있어 추가 작업을 해서 반환하는 형태로 진행했습니다.

( 이 코드보다 더 나은 방법이 있다면 댓글로 부탁드립니다!  )

 

Step. 3 :: 테스트 코드 작성하기

Step. 2-1에서 지정한 폴더 내에 Step. 2-1에서 지정한 파일 이름 패턴에 맞도록 파일을 생성 후 테스트 코드를 작성합니다.

it('looks right', () => {
  const todo = {
    id: '123',
    title: 'Write more tests',
  }
  mount(<Todo todo={todo} />, {
    stylesheets: [
      'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css',
    ],
  })
})

( 예시입니다. )

 

Step. 4 :: 테스트 진행하기
npx cypress run --browser chrome --no-exit
// --browser chrome :: 테스트 대상 브라우저는 chrome으로 진행합니다.
// --no-exit :: 테스트가 끝나도 종료하지 않습니다.

위 명령어를 통해 테스트를 진행할 수 있습니다. 이 부분에 대한 자세한 옵션은 여기에서 볼 수 있습니다. 

반응형

'해본 것 > Cypress' 카테고리의 다른 글

Cypress 명령어  (0) 2020.07.27
`cypress cache` 명령어 옵션 정리  (0) 2020.07.27
`cypress run` 명령어 옵션 정리  (0) 2020.07.26
Cypress 설치  (0) 2020.07.26
다른 '해본 것/Cypress'의 최근 글