最近のライブラリはatom-mocha-test-runnerでJasmineの呪縛から逃れている

[Atomアドベントカレンダー2017](https://qiita.com/advent-calendar/2017/atom)の1日目の記事です。

2016年のアドベントカレンダーで[Atomパッケージのテストの書き方を紹介](https://qiita.com/Kesin11/items/a66a2b49571b05deb430)したのですが、あの頃よりもテスト環境が進化しているので今年のアドベントカレンダーではその進化について紹介します。

今までのAtomのテスト環境はJasmine 1.3を独自に拡張したものでした。
Atomが出た当時のCoffeeScriptが流行っていた頃はおそらくピカピカだったのでしょう。ですが非同期処理のテストのためにasync/awaitをサポートしたmochaと、should/assert/expectといったアサーションから好みのものを選択できるchaiが一般的となった現代からすると残念ながら時代遅れと言わざるを得ません。

特にここ最近ではAtomのAPI自体が非同期対応のために徐々にPromiseを返すように変わってきており、パッケージがそれらのAPIに依存している場合はパッケージ自体に加えてテスト側でもPromiseに対応する必要があります。
Atom内部のV8のバージョンが上がったことでパッケージ本体ではasync/awaitが使えるようになったのですが、テストについてはフレームワークの問題でasync/awaitが使えないので段々とテストコードのメンテが辛くなってきていました。

何か良い方法はないものかと探しているうちに、最近のAtomコアモジュール周りではatom-mocha-test-runnerというモジュールを使ってJasmineを脱出していることを発見しました。

## atom-mocha-test-runnerとは
https://github.com/BinaryMuse/atom-mocha-test-runner

昔のissue([#13899](https://github.com/atom/atom/issues/13899),[#8968](https://github.com/atom/atom/pull/8968))を見たところ、Atom本体のテストフレームワークをリプレースするのは一旦諦めてpackage.jsonの`atomTestRunner`で指定した別のテストランナーを使えるように拡張が行われたようです。

テストランナーは[仕様](https://flight-manual.atom.io/hacking-atom/sections/writing-specs/#customizing-your-test-runner)を満たす必要があるので既にjsで有名なmochaなどを単に持ってくるだけでは動きません。
atom-mocha-test-runnerはその仕様を満たす、mochaでテストを実行できるテストランナーを簡単にビルドするためのモジュールです。
まさにAtomパッケージのテスト界における救世主というわけです。

## 使い方
詳しい使い方はアドベントカレンダーの別の日に改めて投稿する予定ですので、今回は最も簡単な使い方を紹介します。

まず、atom-mocha-test-runnerとchaiをdevDependenciesとしてインストールします。
`npm i -D atom-mocha-test-runner chai`

次にpackage.jsonに`"atomTestRunner": "atom-mocha-test-runner"`を追加します。

さらにspec/にある`**spec.js`を`**.test.js`にリネームします。これはatom-mocha-test-runnerが`.test.js`または`.test.coffee`の拡張子のファイルをテストとして認識するためです。

ではいよいよテスト自体をmochaとchaiを使って書き換えていきましょう。
今まで非同期処理を待つために使われていた`waitsForPromise()`と`runs()`をmochaの[非同期テストの構文](https://mochajs.org/#asynchronous-code)に置き換えます。`expect(...).toBe(true)`といった独自のアサーションは`expect(...).to.be.true`といったchaiの書き方に直す必要があります。
expectが好みでなければassertに変えても良いでしょう。mochaが使えるようになったことでアサーションに関しては好みのものが使用可能です。
ちなみにmochaはimportする必要がありませんが、chaiはそれぞれのテストの中で`import { expect } from 'chai'`をしておく必要があるので注意です。

最後にテストの実行方法ですが、今まで通り`apm test`でテストを実行可能です。
もしspec/というディレクトリ名をtest/に変えたい場合は代わりに`atom --test test/`を実行することでテストを走らせることができます。  
atom-mocha-test-runnerに対応したパッケージを見るとspec/からtest/にリネームして、package.jsonのscriptsに`atom --test test/`を追加し`npm test`でテストを実行できるようにしているものが多いようです。

## 実例
自分が探した中ではAtomのコアパッケージであるwelcomeとgithubが参考になりました。

[welcome](https://github.com/atom/welcome/tree/v0.36.5)[^1]
今回紹介したpackage.jsonに`"atomTestRunner": "atom-mocha-test-runner"`を指定するシンプルな方法です。
リポジトリの規模が小さいので参考にしやすいはずです。

[github](https://github.com/atom/github/tree/v0.8.2)[^2]
atom-mocha-test-runnerのデフォルト設定を使わずに、runner.jsでオプションを渡して挙動をカスタムしています。
runner.jsを使うパターンは別のエントリで紹介する予定です。

他にもGithub上でatomのorganizationの中で[検索](https://github.com/search?q=org%3Aatom+atom-mocha-test-runner&type=Code)するとatom-mocha-test-runnerを使っているパッケージを見つけることができます。

## まとめ
パッケージのテストランナーとしてatom-mocha-test-runnerを使うことで古いJasmine1.3の呪縛から逃れる方法を紹介しました。

今回のエントリでは紹介がメインでしたが、アドベントカレンダーの別の日のエントリで実際にatom-mocha-test-runnerに対応させる実践編の紹介をする予定です。こうご期待！

[^1]: masterブランチだと将来変わっている可能性があるのでv0.36.5のタグのurlにしています
[^2]: こちらも同様にv0.8.2のタグのurl