GitBookjs-primerユニットテストを記述するこのセクションでは、これまで作成したCLIアプリケーションにユニットテストを導入します。ユニットテストの導入と合わせて、ソースコードを整理してテストがしやすくなるようにモジュール化します。前のセクションまでは、すべての処理をひとつのJavaScriptファイルに記述していました。ユニットテストを行うためにはテスト対象がモジュールとして分割されていなければいけません。今回のアプリケーションでは、CLIアプリケーションとしてコマンドライン引数を処理する部分と、MarkdownをHTMLへ変換する部分に分割します。実際にアプリケーションのモジュール化をする前に、CommonJSでのモジュール化について簡単に振り返ります。Node.jsでは、複数のJavaScriptファイル間で変数や関数などをやり取りするために、CommonJSモジュールという仕組みを利用します。CommonJSモジュールからオブジェクトをエクスポートするには、Node.jsのグローバル変数であるmoduleオブジェクトを利用します。module.exportsオブジェクトは、そのファイルからエクスポートされるオブジェクトを格納します。次のgreet.jsというファイルは、greet関数をエクスポートするモジュールの例です。${name}!`;};require関数を使って、指定したファイルパスのJavaScriptファイルをモジュールとしてインポートできます。次のコードでは先ほどのgreet.jsのパスを指定してモジュールとしてインポートして、エクスポートされた関数を取得しています。World!"module.exportsオブジェクトそのものに代入するのではなく、module.exportsオブジェクトのプロパティに代入することでも任意の値をエクスポートできます。次のfunctions.jsというファイルでは、fooとbarの2つの関数を同じファイルからエクスポートしています。console.log("bar関数が呼び出されました");};このようにエクスポートされたオブジェクトは、require関数の戻り値であるオブジェクトのプロパティとしてアクセスできます。次のコードでは先ほどのfunctions.jsをインポートして取得したオブジェクトからfooとbar関数をプロパティとして取得しています。require("./functions");functions.foo();functions.bar();アプリケーションをモジュールに分割するそれではCLIアプリケーションのソースコードをモジュールに分割してみましょう。md2html.jsという名前のJavaScriptファイルを作成し、次のようにmarkedを使ったMarkdownの変換処理を記述します。});};このモジュールがエクスポートするのは、与えられたオプションを元にMarkdown文字列をHTMLに変換する関数です。アプリケーションのエントリーポイントであるmain.jsでは、次のようにこのモジュールをインポートして使用します。console.log(html);});markedパッケージや、そのオプションに関する記述がひとつのmd2html関数に隠蔽され、main.jsがシンプルになりました。md2html.jsはアプリケーションから独立したひとつのモジュールとして切り出され、ユニットテストが可能になりました。ユニットテスト実行環境を作るユニットテストの実行にはさまざまな方法があります。このセクションではテスティングフレームワークとしてMochaを使って、ユニットテストの実行環境を作成します。Mochaが提供するテスト実行環境では、グローバルにitやdescribeなどの関数が定義されます。it関数はその内部でエラーが発生したとき、そのテストを失敗として扱います。期待する結果と異なるならエラーを投げ、期待どおりならエラーを投げないというテストコードを書くことになります。今回はNode.jsの標準モジュールのひとつであるassertモジュールから提供されるassert.strictEqualメソッドを利用します。assert.strictEqualメソッドは第一引数と第二引数の評価結果が===で比較して異なる場合に、例外を投げる関数です。Mochaによるテスト環境を作るために、まずは次のコマンドでmochaパッケージをインストールします。mocha@6--save-devオプションは、パッケージをdevDependenciesとしてインストールするためのものです。package.jsonのdevDependenciesには、そのパッケージを開発するときだけ必要な依存ライブラリを記述します。ユニットテストを実行するには、Mochaが提供するmochaコマンドを使います。Mochaをインストールした後、package.jsonのscriptsプロパティを次のように記述します。testコマンドを実行すると、mochaコマンドでtest/ディレクトリにあるテストファイルを実行します。testコマンドを実行し、Mochaによるテストが行われることを確認しましょう。foundというエラーが表示されます。foundユニットテストを記述するテストの実行環境ができたので、実際にユニットテストを記述します。Mochaのユニットテストはtestディレクトリの中にJavaScriptファイルを配置して記述します。test/md2html-test.jsファイルを作成し、md2html.jsに対するユニットテストを次のように記述します。expected);});it関数で定義したユニットテストは、md2html関数の変換結果が期待するものになっているかをテストしています。test/fixturesディレクトリにはユニットテストで用いるファイルを配置しています。今回は変換元のMarkdownファイルと、期待する変換結果のHTMLファイルが存在します。次のように変換元のMarkdownファイルをtest/fixtures/sample.mdに配置します。サンプルファイルこれはサンプルです。サンプル2そして、期待する変換結果のHTMLファイルもtest/fixturesディレクトリに配置します。gfmオプションの有無にあわせて、expected.htmlとexpected-gfm.htmlの2つを次のように作成しましょう。id="サンプルファイル">サンプルファイル</h1><p>これはサンプルです。id="サンプルファイル">サンプルファイル</h1><p>これはサンプルです。testコマンドを実行しましょう。1件のテストが通れば成功です。(31ms)ユニットテストが通らなかった場合は、次のことを確認してみましょう。test/fixturesディレクトリにsample.mdとexpected.html、expected-gfm.htmlというファイルを作成したかそれぞれのファイルは文字コードがUTF-8で、改行コードがLFになっているかそれぞれのファイルの末尾に余計な改行文字が入っていないかなぜユニットテストを行うのかユニットテストを実施することには多くの利点があります。ユニットテストが可能な状態を保つこと自体に意味があります。実際にテストを行わなくてもテストしやすいコードになるよう心がけることが、アプリケーションを適切にモジュール化する指針になります。ユニットテストには生きたドキュメントとしての側面もあります。ユニットテストはそのモジュールが満たすべき仕様を表すドキュメントとして機能します。中長期的にアプリケーションをメンテナンスする場合にはかかせないものです。よいテストを書くためには、日頃からテストを書く習慣をつけておくことが重要です。まとめこのユースケースの目標であるNode.jsを使ったCLIアプリケーションの作成と、ユニットテストの導入ができました。npmを使ったパッケージ管理や外部モジュールの利用、fsモジュールを使ったファイル操作など、多くの要素が登場しました。これらはNode.jsアプリケーション開発においてほとんどのユースケースで応用されるものなので、よく理解しておきましょう。testコマンドでmochaコマンドを実行できることを確認したmd2html関数のユニットテストを作成し、テストの実行結果を確認した。