概要
機能が多く初めはなかなか掴み所が難しいJestですが、テスト開発を効率的に行うためのTipsをまとめます。
Tips
Watchモードの活用
開発作業中はwatchモードで起動するのが非常に便利なのですが、動きに癖があると感じている方もいるのではないでしょうか?
まずはwatchモードで起動します。
npx jest {パターン} --watch
{パターン}
はディレクトリかファイルですが、一部でもOKです。一致するファイルのみテストが実行されます。
テストが完了するとこんな画面になります。
w
を押すと詳細が見られますが、下記のコマンドを利用することで条件を変更しながら便利にテストを再実行することができます。
Enter
JestのWatchモードはファイルの変更を自動で検知して再実行してくれますが、
エンターキーを押すことでも同じ条件でテストが再実行されます。
また、実行中にエンターキーを押すと、テストが一時停止されるので条件などを変更して再実行ができます。
a
ファイル名のパターンを指定してテストを走らせた場合、最初の実行はパターンで対象のディレクトリが絞られていますが、a
を押すとパターンの指定が解除されます。
p
ファイル名のパターンの指定をしなおすことができます。解除したい場合は空文字でエンターを押せばOKです。
t
テスト名のパターンで絞ることができます。解除したい場合は空文字でエンターを押せばOKです。
test('ここの文字列の部分一致', () => {...});
これらのコマンドの組み合わせで、watchモードにしたまま効率的に開発を続けることができます。
only, skip
上記のwatchモードコマンド p
, t
などで実行するテストを絞ることができましたが、コード上で指定することも可能です。テストを分割する describe
, test
などには、.only
, .skip
という関数が生えています。
describe('テストA', () => {
test.skip('テストAA', () => {});
});
describe.skip('テストB', () => {...});
とすることで、テストAA
, テストB
はスキップされます。
また、
describe('テストA', () => {
test.only('テストAA', () => {});
});
describe('テストB', () => {...});
で、テストAA
だけが実行されます。
describeを活用
テストの階層を作る関数は describe
とtest(=it)
の2つだけですが、test
の内容ができるだけ具体的になるように、describeで階層を作成します。
例えば、以下のように書いた場合、
const person = {
age: 20,
name: {
kana: 'スズキ',
kanji: '鈴木',
}
}
describe('personのテスト', () => {
test('値が正しいことを確認', () => {
expect(person.age).toBe(20);
expect(person.name.kana).toBe('スズキ');
expect(person.name.kanji).toBe('鈴木');
})
});
これでは何をテストしたのか少し曖昧になります。
describeで階層を作成した場合は以下の通りになります。
describe('personのテスト', () => {
describe('値が正しいことを確認', () => {
test('年齢が20歳', () => expect(person.age).toBe(20));
describe('名前', () => {
test('カナが「スズキ」', () => expect(person.age).toBe('スズキ'));
test('漢字が「鈴木」', () => expect(person.age).toBe('鈴木'));
});
})
});
また、結果を非同期で受け取る場合でも、beforeAllなどを活用することで詳細にtest()を分割することができます。
const personApi = () => Promise.resolve({
age: 20,
name: {
kana: 'スズキ',
kanji: '鈴木',
}
});
describe('personのテスト', () => {
let person: any = null;
beforeAll(async () => {
person = await personApi();
});
describe('値が正しいことを確認', () => {
// 以下同様 ...
});
verboseフラグ
折角describeをうまく使っても、複数のテストが対象になる場合は詳細な階層を表示してくれません。
詳細が確認したい場合は --verbose
フラグを設定して実行します。
npx jest --watch --verbose
複数の条件でテストを実行したい
test.each
という関数が利用できます。
const sum = (a: number, b: number) => a + b;
describe('sumの結果が正しい', () => {
test.each([
[1, 1, 2],
[3, 4, 7],
[1, -1, 0],
[1, 0, 1],
])('%i + %i = %i', (a, b, result) => {
expect(sum(a, b)).toBe(result);
})
});
ts-jest
が遅い
Jestが遅い場合の理由は色々ありますが、ts-jestの変換が遅い場合の対処です。
ts-jestはTypeScriptで開発をしている場合にjest.config.jsのtransformに設定して、TSファイルをJSに変換するために利用されます。
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
esbuild-jest
を利用する
esbuild-jest というツールがありますので、ts-jestの代わりに利用できます。
npm i -D esbuild-jest
transform: {
'^.+\\.(ts|tsx)$': 'esbuild-jest',
},
注意として、esbuildがまだ新興ツールなのと、私が利用していて、react周りの変換でエラーが出たりしましたので、バックエンドのコードで利用しています。
tscでビルドする
自分でtscで変換してから、.jsファイルでjestを走らせる方法です。これにより、ts-jestによる変換の時間がかからなくなります。
module.exports = {
// tscが吐き出すパス配下を参照する様にする
roots: ['<rootDir>/dist'],
注意点として、dist配下はコミットしないと思いますが、このままではsnapshotテストの結果がdist配下に吐き出されてしまいます。
jestによって生成されたsnapshotのみ、もとのtsファイルのそばに配置したい場合は snapshotResolver を設定します。