Jest with TypeScript

2woongjae@gmail.com

Mark Lee (이웅재)

  • Studio XID inc. ProtoPie Engineer
  • Seoul.JS 오거나이저
  • 타입스크립트 한국 유저 그룹 오거나이저
  • 일렉트론 한국 유저 그룹 운영진
  • Seoul.js 오거나이저
  • Microsoft MVP - Visual Studio and Development Technologies
  • Code Busking with Jimmy
    • https://www.youtube.com/channel/UCrKE8ihOKHxYHBzI0Ys-Oow

Jest

facebook/jest

  •  리액트의 영향이 크겠지만 가장 핫한 테스트 도구
  • 👩🏻‍💻 Easy Setup

  • 🏃🏽 Instant Feedback

    • ​고친 파일만 빠르게 테스트 다시 해주는 기능 등

  • 📸 Snapshot Testing

    • ​컴포넌트 테스트에 중요한 역할을 하는 스냅샷

테스트 준비 끝

어떤 파일을 테스트 해주나요?

  • 자동으로 만들어지지는 않습니다.
  • Files with .js suffix in __tests__ folders.
  • Files with .test.js suffix.
  • Files with .spec.js suffix.

Quick Start

프로젝트 준비

~/Project/workshop-201801 
➜ npx create-react-app react-ts-jest --scripts-version=react-scripts-ts                                   

~/Project/workshop-201801 
➜ cd react-ts-jest 

Project/workshop-201801/react-ts-jest is 📦 v0.1.0 via ⬢ v8.9.4 
➜ npm i enzyme enzyme-adapter-react-16 react-test-renderer -D
+ react-test-renderer@16.2.0
+ enzyme-adapter-react-16@1.1.1
+ enzyme@3.3.0
added 30 packages in 11.591s

Project/workshop-201801/react-ts-jest is 📦 v0.1.0 via ⬢ v8.9.4 took 12s 
➜ npm i @types/enzyme @types/enzyme-adapter-react-16 @types/react-test-renderer -D
+ @types/enzyme@3.1.8
+ @types/enzyme-adapter-react-16@1.0.1
+ @types/react-test-renderer@16.0.0
added 4 packages in 12.088s

App.test.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
});

Unit Test 를 하는 이유를 물으신다면 ?

  • 사람을 믿으시겠습니까 ?
    • 실제로는 그냥 사람의 감이다.
  • 테스트 코드를 믿으시겠습니까 ?
    • 코드는 거짓말을 하지 않습니다.
  • 통합테스트에 비해 빠르고 쉽습니다.
  • 통합테스트를 진행하기 전에 문제를 찾아낼 수 있습니다.
    • 그렇다고, 통합테스트가 성공하리란 보장은 없습니다.
  • 테스트 코드가 살아있는(동작을 설명하는) 명세가 됩니다.
    • 테스트를 읽고 어떻게 동작하는지도 예측 가능합니다.
  • 소프트웨어 장인이 되려면 해야죠..
    • 선 코딩 후 (몰아서) 단위테스트가 아니구요

Component Test

  • App 컴포넌트
    • should render title in a h1 tag
    • should create the app
    • should have as title 'app'
  • TsButton 컴포넌트
    • 컴포넌트가 정상적으로 생성된다.
    • 컴포넌트가 생성되면 버튼 엘리먼트가 생성되어 null 이 아니다.
    • 버튼 엘리먼트에 써있는 텍스트는 "ts-button" 이다.
    • 버튼을 클릭하면, p 태그 안에 "버튼이 방금 눌렸다." 라고 쓰여진다.
    • 버튼을 클릭하기 전에는, p 태그 안에 "버튼이 눌리지 않았다." 라고 쓰여진다.
    • 버튼을 클릭하고 5초 뒤에는, p 태그 안에 "버튼이 눌리지 않았다." 라고 쓰여진다.
    • 버튼을 클릭하면, 5초 동안 버튼이 비활성화 된다.

컴포넌트가 정상적으로 생성된다.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import TSButton from './TsButton';

describe('TsButtonComponent', () => {
  it('컴포넌트가 정상적으로 생성된다.', () => {
    const div = document.createElement('div');
    ReactDOM.render(<TSButton />, div);
  });
});

enzyme 설정 : setupTests.ts

import { configure } from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

enzyme 로 테스트 수정

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import TSButton from './TsButton';

describe('TsButtonComponent', () => {
  it('컴포넌트가 정상적으로 생성된다.', () => {
    shallow(<TSButton />);
  });
});

컴포넌트가 생성되면 버튼 엘리먼트가 생성되어 null 이 아니다.​

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import TSButton from './TsButton';
import { shallow } from 'enzyme';

describe('TsButtonComponent', () => {
  it('컴포넌트가 정상적으로 생성된다.', () => {
    shallow(<TSButton />);
  });
  it('컴포넌트가 생성되면 버튼 엘리먼트가 생성되어 null 이 아니다.', () => {
    // Given
    const wrapper = shallow(<TSButton />);
    // When
    // Then
    expect(wrapper).not.toBeNull();
  });
});

버튼 엘리먼트에 써있는 텍스트는 "ts-button" 이다.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import TSButton from './TsButton';
import { shallow } from 'enzyme';

describe('TsButtonComponent', () => {
  it('컴포넌트가 정상적으로 생성된다.', () => {
    shallow(<TSButton />);
  });
  it('컴포넌트가 생성되면 버튼 엘리먼트가 생성되어 null 이 아니다.', () => {
    // Given
    const wrapper = shallow(<TSButton />);
    // When
    // Then
    expect(wrapper).not.toBeNull();
  });
  it('버튼 엘리먼트에 써있는 텍스트는 "ts-button" 이다.', () => {
    // Given
    const wrapper = shallow(<TSButton />);
    // When
    // Then
    const button = <button>ts-button</button>;
    expect(wrapper.contains(button)).toBeTruthy();
  });
});

버튼을 클릭하면, p 태그 안에 "버튼이 방금 눌렸다." 라고 쓰여진다.

버튼을 클릭하기 전에는, p 태그 안에 "버튼이 눌리지 않았다." 라고 쓰여진다.

버튼을 클릭하고 5초 뒤에는, p 태그 안에 "버튼이 눌리지 않았다." 라고 쓰여진다.

버튼을 클릭하면, 5초 동안 버튼이 비활성화 된다.

[CODEBUSKING WORKSHOP] Jest with TypeScript

By Woongjae Lee

[CODEBUSKING WORKSHOP] Jest with TypeScript

코드버스킹 워크샵 - React with TypeScript 세번째 (2018년 1월 버전)

  • 974