리액트

#9. 테스팅(2) - 스냅샷 테스팅, 코드 커버리지

YJH3968 2021. 4. 2. 21:14
728x90

1. 스냅샷 테스팅

  • UI 개발에 TDD를 적용하기가 어렵고 때로는 비실용적이다. UI가 자주 바뀌면 UI 테스트를 유지보수하는데 시간이 오래 걸릴 수 있기 때문이다. 또한 이미 프로덕션 환경에서 작동 중인 UI component에 대한 테스트를 작성해야 하는 경우도 자주 있다.
  • 스냅샷 테스팅을 사용하면 UI component에 원치 않는 변화가 생기지 않았음을 확신할 수 있는 테스트를 빠르게 진행할 수 있다.
  • 제스트는 렌더링한 UI의 스냅샷을 저장할 수 있고 나중에 진행하는 테스트에서 SUT가 렌더링한 결과를 스냅샷과 비교해 소스 코드 변경이 UI에 변화를 주지 않았음을 빠르게 확인하면서도 UI 테스트 구현의 어려움을 덜 수 있다.
  • 스냅샷 테스팅은 처음 테스트를 실행할 때 DOM의 스냅샷을 저장하고 그 후 테스트를 실행할 때마다 렌더링한 출력이 스냅샷과 일치하는지 비교한다.
import { shallow } from 'enzyme'
import Color from '../../../src/components/ui/Color'

describe("<Color /> UI Component", () => {

  it("Renders correct properties", () =>
    let output = shallow(
      <Color title="Test Color"
             color="#F0F0F0"
             rating={3}
             timestamp="Mon Apr 11 2016 12:54:19 GMT-0700 (PDT)"
      />
    ).html()
  )

  expect(output).toMatchSnapshot()
})

 

  • 이 테스트는 엔자임을 사용해 component를 렌더링한 결과를 HTML 문자열로 수집한다.
  • .toMatchSnapshot은 스냅샷 테스트에 사용하는 제스트 matcher로 테스트를 처음 실행하면 제스트가 결과 HTML을 스냅샷 파일에 저장하고 이를 테스트와 같은 위치에 있는 __snapshots__ 디렉토리에 저장한다. 
  • 그리고 테스트를 실행할 때마다 제스트는 렌더링한 출력과 스냅샷을 비교한다. 결과 HTML과 다른 부분이 있다면 테스트는 실패한다.
  • 하지만 이 방법은 UI 변경이 자주 있는 경우 잘 깨지는 테스트를 작성하게 되거나 실패해야 하는데도 성공하는 테스트를 작성할 수도 있다. 그래서 이를 개선하기 위해 출력을 JSX로 저장한다.
// 스냅샷을 JSX로 저장하기 위해 enzyme-to-json 설치
npm install enzyme-to-json --save-dev
import { shallow } from 'enzyme'
import toJSON from 'enzyme-to-json' 
import { compose } from 'redux'
import Color from '../../../src/components/ui/Color'

describe("<Color /> UI Component", () => {

  const shallowExpect = compose(expect, toJSON, shallow)
  
  it("Renders correct properties", () =>
    shallowExpect(
      <Color title="Test Color"
             color="#F0F0F0"
             rating={3}
             timestamp="Mon Apr 11 2016 12:54:19 GMT-0700 (PDT)"
      />
    ).toMatchSnapshot()
  )
})
  • enzyme-to-json의 toJSON을 이용해 shallow 렌더링 결과를 JSON으로 변환해서 expect method에 넘기는 과정을 compose를 이용해 한 번에 처리한다.
  • 이 테스트를 실행하면 출력이 HTML이 아니라 JSX이기 때문에 테스트가 실패하는데, 이는 updateSnapshot 플래그를 붙여서 테스트를 다시 실행해 스냅샷을 갱신함으로써 해결한다.
// updateSnapshot 플래그를 붙여 테스트를 실행한다.
jest --updateSnapshot

// watch 플래그를 지정하면 제스트가 계속 실행되면서 소스 코드 변화를 감시하다가
// 변경된 내용이 있으면 테스트를 자동으로 진행한다.
jest --watch
  • 이렇게 스냅샷을 갱신하면 원래는 한 줄로 된 HTML 문자열이었으나 훨씬 보기 깔끔한 스냅샷을 볼 수 있다.

 

5. 코드 커버리지

  • 코드 커버리지는 테스트가 소스 코드 중 몇 줄을 실제로 테스트했는지 보고하는 과정이다. 이는 테스트를 충분히 작성했는지 보여주는 지표가 될 수 있다.
  • 제스트에는 테스트를 분석해서 얼마나 많은 문장, 분기, 함수, 줄을 검사했는지 표시해주는 이스탄불이라는 자바스크립트 도구가 있다.
// 코드 커버리지 검사
jest --coverage
  • 제스트는 웹 브라우저에서 볼 수 있는 보고서도 생성한다. 웹 브라우저에 /coverage/locv-report/index.html을 열어보면 상호작용이 가능한 보고서에서 코드 커버리지를 살펴볼 수 있다.
  • package.json 파일에 커버리지 관련 옵션을 넣을 수도 있다.
"jest": {
  "setupFiles" : ["./__tests__/global.js"],
  "modulePathIgnorePatterns": ["global.js"],
  "moduleNameMapper": {
    "\\.(scss)$": "<rootDir>/node_modules/jest-css-modules"
  },
  // 커버리지 관련 옵션들
  "verbose": true,
  "collectCoverage": true,
  "notify": true,
  "collectCoverageFrom": ["src/**"],
  "coverageThreshold": {
  	"global": {
      "branches": 80,
      "functions": 80,
      "lines": 80,
      "statements": 80
    }
  }
}
  • coverageThreshold 필드는 테스트를 통과하기 위해 필요한 최소한의 코드 커버리지를 정의한다. 예제에서는 모든 분기, 함수, 줄, 문장의 80%를 커버해야 테스트에 통과하도록 정한다.
  • collectCoverageFrom 필드는 커버리지를 검사할 대상이 되는 파일을 와일드카드 파일 이름 패턴 배열로 지정한다. 예제에서는 src 디렉토리나 그 하위 디렉토리 안에 있는 모든 파일을 대상으로 지정한다.
  • collectCoverage 옵션을 true로 하면 이 프로젝트에 jest 명령이 실행될 때마다 커버리지 데이터를 수집한다.
  • notify 필드는 운영체제에 따른 통지 대화창을 띄우게 한다.
  • verbose 옵션은 제스트를 실행할 때마다 테스트 결과를 자세히 보고하도록 만든다.
  • 보통 85% 이상을 커버하는 것을 목표로 한다.

 

출처 : learning react(2016)

728x90

'리액트' 카테고리의 다른 글

#11. 리액트와 서버  (0) 2021.04.06
#10. React Router  (0) 2021.04.04
#9. 테스팅(1) - ESLint, Redux와 React Component 테스트하기  (0) 2021.04.02
#8. React-Redux  (0) 2021.04.01
#7. Redux  (0) 2021.04.01