Node.js(ES6で実装)でJestによるテストを実行するためのBabel・ESLintの設定とは?
はじめに
こんにちは、SHIFT の開発部門に所属しているKatayamaです。
Node.js で ES Modules を利用する時に、Babel によるトランスパイルを利用しているような場合、そのまま Jest によるテストを実行すると以下のようなエラー("Cannot use import statement outside a module")が発生すると思います。
[root@localhost node-express]# yarn test
yarn run v1.22.17
$ jest
FAIL tests/sum.test.js
● Test suite failed to run
...
Details:
/root/workspace/node-express/tests/sum.test.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import sum from '../src/sum';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.723 s
Ran all test suites.
error Command failed with exit code 1.
今回は Node.js で ES Modules を利用するのに、Babel によるトランスパイルを利用している時の Jest の設定方法についてみていきたいと思います。
また、Project に ESLint を設定してる場合、Jest でテストを書くと、以下のようにエラー(Jest の構文に対する "no-undef")が表示されてしまいます。このエラーを解消する方法についてもみていきたいと思います。
※Node.js で ES Modules を利用するための設定については、Node.js で import・export(ES6 の構文)を使えるように webpack × Babel の設定をやってみたを参照ください。
Jest でテスト実行できるように設定する
結論:どうすればいいか?
Babel の設定ファイル(今回は babel.config.js)に、以下のような設定を行う。
// babel.config.js
module.exports = {
presets: [["@babel/preset-env", { targets: { node: "current" } }]],
};
※既に Babel の設定がある場合、既存の設定と競合しないようにするために以下のように process.env.NODE_ENV=test の時だけ有効になる設定の書き方をする。
// babel.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
...
}
]
],
env: {
test: {
presets: [
[
'@babel/preset-env',
{
targets: { node: 'current' }
}
]
]
}
}
};
設定について
基本的には Jest の公式「Babel を使用する」に書かれている通りに設定すればいい。まずは必要なものをインストールする。
yarn add --dev jest babel-jest @babel/core @babel/preset-env
一点、"babel-jest"ついてだが、jestがコードを解釈するときに実行されるトランスパイル時の設定が、プロジェクトに存在する Babel の設定(babel.config.jsなど)を読み込むだけであれば、"yarn add --dev"で明示的にdevdependencyに追加する必要性はない。理由としては jest のインストール時に自動的に node_modules に"babel-jest"が追加されるようになっているため。そのことは公式にも
と確かに書かれている事からもわかる。ちなみに、本当にjestをインストールしただけで"babel-jest"が node_modules に追加されるのか?だが、それは package.lock.json or yarn.lock を確認すれば babel-jest が入っている事が確認できる。
後は Babel の configration(babel.config.js など)に以下を記述すれば OK。
// babel.config.js
module.exports = {
presets: [["@babel/preset-env", { targets: { node: "current" } }]],
};
※上記のように設定する際に、既に Babel の設定がある場合には、既存の設定と上記の設定をどのように共存させるのか?という疑問が出てくる。この場合には、Babel の設定オプションのenvを使って、環境変数 NODE_ENV の値で有効化する設定を変える事で対応できる。具体的には、Jest 実行時には NODE_ENV=test になるので、以下のように babel.config.js に test 用の設定を追加する。
// babel.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
...
}
]
],
env: {
test: {
presets: [
[
'@babel/preset-env',
{
targets: { node: 'current' }
}
]
]
}
}
};
※Jest 実行時には NODE_ENV=test になるというのは、公式の以下の記述から確認できる。
Babel の設定後に Jest でテスト を実行してみる
問題なくテスト実行できるようになった事が確認できる。
[root@localhost node-express]# yarn test
yarn run v1.22.17
$ jest
PASS tests/sum.test.js
✓ adds 1 + 2 to equal 3 (499 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.92 s
Ran all test suites.
Done in 3.28s.
テスト対象のコードは以下(ES6 以降の構文である async/await をわざと入れたコードにしている)。
sum.js
export default async (a, b) => {
await new Promise((resolve) => {
setTimeout(() => {
resolve('sleep');
}, 500);
});
return a + b;
};
テストコードは以下。
import sum from '../src/sum';
test('adds 1 + 2 to equal 3', async () => {
expect(await sum(1, 2)).toBe(3);
});
ESLint でエラーが発生しないように設定をする
結論:どうすればいいか?
.eslintrc.json に以下のように"plugin:jest/recommended"を extends に追加する。
// .eslintrc.json
{
...
"extends": [
...
"plugin:jest/recommended",
...
],
...
}
設定について
eslint-plugin-jestをインストールして、extends に"plugin:jest/recommended"を追加する。
こうする事で、以下のようにtestやexpectでエラーが表示されなくなる。また、eslint-plugin-jest で定義されているルールに基づき新たに warn が出るようになり、ちゃんと ESLint の設定がうまく動いている事が分かる(after の方には ESLint が動いている事を確認する意味で、わざと warn が表示されるような実装を追加している)。
※補足として、公式のUsageを見ると、"plugins": ["jest"]や"env": { "jest/globals": true }を .eslintrc.json に追加するように書いてあるが、今回そうではなく extends に追加するだけにしたのは、eslint-plugin-jest の ESLint の設定が書かれているindex.tsに既に
plugins: ['jest'],
env: { 'jest/globals': true },
という設定が書かれており、この設定は (extends に"plugin:jest/recommended"のようにする事で)recommended: createConfig(recommendedRules)の部分から自身の .eslintrc.json に追加されるようになっているため。
※eslint-plugin-jest には、"plugin:jest/recommended"以外にも、"plugin:jest/style"や"plugin:jest/all"という設定もあり、要求に応じて使い分けも可能。
まとめとして
今回は Node.js で Babel によるトランスパイルを利用しているような場合に、Jest を実行するために必要な設定と、Jest でテストを実装する際に出てしまう ESLint のエラーを表示されないようにする設定についてみてきた。上記のような設定で快適に Jest によるテストを書いていく事ができると思う。
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/