MochaでJavascript以外を指定してテストしたい

Node.js用テスティング環境であるmochaでは、compilersオプションを指定することにより、Javascript以外のコードも扱えるみたいです。 が、しかし、公式のマニュアルを読んでも、さっぱりやり方が分からなかったので、がんばってMochaのコードを追いかけてみました。

compilerオプションについて

compilerオプションでは、

"拡張子":"コンパイルモジュール"

を指定します。 これは、指定した拡張子のファイルに遭遇したら、指定したコンパイルモジュールでJavascriptにコンパイルしてね というおまじないになります。 規定では、.js のみが対象となっています。

Mochaは、テスト対象のフォルダを再帰的に走査して、遭遇したファイルが.jsと指定された拡張子以外であれば、無視するような仕掛けとなっています。

Node.jsでJavascript以外を扱う仕組み

対象の拡張子のファイルに遭遇すると、Mochaは、そのファイルをrequireで読み込もうとします。 Node.jsのマニュアルで require を調べると、

  • .js
  • .json
  • .node

が読み込み対象と書かれています。 ではそれ以外のファイルがきた時は、どうなってしまうのでしょう?

Node.jsでは、上記以外のファイルの場合、require.extensions からの読み込みを試みます。 require.extensionsは、拡張子をキーに、指定されたファイルをJavascriptに変換する関数が登録された辞書です。

この関数の型は、

1
2
3
function (module, filename) {
  ...
}

となっており、ここで、

  • module - Moduleモジュール
  • filename - 読み込むファイル名

Mochaに渡すコンパイルモジュールの仕様

仕様と言えるような、大それたものはなく、Javascriptに変換する関数を実装し、それを単に上述のrequire.extensions に追加するだけです。

この関数の実装において、一つ重要な点があります。 それは、Javascriptのコードに変換後、module._compile(<変換されたコード>)という非公開の関数を呼ぶということです。

この module._compile が呼ばれることで、ロードが完了する仕組みとなっているようです。

requireの呼び出し元は、module._compileが呼ばれるまで、ブロックされるようになっているため、Javascriptへの変換関数が非同期的に実装(fs.readFile等)されていても、まったく問題ないです。

変換関数の具体的な実装は、coffee-scriptモジュールを読んでみるよいでしょう。

例:Haxeの場合

Haxeには、mocha.js-haxeという、Mocha用のコードに変換するための拡張ライブラリが公開されています。 そこで、Haxeのオプション記述ファイル(.hxml)に対してコンパイルモジールを作成しておけば、MochaでHaxeのコードを直接テストできるようになります。

Javascriptへの変換関数関数の仕様として、

  1. child_processモジュールのexec関数で、hxmlファイルを渡して、HaxeのコードをJavascriptコンパイルする。
  2. コンパイルしたファイルを、fsモジュールのreadFile(またはfs.readFileSync)で読み込んで、コードを取得する。
  3. module._compileにそのコードを渡す。

とすれば、よいでしょう。