SharePoint Framework でも自動テストを実施したいということがあります。幸い公式のドキュメントでは Jest を使ってテストを実施する方法が紹介されています。
この方法では package.json を書き換えて既定の gulp test ではなく Jest を直接呼び出すようになっています。それはそれでいいのですが既定の gulp test のままで実施できないのかなと思ったのでちょっと試してみました。
gulp test について
そもそも gulp test が何をするのかを理解する必要があります。SharePoint Framework のツールチェーンでは @microsoft/gulp-core-build パッケージに定義されているタスクを実行しています。
そこで @microsoft/gulp-core-build パッケージのソースを辿っていくと JestTask というタスクが見つかります。どうやらこれを実行しているようです。
一般的に Jest を使って TypeScript のコードをテストする場合は ts-jest を使って内部的にトランスパイルするのですが、gulp test によるテストの場合、事前の gulp タスクで tsc や webpack が実行され lib フォルダーに格納されたコードに対してテストが行われます。
サンプル コード
テストを実施する
全体的な流れはわかったので実際にテスト コードを書いていきます。まずは @types/jest をインストールします。@microsoft/gulp-core-build が使っている Jest のバージョンが 23.6.0 なのでバージョンを合わせるようにします。
npm install @types/jest@23.3.14 --save-dev
tsconfig.json で Jest が型解決できるようにします。
"types": [
"es6-promise",
"webpack-env",
+ "jest"
],
components フォルダーに MyApplicattion.test.tsx をいうファイルを作成して適当にテスト コードを追加してみます。
// とりあえず必ず PASS するテスト it('test1', () => { expect(true).toBe(true); });
gulp test すればテストが実行されるはずですが、試してみると実行されません。JestTask のコードを見てみると、isEnabled という設定があってこれを true にする必要があるので config/jest.json を追加します。また今回は coverage は使わないので false にしておきます。
{ "isEnabled": true, "coverage": false }
これで再度 gulp test するとテストが実行されます。
[00:00:00] Starting subtask 'jest'... PASS lib\webparts\my-application\components\MyApplicattion.test.js [00:00:00] Finished subtask 'jest' after 1.5
スナップショット テストを実施する
基本的なテストができることはわかりましたが、React のスナップショット テストも実施してみたいです。まずは React をテストできるようにセットアップします。
必要なパッケージをインストールします。
npm install babel-jest@22.4.4 react-test-renderer@16.8.6 @types/react-test-renderer@16.8.3 babel-preset-env babel-preset-react --save-dev
.babelrc を追加します。
{ "presets": [ "babel-preset-env", "babel-preset-react" ] }
テスト コードを追加します。
import * as React from 'react'; import { create } from 'react-test-renderer'; import MyApplication from './MyApplication'; import { IMyApplicationProps } from './IMyApplicationProps'; // スナップショットを作成するテスト it('test2', () => { const props = {} as IMyApplicationProps; const tree = create(<MyApplication {...props} />).toJSON(); expect(tree).toMatchSnapshot(); });
これでテストを実行するとエラーが発生してしまいます。
[00:00:00] Starting subtask 'jest'... FAIL lib\webparts\my-application\components\MyApplicattion.test.js ● Test suite failed to run SyntaxError: Unexpected token . 5 | container: 'container_835912dc', 6 | row: 'row_835912dc', > 7 | column: 'column_835912dc', 8 | 'ms-Grid': 'ms-Grid_835912dc', 9 | title: 'title_835912dc', 10 | subTitle: 'subTitle_835912dc', at ScriptTransformer._transformAndBuildScript (node_modules/jest-cli/node_modules/jest-runtime/build/script_transformer.js:316:17) at Object.<anonymous> (lib/webparts/my-application/components/MyApplication.module.scss.js:7:1) at Object.<anonymous> (lib/webparts/my-application/components/MyApplication.js:11:28) at Object.<anonymous> (lib/webparts/my-application/components/MyApplicattion.test.js:9:22) [00:00:00] Error - 'jest' sub task errored after 1.86 s Jest tests failed [00:00:00] 'test' errored after 8.45 s [00:00:00] [00:00:00] ==================[ Finished ]================== Error - 'jest' sub task errored after 1.86 s Jest tests failed
これは CSS ファイルを require しようとして失敗しているのが原因なので、モックを追加します。
config/jest/jest.config.json を追加します。
{ "moduleNameMapper": { "\\.css$": "<rootDir>/__mocks__/cssmock.js" } }
__mocks__/cssmock.js を追加します。
module.exports = '';
これでテストが成功します。
[00:00:00] Starting subtask 'jest'... PASS lib\webparts\my-application\components\MyApplicattion.test.js [00:00:00] Finished subtask 'jest' after 1.53 s [00:00:00] Finished 'test' after 7.64 s
まとめ
やればできる。けど普通に Jest 使ったほうがいいと思います。