3

私はJSファイルに次のようなコードを持っています(もちろん簡略化されています):

$(function () {
  var num;
  $.getJSON('./getNumber.php', function (n) {
    num = n;
  });

  $('#id').on('click', function () { alert(num); });
});

2つの単体テストを作成する必要があります。

  1. ページが読み込まれたときに、スクリプト./getNumber.phpがサーバーにリクエストを送信することを確認してください
  2. #idがクリックされると、アラートが表示されることを確認してくださいnum

明らかに、FakeXmlHTTPRequestが必要で、alert関数をモックします。おそらく、をスパイし$.getJSONます。ただし、2つのアトミックを維持しながらテストを作成する正しい方法がわかりません。

そうすることだけが<script>、各テストのブロックを動的に注入することになると思います。しかし、私はそれが正しくないと感じています。正しい方法は何ですか?ありがとう。

編集:SO以外のコメントに基づいて、私が学ぶ必要があるのは、テスト可能性の低いもののテストケースを考え出すのではなく、テスト可能なJavascriptを作成することです。誰かがこのコードを書き直すことについて私にいくつかのアドバイスを与えることができれば、それも大いに感謝されるでしょう。

4

1 に答える 1

2

あなたの質問に対する正しい答えは1つではなく、学ぶべき多くの良い原則があります。次のコードを検討してください。私はあなたの例をリファクタリングしました。私がしたことすべてを以下に説明します。

// Define your module in a self-executing function.
// This module is now completely unit testable.
var myModule = (function () {
    var num;

    function getNum() {
        $.getJSON('./getNumber.php', function (n) {
            num = n;
        });
    }

    function alertNum() {
        alert(num);
    }

    // this returned object will by set to myModule and will publicly
    // expose the necessary functions
    return {
        getNum: getNum,
        alertNum: alertNum
    };
})();

// wire up your events
$(function() {
    $("#id").on('click', myModule.alertNum);
});

この例は、この単純なコードには明らかにやり過ぎですが、いくつかの良いアイデアが得られるはずです。

  1. これで、コア機能がモジュールにカプセル化されました。モジュール内に追加のプライベート関数と変数(などnum)を保持しますが、返されたオブジェクトを介して公開されているすべてのものをテストできるようになりました。(下記の注を参照)

  2. モジュールの外部でイベントを配線しました。モジュールが大きい場合は、このコードを別のスクリプトに配置することもできます。いずれにせよ、それはよりMVCのようなアプローチであなたの懸念を分離します。このコードのチャンクをテストすることはできますが、実際にテストする必要はありません。これは非常に単純なjQueryである必要があり、テストをラップすることは、jQueryチームによってすでに徹底的にテストされているjQueryライブラリをテストすることにすぎません。

  3. これは奇妙に思えるかもしれませんが、モジュール内でjQueryセレクターを使用しないでください。モジュールに要素が必要な場合は、それを関数パラメーターとして渡します。それをスタブする方法はいくつかありますが、それは本当に面倒であり、懸念を適切に分離していれば必要ないはずです。私のモジュール(またはモジュール内のオブジェクト)のほとんどは、init()ものを渡すことができるメソッドになります。.find()--モジュール内の要素でjQueryのメソッドを使用することを選択する場合もあります。それは、モジュールの特定のニーズに基づいてあなただけが行うことができる判断の呼びかけです。これを行うには、テストでDOM要素のより詳細なモックを実行する必要がありますが、数十の要素をに渡すよりも簡単な場合がありますinit()(代わりにメインコンテナを渡すだけです)。


注:モジュールの管理には、 RequireJSまたは別のAMDモジュールローダーを使用することを強くお勧めします。これmyModuleにより、上記のようなものがグローバル名前空間から除外されます。ただし、QUnitでRequireを設定するのは少し面倒で、単体テストを理解した後で取り組むのが難しいかもしれません。

于 2013-01-09T01:25:56.830 に答える