# Jest Snapshot Test
# 개요
Jest Snapshot Test는 UI가 예상치못하게 변경되지않도록 도와줍니다.
코드의 일부분을 수정했을때, 해당 코드에 의존하고 있는 여러 컴포넌트가 변화될 수 있는데 그 변화를 정확하게 예측하긴 어렵습니다.
스냅샷 테스트 코드를 작성하여컴포넌트의 변화를 알기 쉽게 합니다.
# 활용
먼저 스냅샷 테스트 코드를 작성합니다.
// button.react.test.js
import React from "react";
import renderer from "react-test-renderer";
it("button renders correctly", () => {
const tree = renderer
.create(
<button type="button" onClick={() => {}}>
OK
</button>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
테스트코드를 실행시키면 아래와같이 __snapshot__
디렉토리에 snap이라는 확장자로 된 파일이 하나 생성됩니다.
(정확히는 toMatchSnapshot 메소드를 실행시키면 파일이 생성됩니다.)
// __snapshot__/button.react.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`button renders correctly 1`] = `
<button
onClick={[Function]}
type="button"
>
OK
</button>
`;
template literal을 보시면 react component가 string형태로 생성되어 있습니다.
여기서 의도적으로 button의 type을 submit으로 바꿔보겠습니다.
// button.react.test.js
import React from "react";
import renderer from "react-test-renderer";
it("button renders correctly", () => {
const tree = renderer
.create(
<button type="submit" onClick={() => {}}>
OK
</button>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
변경하면 아래와 같은 긴 테스트 실패 메시지가 콘솔에 출력됩니다
FAIL src/components/common/__tests__/Button.react.test.tsx
● button renders correctly
expect(received).toMatchSnapshot()
Snapshot name: `button renders correctly 1`
- Snapshot
+ Received
<button
onClick={[Function]}
- type="button"
+ type="submit"
>
OK
</button>
10 | )
11 | .toJSON();
> 12 | expect(tree).toMatchSnapshot();
| ^
13 | });
14 |
at Object.<anonymous> (src/components/common/__tests__/Button.react.test.tsx:12:16)
› 1 snapshot failed.
Snapshot Summary
› 1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.
+로 표시된 부분과 -로 표시된 부분을 보시면, 스냅샷과 현재상태를 비교해서 보여줍니다.
어떤 부분이 변경됐는지 명확하게 파악할 수 있습니다.
의도하지않은 변경이라면 코드를 수정하면 될 것이고
의도한 변경이라면 스냅샷을 변경(업데이트)해주면 됩니다.
콘솔에서(watch모드인 경우) 'u'를 누르면 자동으로 업데이트됩니다.
혹은 테스트 커맨드에 jest라면 --updateSnapshot 옵션을, react-scripts test라면 -u 옵션을 주면 됩니다.
# 인라인 스냅샷
__snapshot__/button.react.test.js.snap
이런식으로 파일과 디렉토리가 늘어나는게 별로 반갑지않다면 인라인 스냅샷을 하는 방법도 있습니다.
toMatchInlineSnapshot 을 사용하세요.
테스트를 실행하고나면 해당 메소드 파라미터에 template literal이 자동으로 생성되어 추가됩니다.
import React from "react";
import renderer from "react-test-renderer";
it("button renders correctly", () => {
const tree = renderer
.create(
<button type="button" onClick={() => {}}>
OK
</button>
)
.toJSON();
expect(tree).toMatchInlineSnapshot(`
<button
onClick={[Function]}
type="button"
>
OK
</button>
`);
});
# 마무리
스냅샷 테스트가 오류를 뱉어낼때, 컴포넌트의 변경을 알기 쉽지만
반대로 컴포넌트가 의도적으로 변경된 것 인지 판단할 수 있는 개발자의 역량이 필요합니다.
만약 의도치않은 컴포넌트 에러가 났는데도 실수로 스냅샷 테스트를 업데이트하면 의도하지 않은 변경이라도 테스트에서 통과됩니다.
복잡한 컴포넌트에는 적용하기가 귀찮다.
공통으로 활용되는 컴포넌트들에 적용해놓으면 마음이 조금 더 편해질것같다.
인라인 스냅샷의 경우 pr로 코드리뷰를 한다면, 스냅샷 업데이트를 pr에 올리지않게 하기위해.. 조금 더 손이 간다. 그래서 개인적으로 추천하진않는다.