2018年にNode.jsとIEとEdgeとFirefoxとChromeとSafariとElectronとNW.jsでTypeScript+mocha+power-assertな単体テストをカバレッジ付きで走らせたメモ
-- 2018/01/03 12:05
元旦に思い立って表題の通りにする過程で色々調べたメモ。TypeScript+色々系はいまいちまとまったのがないので参考になれば。
背景
上記全環境で動作予定がある、小規模だけど少しめんどくさい処理をするライブラリ(lazy-event-router イカガカプロジェクト用)を書いてたので、CI謎テストこけを直しついでに今風に刷新することにした。
できるだけデフォルトに沿い極力設定を書かない方針でいった。個人的にあんま使わないのでwatch系はなし。タスクランナーはnpm scripts。
本体コード
コードは全部TypeScriptで、babelは使わずtscとwebpackだけでES2015とES5(IE用)にトランスパイルする基本構成に。
tsconfigにtargetがes5になってもes2015のライブラリは使えることを示すために"lib"を記述しておくところと、webpackで使う時に型定義出力先となるoutDirを変えているところがポイント。
ここでは使っていないがJSXもtsconfigに書けば基本babel不要でいけるので、インストール量を減らしてゆこう。
テストとカバレッジ
テストはpower-assertとmochaで、node.jsではカバレッジは
nyc mocha
で取れるように構成する。が、まずココにはまりポイントがある。
WebpackとBabelなしのTypeScript環境でpower-assertを使う自然な選択肢としてespower-typescriptを使うが、そのまま何の気なしにmocha.optsに--require espower-typescript/guess --recursive test/*.tsと書いても、カバレッジの%は出るのになぜかlcovやhtml出力にエラーが吐かれることになる。
これはespower-typescriptのissueに上げられており、tsconfig.jsonにsourceRootを指定することで解消する。
ただしこれを指定すると今度はtypedocのほうがsourceRoot指定するなとエラーを吐いてくるのでめんどくさい。こちらもtypedocのissueに回避方法が載ってはいるが無理矢理過ぎるので、現状は仕方なくtypedocを実行するときだけ手動で外すかなと思っている。(回数は多くないし)
とりあえずここまででnode.js上でTS+mocha+power-assertをカバレッジ付きで開発できる。
ブラウザ実働テスト必要ない場合はこれで終わって良い。
Karma
次にブラウザでのテストだが、単体テストだけすれば良い感じのライブラリなのでKarmaを使う。
フレームワークはmocha。karma-webpackでTSトランスパイルからバンドルまで行い、karma-sourcemap-loaderでカバレッジ用にソースマップを受け流し、karma-espower-preprocessorでespowerしてからテストする。
カバレッジレポートはkarma-coverageを使う。
karma-coverageはカバレッジ集計も担う機能があるが、今回Webpackを使う関係でそれは使えない(Webpackだとkarma.confのfilesにテストファイルのみ指定するので、カバレッジ集計対象がそこから取れないためっぽい)。なのでwebpack.config.test.jsを作ってwebpackの時点で集計を食わせることで動作させる。
espowerもwebpackの時点で食わせる方法があるが、webpack1時代にそれでハマったことがあり、今回試していない。そっちでも普通に出来るかもしれない。
ちなみにIEだけES5で食わせる必要があるのでkarma.conf.es5.jsを作って別立てでもう一回karmaを走らせている(webpack設定を読むときの副作用でes5設定にする雑な感じ)。
ここでのハマりポイントは"mime"プロパティの指定。
IE以外のブラウザではこの指定が無いと.tsファイルがブラウザにスクリプトとして解釈されず、テストケース自体が0という表示になって何事も無く終了するのでたちが悪い。「この設定でIEでは正しく動いているの」という心のよりどころのおかげでハマり時間が少なくてよかった。angularのissueなどに解があった。
なおkarma-detect-browsersは古くから愛用しており、launcher系さえ入れておけばいい感じにブラウザを立ててくれる(WindowsならIEとEdge、MacならSafariも走る)。なおカスタマイズでIEのみを省いたり、自動検出スキップできるようにしたり、Chromeをせっかくだからheadlessにしたりしている。PhantomJSとはおさらば。いままでありがとう。
AppVeyor・Travis
ここでブラウザを使うことで若干ややこしくなるのがTravisの設定。
appveyor.ymlは追加でIE決め打ちテストを走らせるためにnpm run test-winにしているくらい。FirefoxもChromeも入っているし普通にGUI上で走るので目立った設定は不要だ。
.travis.yml、まずLinuxでGUIアプリケーション(Firefox)を走らせるためにDISPLAY設定したりxvfbを立ち上げて立ち上がるまでてきとうにsleepするという設定が入っている。これはTravisのGUI and Headless Browser Testingの通り。
さらにLinux/Mac両方でFirefoxとChromeを使いたいためaddonsでインストールを指定する。
これもTravisのFirefoxとGoogle Chromeの項のとおり。
LinuxのChromeインストールのためにdist: trustyも忘れずに。
あとcodecovがカバレッジをWebで見られるようにしてくれるのでafter_successにそれを指定している。
コンソールアプリケーションだけの時より多少複雑にはなるが、まあこれくらいはいいはず。
昔と比べて大分シンプルに書けるようになった。
とりあえずここまでで一般的なブラウザ(AppVeyorが未対応のEdgeを除く)をWindows/Linux/Mac環境のCIで走らせる設定まで完了した。
一般的なライブラリならこのあたりで終わって良いかも。
Electron
これがくせ者だった。
同じくKarmaでWebpackでブラウザ用にバンドルすればまあ動くのだが、テストしたいのはrequireを使うElecctronらしい利用法。
まずkarma-electron-launcherを試すがmochaが正しく読まれない。
karma-electronがパスをゴニョるとかしてなんとかするらしいのでこちらを使うもWebpackでtargetをelectron-rendererにするとrequireを上書きする挙動と相性悪いらしく無限ループしてコールスタック使い切る。
Webpackを使わない道として、(karma-typescriptはごてごてしていて訳が分からんので避ける形で)karma-typescript-preprocessorを使ってみるが、冒頭に差し込まれるexportsを参照するコードがアウト。requireだけのコードをfilesに指定してみるも、webpackを通していないのでrequire先のtsファイルが解決できずアウト。
他色々試したが軒並みしんどいので、最終的にKarmaを使わずelectron-mochaを使う形でお茶を濁すことに。
見た目シンプルだがnycと相性が悪いようで簡単にはカバレッジが取れないらしく(issueがあるが要領を得ない)、そこについては断念した。
NW.js
意外にもelectronより辛くなかった。
利用者が少ないのか探してもコマンドラインベースでのテストについてロクな情報が出てこない(mochaのヘルプにGUIでの事例はある)中、ほとんどユーザーのいないkarma launcherに望みを繋いだらなんとかなった。
Webpackと連携する構成じゃないとまたexportsとかで死ぬので、とりあえずWebpackのターゲットをnode-webkitにするべくwebpack.config.test.nwjs.jsを作る。
Karmaのランチャーはkarma-nwjs-launcherを使い、readmeに書かれているNWJSConfigエントリの内容を省略すること無く記述し、その内部で使っていながら依存関係に記述されてないcopyをインストールし、さらにmochaがロード時にエラーになるのをnode.jsのglobal変数を無理矢理待避させて回避するkarma-nodewebkit-mochaをkarma-mochaの代わりに噛ませて、karma.conf.nwjs.jsを作る。
これで一応動作し、他のWebブラウザ同様普通にカバレッジまで出せるようになる。
なんか全体的に危なっかしい感じだけれど、調べた限りおそらくこれが連携用の長大独自コードを書かずにコマンドラインベースでテストできる唯一の方法ではないかと思う。他あったらお知らせ下さい。
npm scripts (package.json)
最後にこれらを(結局人類はMakefileの元に帰る運命にあるのだなと思いながら)npm scriptsに書く。
prepublishも書いておくとビルドし直しわすれが減る。
mainはes2015コードを示し、typesも忘れずに。
上記の通り設定ファイルが沢山出来るので、"files"によるポジティブリスト指定により配布ファイル量も少なくしておく。
以上
とりとめなかったですが、こんな感じで表題の通りの環境が作れます。
昔に比べてTypeScript、Webpack、Karmaのバージョンもそれぞれ上がって周辺環境も洗練され、何点かのハマりポイントを回避すれば格段にシンプルに構築しやすくはなっています。
それでは今年も良いTypeScriptライフを。
- 関連記事
-
- 2018年にNode.jsとIEとEdgeとFirefoxとChromeとSafariとElectronとNW.jsでTypeScript+mocha+power-assertな単体テストをカバレッジ付きで走らせたメモ 2018/01/03
- マスターデータ管理を優しくExcelから解き放つ (ドリコムアドベントカレンダー9日目) 2017/12/09
- TypeScriptでのツクールMVプラグイン制作+α (RPGツクールMV Advent Calendar 4日目) 2017/12/04
- DBD::SQLiteがコアダンプはいてたのなおした 2016/05/15
- 研修で新規ゲームアプリをモデルとビューに分けて作ったり色々したら捗った話 2015/12/20
コメント