概要
MUI 公式 Example の中から Next.js (TypeScript version) を雛形とし、自分の作りたいサイトに改造する 4 回目です。
今回は、JEST と React Testing Library をインストールし、最後のほうで簡単なテストのサンプルを使って練習をしてみます。
Rails を使っていた頃は、少しはテストをしていたのですが、なんか面倒で積極的にやりたい気が起きませんでした。
テストに対する苦手意識を克服するためにも、なんとか頑張ってみたいと思います。
数回に分けて連載する MUI に関連する記事の全体像
この記事の目次
ホスト
参考サイト
Jestの設定 · Jest
この頃流行りのJestを導入して軽快にJSをテストしよう - Qiita
% vim package.json
以下を追加
"scripts": {
"test": "jest",
"test:ci": "jest --ci"
},
"devDependencies": {
"@testing-library/jest-dom": "5.14.1",
"@testing-library/react": "12.0.0",
"@testing-library/user-event": "13.2.1",
"@types/node": "^17.0.0",
"babel-jest": "27.0.6",
"eslint-plugin-testing-library": "4.11.0",
"jest": "27.3.1",
"react-test-renderer": "17.0.2"
}
インストール
% npm install
jest.config.js
参考サイト
next.js/jest.config.js at canary · vercel/next.js · GitHub
設定
基本的に Vercel の上記公式サイトのものを使用していますが、"testEnvironment": "jsdom",
の部分だけ追加しました。デフォルトは、node
なのですが、テストによってはエラーが出るので、jsdom
にしております。詳細については、以下のサイトが参考になりました。
Jestの「 The error below may be caused by using the wrong test environment」の解決方法 - Qiita
% vim jest.config.js
const nextJest = require('next/jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapper: {
// Handle module aliases (this will be automatically configured for you soon)
'^@/components/(.*)$': '<rootDir>/components/$1',
},
"testEnvironment": "jsdom",
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
jest.setup.js
参考サイト
next.js/jest.setup.js at canary · vercel/next.js · GitHub
設定
Vercel のものを、そのまんま使いました。
% vim jest.setup.js
// Optional: configure or set up a testing framework before each test.
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`
// Used for __tests__/testing-library.js
// Learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect'
% pwd
/Users/ユーザー/React/school-test
% mkdir __tests__
practice ディレクトリ作成
練習用のファイルをひとまとめに保管するためのディレクトリを準備しました。
% pwd
/Users/ユーザー/React/school-test/src/pages
% mkdir __practice__
テスト例 1 ( CommonJs )
まずは、CommonJs を使った場合のテストを練習してみます。実際のプログラムで、CommonJs を使うことは、今後、あまりないとは思いますが、ES6 との違いがわかるので、やってみて損はないのではないでしょうか。
参考サイト
はじめましょう · Jest
commonjs_sum.js
% vim /Users/ユーザー/React/school-test/src/pages/__practice__/commonjs_sum.js
# CommonJs
function sum(a, b) {
return a + b;
}
module.exports = sum;
commonjs_sum.test.js
vim /Users/ユーザー/React/school-test/__tests__/commonjs_sum.test.js
const sum = require('../src/pages/__practice__/commonjs_sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
実行
% npm test commonjs_sum.test.js
実行結果
> nextjs-with-typescript@5.0.0 test
> jest "commonjs_sum.test.js"
PASS __tests__/commonjs_sum.test.js
✓ adds 1 + 2 to equal 3 (3 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.671 s
Ran all test suites matching /commonjs_sum.test.js/i.
テスト例 2 ( ES6 無名関数 )
次は、TypeScript です。ES6 の無名関数の場合のテストを練習してみます。プログラムの中身が、無名関数であろうが、アロー関数であろうが、テストの書き方は同じで大丈夫です。
参考サイト
JestをES6化してimport/exportを使う方法
noname_sum.ts
% vim /Users/ユーザー/React/school-test/src/pages/__practice__/noname_sum.ts
// ES6 無名関数
const sum = function(a:number, b:number):number {
return a + b;
}
export default sum
noname_sum.test.ts
vim /Users/ユーザー/React/school-test/__tests__/noname_sum.test.ts
import sum from '../src/pages/__practice__/noname_sum'
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3)
})
実行
% npm test noname_sum.test.ts
実行結果
> nextjs-with-typescript@5.0.0 test
> jest "noname_sum.test.ts"
PASS __tests__/noname_sum.test.ts (6.735 s)
✓ adds 1 + 2 to equal 3 (3 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 6.892 s
Ran all test suites matching /noname_sum.test.ts/i.
テスト例 3( ES6 アロー関数 )
次は、ES6 のアロー関数の場合です。テストの書き方は、上記の無名関数のときと全く同じです。あたりまえといえば、あたりまえですが。
参考サイト
JestをES6化してimport/exportを使う方法
FN1609010 | TypeScript入門 09: アロー関数式 | HTML5 : テクニカルノート
arrow_sum.ts
% vim /Users/ユーザー/React/school-test/src/pages/__practice__/arrow_sum.ts
// ES6 アロー関数
const sum = (a:number, b:number) => a + b;
export default sum
arrow_sum.test.ts
vim /Users/ユーザー/React/school-test/__tests__/arrow_sum.test.ts
import sum from '../src/pages/__practice__/arrow_sum'
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3)
})
実行
% npm test arrow_sum.test.ts
実行結果
> nextjs-with-typescript@5.0.0 test
> jest "arrow_sum.test.ts"
PASS __tests__/arrow_sum.test.ts (6.404 s)
✓ adds 1 + 2 to equal 3 (3 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 6.566 s
Ran all test suites matching /arrow_sum.test.ts/i.
テスト例 4
スプレッド構文や reduce を使っているサンプル。自分用のメモとして、ここに上げておきます。
参考サイト
Jest - TypeScript Deep Dive 日本語版
スプレッド構文 - JavaScript | MDN
【JavaScript】”…”ドットが3つ…?これ、どうやって使うの?スプレッド構文の挙動と活用方法|ProgLearn|エンジニアのためのプログラミング情報メディア
【javascript】reduce - Qiita
JavaScript reduce関数の基本的な使い方
% vim /Users/ユーザー/React/school-test/src/pages/__practice__/foo.ts
export const sum
= (...a: number[]) =>
a.reduce((acc, val) => acc + val, 0);
vim /Users/ユーザー/React/school-test/__tests__/foo.test.ts
import { sum } from '../src/pages/__practice__/foo';
test('basic', () => {
expect(sum()).toBe(0);
});
test('basic again', () => {
expect(sum(1, 2)).toBe(3);
});
実行
% npm test foo.test.ts
実行結果
> nextjs-with-typescript@5.0.0 test
> jest "foo.test.ts"
PASS __tests__/foo.test.ts (6.44 s)
✓ basic (3 ms)
✓ basic again
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 6.59 s
Ran all test suites matching /foo.test.ts/i.
テスト例 5
String を使ったサンプル。自分用のメモとして。
参考サイト
TypeScript のテストを Jest (ts-jest) でやってみる - Qiita
greet.ts
% vim /Users/ユーザー/React/school-test/src/pages/__practice__/greet.ts
export default (name: string): string => `Hello, ${name}!`;
greet.test.ts
vim /Users/ユーザー/React/school-test/__tests__/greet.test.ts
import greet from '../src/pages/__practice__/greet'
describe('greet', (): void => {
test('should say hello to Tom.', (): void => {
const response: string = greet('Tom');
expect(response).toBe('Hello, Tom!');
});
})
実行
% npm test greet.test.ts
実行結果
> nextjs-with-typescript@5.0.0 test
> jest "greet.test.ts"
PASS __tests__/greet.test.ts (6.407 s)
greet
✓ should say hello to Tom. (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 6.554 s
Ran all test suites matching /greet.test.ts/i.
テスト例 6
参考サイト
React Testing Libraryの使い方 - Qiita
App.js
% vim /Users/ユーザー/React/school-test/src/pages/__practice__/App.js
import React from 'react';
const title = 'Hello React';
function App() {
return <div>{title}</div>;
}
export default App;
App.test.js
vim /Users/ユーザー/React/school-test/__tests__/App.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from '../src/pages/__practice__/App';
describe('App', () => {
test('renders App component', () => {
render(<App />);
screen.debug();
});
});
実行
% npm test App.test.js
実行結果
> nextjs-with-typescript@5.0.0 test
> jest "App.test.js"
"next/jest" is currently experimental. https://nextjs.org/docs/messages/experimental-jest-transformer
console.log
<body>
<div>
<div>
Hello React
</div>
</div>
</body>
/Users/ユーザー/React/school-test/__tests__/App.test.js:15:24
13 |
at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:89:13)
PASS __tests__/App.test.js
App
✓ renders App component (80 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.142 s, estimated 3 s
Ran all test suites matching /App.test.js/i.
まだまだ練習したりないので、続きは後日。