Siesta – No.3 非同期処理とグローバルスコープの汚染チェック
Siestaには、今後紹介する操作のシミュレーションなど強力な機能がたくさんあります。 前回は、アサーションについて学びましたが、引き続き、非同期処理への対応の仕方と、グローバルスコープの汚染チェックについて、今回は学んでいきます。
グローバルスコープの汚染チェック
JavaScriptでプログラムを組んでいると、どうしても知らないうちに、グローバルスコープへプロパティを追加してしまっていたりすることがあります。 単純にvarの付け忘れだけでも、グローバルスコープは汚染されていくのです。
これらを未然に防ぐために、テストクラスには、verifyGlobalsというメソッドが用意されています。 このメソッドを呼び出すと、テスト開始時とテスト終了後のグローバルスコープのプロパティキーを比較して、新たにグローバルスコープにプロパティが追加されているとFailを発生させてくれます。
verifyGlobalsは、自分で呼び出しても良いのですが、ハーネスの設定でautoCheckGlobalsをtrueに設定することで、自動的に実行されます。
このままだと、グローバルスコープに、意図的にプロパティを追加した場合でも、Failが発生してしまいます。 そのため、意図的にグローバルスコープにプロパティが追加されるときは、expectGlobalsメソッドを利用して、予めプロパティ名を登録しておくことで、Failになりません。 expectGlobalsメソッドには、グローバルスコープに追加されても問題の無いとするキー名を、引数に設定して実行します。expectGlobalsで設定する以外に、verifyGlobalsの引数に設定することも可能です。
020_global_variables.t.js
1 2 3 4 5 6 7 8 9 10 11 12 | StartTest(function(t) { t.diag("グローバルスコープチェック"); window.hoge = 1; sage = 2; // t.expectGlobals('hoge', 'sage'); // t.verifyGlobals(); t.verifyGlobals('hoge', 'sage'); }); |
非同期処理
Ajaxリクエストや、setTimeoutなど、非同期処理のテストを行う場合に、beginAsyncメソッドと、endAsyncメソッドが用意されています。非同期処理を開始する前に、beginAsyncメソッドを呼び出して、フレームオブジェクトといわれるendAsyncの引数に利用するIDのようなオブジェクトを取得します。非同期処理が完了した時点で、フレームオブジェクトを引数に設定してendAsyncメソッドを呼び出します。 一定の時間内に、endAsyncが呼び出されない場合は、エラーが送出されます。
021_async.t.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | StartTest(function(t) { var asyncFunc1 = function(a, b, callback, err) { setTimeout(function () { var res = a + b; if(isNaN(res)) { err(res); } else { callback(res); } }, 100); }; var asyncFunc2 = function () { var async2 = t.beginAsync(); asyncFunc1(1, {}, function () { t.fail('ここには、来ないはず。'); }, function (res) { t.ok(isNaN(res), '1 + {} は、NaNになります。'); t.endAsync(async2); }); } var async1 = t.beginAsync(); asyncFunc1(1, 2, function(res) { t.is(res, 3, '1 + 2 = 3'); t.endAsync(async1); asyncFunc2(); }, function() { t.fail('ここには、来ないはずです。'); }); }); |
beginAsyncメソッドと違い、wait/endWaitメソッドは、引数に文字列でIDを指定し、非同期の開始と終了を明示的に記述します。 beginAsyncメソッドの場合は、endAsyncが一定の時間内に呼び出されればエラーとなりませんでしたが、waitメソッドは、明示的に非同期が完了した時点で呼び出す必要があります。endWaitメソッドが呼び出されるまで、Siestaは、テストを中断し待ちます。
022_wait.t.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | StartTest(function(t) { t.wait("xcalc") var x = 0; setTimeout(function() { t.is(x, 1, 'Xは、加算されています。') t.endWait("xcalc"); }, 1000); // 加算処理 x++; }); |
まとめ
グローバルスコープの汚染は、JavaScriptでプログラムを組んでいる以上、避けられない、かつ注意深くチェックしたい項目です。autoCheckGlobalsをtrueに設定して、常にテストケースでverifyGlobalsが実行されるよう、ハーネスに設定することをオススメします。
また、Sencha Ext JS、Sencha Touchを利用している場合、クラスシステムの動的ローディングは切っても切り離せない重要な仕組みになり、この仕組みは非同期でソースコードが読み込まれていきます。そんなクラスのチェックや、もちろん通常のXHRオブジェクトによるAJAX通信のテストなど、最近では同期だけで処理が終わることは少なくなってきているのかもしれません。beginAsyncメソッドや、waitメソッドを有効に利用して、非同期処理のテストケースもスマートに記述していきましょう。
次回は、ブラウザ内でのユーザーインタラクションをSiestaを通してシミュレーションします。 SiestaのUIテストの本領発揮といったところでしょうか。実際に、クリックさせたりキーボードをおさせたりするシナリオを用意して、いつでも何度でも実行できるのがSiestaのUIテストの強みです。 その、シミュレーションに関して、具体的なコードを確認しながら、シミュレーションを実際に行って見ましょう。
今回のテストケースは、以下のURLで確認できるように設置してあります。
http://preview.xenophy.com/xenophy/senchaug/bryntum/siesta/no3/harness.html