6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Jestを効率的に実行するためのTips

Last updated at Posted at 2021-09-14

概要

機能が多く初めはなかなか掴み所が難しいJestですが、テスト開発を効率的に行うためのTipsをまとめます。

Tips

Watchモードの活用

開発作業中はwatchモードで起動するのが非常に便利なのですが、動きに癖があると感じている方もいるのではないでしょうか?

まずはwatchモードで起動します。

npx jest {パターン} --watch

{パターン}はディレクトリかファイルですが、一部でもOKです。一致するファイルのみテストが実行されます。

テストが完了するとこんな画面になります。

スクリーンショット 2021-09-15 7.00.04.png

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を活用

テストの階層を作る関数は describetest(=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('鈴木');
  })
});

スクリーンショット 2021-09-15 7.14.53.png

これでは何をテストしたのか少し曖昧になります。

describeで階層を作成した場合は以下の通りになります。

describe('personのテスト', () => {
  describe('値が正しいことを確認', () => {
    test('年齢が20歳', () => expect(person.age).toBe(20));
    
    describe('名前', () => {
      test('カナが「スズキ」', () => expect(person.age).toBe('スズキ'));
      test('漢字が「鈴木」', () => expect(person.age).toBe('鈴木'));
    });
  })
});

スクリーンショット 2021-09-15 7.22.04.png

また、結果を非同期で受け取る場合でも、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をうまく使っても、複数のテストが対象になる場合は詳細な階層を表示してくれません。

スクリーンショット 2021-09-15 7.26.38.png

詳細が確認したい場合は --verbose フラグを設定して実行します。

npx jest --watch --verbose

スクリーンショット 2021-09-15 7.28.38.png

複数の条件でテストを実行したい

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);
  })
});

スクリーンショット 2021-09-15 7.53.57.png

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による変換の時間がかからなくなります。

jest.config.js
module.exports = {
  // tscが吐き出すパス配下を参照する様にする
  roots: ['<rootDir>/dist'],

注意点として、dist配下はコミットしないと思いますが、このままではsnapshotテストの結果がdist配下に吐き出されてしまいます。
jestによって生成されたsnapshotのみ、もとのtsファイルのそばに配置したい場合は snapshotResolver を設定します。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?