Jest

Happhee·2022년 5월 18일
1

💙  React 💙

목록 보기
17/18
post-thumbnail

✨ Jest란?

페이스북에서 만들어서 React와 더불어 많은 자바스크립트 개발자들로 부터 좋은 반응을 얻고 있는 테스팅 라이브러리이다.

Jest 이전에는 자바스크립트 코드를 테스트하라면 여러가지 테스팅 라이브러리를 조합해서 사용했다!

예를 들어, Mocha나 Jasmin을 Test Runner로 사용하고, Chai나 Expect와 같은 Test Mathcher를 사용했으며, 또한 Sinon과 Testdouble 같은 Test Mock 라이브러리도 필요했었다.

이 라이브러리들은 굉장히 유사하지만 살짝씩 다른 API를 가지고 있었기 때문에, 여러 프로젝트에 걸쳐서 일하는 자바스크립트 개발자들에게 혼란을 주기도 했었다.

하지만 Jest는 라이브러리 하나만 설치하면, Test Runner와 Test Mathcher 그리고 Test Mock 프레임워크까지 제공해주기 때문에 현재 대세라고 말할 수 있다.

✨ Jest 설치

yarn add --dev jest

npm install --save-dev jest

설치가 끝나면 package.json에 아래 코드를 추가한다.

"scripts": {
    "test": "jest",
  },

yarb test로 스크립트를 실행한다.

✨ JEST 기본 문법

test할 파일을 만들때에는 테스트 함수파일명.test.js

  • sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;
  • sum.test.js
const sum = require("./sum");

test("adds 1 + 2 to equal 3", () => {
  expect(sum(1, 2)).toBe(3);
});

npm test를 실행시키면 아래와 같은 결과가 나온다.

toBe(8)을 넣고 다시 테스트를 진행해보면, 어디에서 실패되었는지 정확하게 알려준다.

❗️ CommonJS 👉 ES6 ❗️

  • sum.js
function sum(a, b) {
  return a + b;
}
export default sum;
  • sum.test.js
import sum from "./sum";

test("adds 1 + 2 to equal 3", () => {
  expect(sum(1, 2)).toBe(8);
});

이후 npm test를 진행해보자.

jest는 CommonJS 모듈 시스템을 사용하기 때문에 ES6 문법을 사용하면 에러가 나타난다!

Babel 사용하기

따라서 우리는 Babel 설정을 진행해주어야 한다.

✅ JavaScript

npm install -D jest @types/jest @babel/core @babel/preset-env

yarn add --dev babel-jest @babel/core @babel/preset-env

프로젝트 루트에 babel.config.js을 생성하여 현재 노드 버전에 맞는 Babel을 설정한다.

  • babel.config.json
{
  "presets": ["@babel/preset-env"]
}
  • jest.config.json
{
  "collectCoverage": true,
  "moduleFileExtensions": ["js", "mjs"],
  "transform": {
    "^.+\\.js$": "babel-jest",
    "^.+\\.mjs$": "babel-jest"
  },
  "testRegex": "((\\.|/*.)(test))\\.js?$"
}

이후 npm test를 진행하면 ES6 문법을 사용할 수 있다.

✅ TypeScript

  • sum.ts
function sum(a: number, b: number): number {
  return a + b;
}
export default sum;

타입스크립트로 변환 후 npm test를 해주면 어마어마한 에러가 발생하게 된다😭

❗️ 하지만 이것도 패키지를 다운받아 해결할 수 있다 ❗️

npm install --dev @babel/preset-typescript

yarn add --dev @babel/preset-typescript
  • babel.config.json
{
  presets: [
    [
      '@babel/preset-env', 
      {targets: {node: 'current'}}
    ],
    '@babel/preset-typescript', // 👈 여기 !!
  ],
};
  • jest.config.json
{
  "preset": "ts-jest", // 👈 여기
  "collectCoverage": true,
  "moduleFileExtensions": ["js", "mjs", "ts"], // 👈 여기
  "transform": {
    "^.+\\.js$": "babel-jest",
    "^.+\\.mjs$": "babel-jest"
  },
  "testRegex": "((\\.|/*.)(test))\\.js?$"
}

이후 npm test를 진행하면 타입스크립트를 사용할 수 있다.

import sum from "./sum";

test("sum 1 + 2 to equal 3", () => {
  expect(sum(1, 2)).toBe("3");
});

✅ React

그렇다면 리액트는 어떻게 사용할까?
리액트 공식문서에서 사용을 권장하는 라이브러리는 react-testing-library이며 대체방안으로 Enzyme 이 있다.

react-testing-library vs Enzyme

react-testing-library

  • 실제 DOM 에 대해서 신경을 더 많이 쓰고 컴포넌트의 인스턴스에 대해서 신경쓰지 않는다.
  • 실제 화면에 무엇이 보여지는지, 어떠한 이벤트가 발생했을때 화면에 원하는 변화가 생겼는지 확인하기에 조금 더 최적화되어있다.

Enzyme

  • 테스트 코드를 작성 할 때에는 컴포넌트의 내부 기능을 자주 접근한다.
  • props, state 를 확인하고, 컴포넌트의 내장 메서드를 직접 호출하기도 한다.

📄 React-testing-library 적용하기

1️⃣ react-testing-library 설치

// CRA
npx create-react-app jest-react

yarn create jest-react

// 설치
npm i -D @testing-library/react @testing-library/jest-dom

yarn add --dev @testing-library/react @testing-library/jest-dom
  • src/setupTests.js
import "@testing-library/jest-dom";

2️⃣ 컴포넌트 및 테스트 작성

  • Profile.js
import React from "react";

const Profile = ({ username, name }) => {
  return (
    <div>
      <b>{username}</b>
      <span>({name})</span>
    </div>
  );
};

export default Profile;
  • Profile.test.js
import React from "react";
import { render, screen } from "@testing-library/react";
import Profile from "./Profile";

describe("<Profile />", () => {
  it("matches snapshot", () => {
    const utils = render(<Profile username="Happhee" name="서히" />);
    expect(utils.container).toMatchSnapshot();
  });
  it("shows the props correctly", () => {
    const utils = render(<Profile username="Happhee" name="서히" />);
    screen.getByText("Happhee"); // Happhee 라는 텍스트를 가진 엘리먼트가 있는지 확인
    screen.getByText("(서히)"); // (서히) 이라는 텍스트를 가진 엘리먼트가 있는지 확인
    screen.getByText(/서/); // 정규식 /서/ 을 통과하는 엘리먼트가 있는지 확인
  });
});

toMatchSnapshot을 실행 👉 __snapshots__/Profile.test.js.snap 이 생성

이 칭구는 컴포넌트를 수정했을 때 원하는 방식으로 렌더되는지 비교하기 위해 생성된다!

  • Profile.test.js.snap`
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Profile /> matches snapshot 1`] = `
<div>
  <div>
    <b>
      Happhee
    </b>
     
    <span>
      (
      서히
      )
    </span>
  </div>
</div>
`;

"Happ"에 대한 검사를 진행하도록 변경하면

it("shows the props correctly", () => {
    const utils = render(<Profile username="Happhee" name="서히" />);
    screen.getByText("Happ");
    screen.getByText("(서히)"); 
    screen.getByText(/서/); 
  });

아래와 같이 에러가 뜨게 된다!

설명

  • describe
    test들을 블록으로 묶어준다.

  • it
    각 test들을 의미한다.

  • render
    리액트 컴포넌트를 렌더링 시켜준다.
    - matcher
    위의 코드에서 toMatchSnapshot(), toBe와 같은 것
    이외에도 다양한 matcher들이있다.

15.8 Jest에서 import/export를 사용하기

profile
즐기면서 정확하게 나아가는 웹프론트엔드 개발자 https://happhee-dev.tistory.com/ 로 이전하였습니다

0개의 댓글