プラグインの開発

Karmaはプラグインによって拡張できます。プラグインには、_フレームワーク_、_レポーター_、_ランチャー_、_プリプロセッサ_、_ミドルウェア_の5種類があります。それぞれのタイプは、Karmaの動作のある側面を変更することを可能にします。

  • _フレームワーク_は、テストフレームワーク(Mochaなど)をKarma APIに接続し、ブラウザがテスト結果をKarmaサーバーに送り返せるようにします。
  • _レポーター_は、テスト結果がユーザーにどのように報告されるかを定義します。
  • _ランチャー_は、Karmaがテストを実行するために異なるブラウザを起動できるようにします。
  • _プリプロセッサ_は、ソースファイルをブラウザにロードする前に変換/トランスパイルする役割を担います。
  • _ミドルウェア_は、ブラウザにファイルを提供する方法をカスタマイズするために使用できます。

依存性注入 #

Karmaは_依存性注入_を使用して組み立てられています。プラグインを開発するためには、この概念を理解することが重要です。

非常に高いレベルでは、Karmaを、各キー(_DIトークン_)が特定のKarmaオブジェクト(_サービス_)にマッピングされたオブジェクトと考えることができます。たとえば、`config` DIトークンは、現在のKarma設定を保持する`Config`インスタンスにマッピングされます。プラグインは、対応するDIトークンを指定することで、さまざまなKarmaオブジェクトを要求(または_注入_)できます。注入されると、プラグインは注入されたサービスと対話して機能を実装できます。

利用可能なすべてのサービスとそのDIトークンの網羅的なリストはありませんが、Karmaまたは他のプラグインのソースコードを読むことで、それらを発見できます。

プラグイン構造 #

各プラグインは、本質的に、関連付けられたDIトークンを持つサービスです。ユーザーが設定でプラグインをアクティブ化すると、Karmaは対応するDIトークンを探し、このDIトークンにリンクされたサービスをインスタンス化します。

プラグインを宣言するには、プラグインのDIトークンを定義し、Karmaにそれをインスタンス化する方法を説明する必要があります。DIトークンは、プラグインタイプとプラグインの一意の名前の2つの部分で構成されます。前者は、プラグインが何をすることができるか、サービスのAPIへの要件、いつインスタンス化されるかを定義します。後者は一意の名前であり、プラグインユーザーはプラグインをアクティブ化するために使用します。

プラグインが複数のサービスを定義することは完全に有効です。これは、プラグインによってエクスポートされたオブジェクトにキーを追加することによって行うことができます。この一般的な例は、通常一緒に提供される`framework` + `reporter`プラグインです。

インスタンス化されたときに「Hello, world!」を出力する非常に単純なプラグインを作成してみましょう。Karmaライフサイクルの初期にインスタンス化され、APIに何の要件もないため、`framework`タイプを使用します。プラグインを「hello」と呼ぶことにしましょう。そうすると、一意の名前は`hello`になります。これら2つの部分を結合すると、プラグイン`framework:hello`のDIトークンが得られます。それを宣言しましょう。

// hello-plugin.js

// A factory function for our plugin, it will be called, when Karma needs to
// instantiate a plugin. Normally it should return an instance of the service
// conforming to the API requirements of the plugin type (more on that below),
// but for our simple example we don't need any service and just print 
// a message when function is called.
function helloFrameworkFactory() {
  console.log('Hello, world!')
}

module.exports = {
  // Declare the plugin, so Karma knows that it exists.
  // 'factory' tells Karma that it should call `helloFrameworkFactory`
  // function and use whatever it returns as a service for the DI token
  // `framework:hello`.
  'framework:hello': ['factory', helloFrameworkFactory]
};
// karma.conf.js

module.exports = (config) => {
  config.set({
    plugins: [
      require('./hello-plugin')
    ],
    // Activate our plugin by specifying its unique name in the 
    // corresponding configuration key.
    frameworks: ['hello']
  })
}

依存性の注入 #

「依存性注入」セクションでは、任意のKarmaサービスをプラグインに注入して対話できることを説明しました。これは、プラグインのファクトリ関数で`$inject`プロパティを、プラグインが対話したいDIトークンの配列に設定することによって行うことができます。Karmaはこのプロパティを取得し、要求されたサービスをパラメータとしてファクトリ関数に渡します。

`hello`フレームワークをもう少し便利にして、`hello.js`ファイルを`files`配列に追加してみましょう。こうすることで、プラグインのユーザーは、たとえば、テストから`hello.js`で定義された関数にアクセスできます。

// hello-plugin.js

// Add parameters to the function to receive requested services.
function helloFrameworkFactory(config) {
  config.files.unshift({
    pattern: __dirname + '/hello.js',
    included: true,
    served: true,
    watched: false
  })
}

// Declare DI tokens plugin wants to inject.
helloFrameworkFactory.$inject = ['config']

module.exports = {
  'framework:hello': ['factory', helloFrameworkFactory]
};

Karmaの設定は変更されておらず、簡潔にするために省略されています。プラグインの使用法については、上記の例を参照してください。

注記

現在、KarmaはDI実装としてnode-diライブラリを使用しています。ライブラリは上記で説明されているものよりも強力ですが、DI実装は将来変更される可能性があるため、node-di実装の詳細に依存しないことをお勧めします。

プラグインの種類 #

このセクションでは、さまざまなプラグインタイプのAPI要件と規則について概説します。インスピレーションを得るために使用できるいくつかのプラグインへのリンクもあります。

フレームワーク #

フレームワークは、既存のテストライブラリをKarmaのAPIに接続するため、その結果をブラウザに表示してサーバーに送り返すことができます。

Karmaフレームワークは、Karmaがテスト実行を開始するために呼び出す`window.__karma__.start`メソッドを_実装する必要があります_。この関数は、結果をkarmaに送り返すためのメソッドを持つオブジェクトを使用して呼び出されます

  • `.result` 単一のテストが終了しました
  • `.complete` クライアントはすべてのテストの実行を完了しました
  • `.error` クライアントでエラーが発生しました
  • `.info` その他のデータ(テストの数やデバッグメッセージなど)

最も一般的には、`result`メソッドを使用して、個々のテストの成功または失敗のステータスを送信します。メソッドは次の形式のオブジェクトを取ります

{
    // test id
    id: String,

     // test description
    description: String,

    // the suite to which this test belongs. potentially nested.
    suite: Array[String],

    // an array of string error messages that might explain a failure.
    // this is required if success is false.
    log: Array[String],

    success: Boolean, // pass / fail

    skipped: Boolean // skipped / ran
}

レポーター #

ランチャー #

プリプロセッサ #

プリプロセッサは、3つの引数(`content`、`file`、`next`)を受け取り、何らかの方法でコンテンツを変更し、次のプリプロセッサに渡す関数です。

  • プリプロセッサプラグインに渡される引数
    • **`content`** 処理されるファイルのコンテンツ
    • **`file`** 処理されるファイルを表すオブジェクト
      • **path:** 現在のファイル、変更可能なファイルパス。例:`some/file.coffee` -> `some/file.coffee.js` _このパスは変更可能であり、実際には存在しない場合があります。_
      • **originalPath:** 元の変更されていないパス
      • **encodings:** 変更可能なキー付きオブジェクト。キーは有効なエンコーディングタイプ( 'gzip'、 'compress'、 'br'など)であり、値はエンコードされたコンテンツです。エンコードされたコンテンツはここに保存し、`next(null, encodedContent)`を使用して解決しないでください
      • **type:** ファイルを提供するときに、ファイルを含める方法を決定します
    • **`next`** 前処理が完了したときに呼び出される関数。`next(null, processedContent)`または`next(error)`として呼び出す必要があります

より高度な処理 #

Karmaは依存性注入によって組み立てられるため、プラグインはほぼすべてのKarmaコンポーネントを要求して対話できます。このような、より興味深い処理を行うプラグインがいくつかあります。karma-closurekarma-intellijを確認してください。