JavaScriptはダイナミックタイプの言語であり、彼女の強力なパフォーマンス能力を提供しますが、コンパイラを開発者にヘルプを提供することもほとんど不可能になります。このため、JavaScriptコードを作成することで、強力で完全なテストセットが必要だと感じています。 Angularには、アプリケーションをテストしやすくする多くの機能があります。テストを書かないという言い訳はありません(これは...)。
1.それはすべての懸念を混合しないことです(コード関係が複雑になることを避けることがすべてです...)
名前としての単位テストは、単一の「ユニット」をテストすることです。ユニットテストは、これらの質問に答えるよう努めています。私はすでに私の論理に関する考慮事項で正しいですか?ソートメソッドによって得られた結果は正しいですか?これらの質問に答えるには、それらを分離することが特に重要です。これは、ソートメソッドをテストしている場合、DOM要素など、他の関連するフラグメントを気にしたり、XHRリクエストを開始してデータを取得するなどです。明らかに、通常、典型的なプロジェクトで機能を個別に呼び出すことは困難です。この問題の理由は、開発者がしばしば関係を複雑にし、すべてができるようにスニペットを見せることになっているからです。 XHRを介してデータを取得し、データをソートしてから、DOMを操作します。 Angularとともに、より良いコードをより簡単に書き込むことができるため、AngularはXHRの依存噴射を提供し(シミュレートできます)、AngularはDOMを操作することなくモデルをソートできる抽象化を作成します。したがって、最後に、ソートメソッドを単純に記述し、テスト時に使用するソートメソッドのテストケースを介してデータセットを作成し、結果モデルが期待を満たしているかどうかを判断できます。このテストでは、XHRが対応するDOMを作成し、関数がDOMを正しく動作させるかどうかを判断するのを待つ必要はありません。 Angularの中心的なアイデアには、コードのテスト可能性が含まれていますが、正しいことをする必要もあります。 Angularは正しいことをする方法を簡素化することに取り組んでいますが、Angularは魔法ではありません。つまり、次のポイントに従わないと、テスト不可能なアプリケーションになってしまう可能性があります。
1。依存関係注入
依存関係リソースを取得するには多くの方法があります。1)新しいオペレーターを使用できます。 2)「Global Singleton」と呼ばれる有名な方法を使用します。 3)レジストリサービスからリクエストできます(ただし、レジストリを取得するにはどうすればよいですか?次の章を確認できます)。 4)渡されると期待できます。
上記の方法のうち、最後の方法のみがテスト可能です。理由を見てみましょう。
1)新しいオペレーターの使用
新しいオペレーターを使用する場合、基本的にエラーはありませんが、問題は、新しいオペレーターを介してコンストラクターを呼び出すと、発信者がタイプに永久にバインドすることです。たとえば、サーバーからデータを取得できるように、XHRオブジェクトをインスタンス化しようとします。
function myclass(){this.dowork = function(){var xhr = new Xrh(); xhr.open(Method、url、true); xhr.onedeadystatechange = function(){…}; xhr.send(); }}問題は、テスト時に、テストデータまたはネットワークエラーを返すことができる仮想XHRをインスタンス化する必要があることです。 new XHR()を呼び出すことで、実際のXHRに永久にバインドしますが、それを交換する良い方法はありません。もちろん、悪い治療法があり、それが悪い考えであることを証明する多くの理由があります:
var oldxhr = xhr; xhr = new mockxhr(){}; myclass.dowork(); // mockxhrが通常のパラメーターを使用してxhr = oldxhrを呼び出すかどうかを判断します; //この手順を忘れた場合、悲しいことを引き起こすのは簡単です。2)グローバルルックアップ
問題を解決する別の方法は、よく知られている場所で依存関係リソースを取得することです。
function myclass(){this.dowork = function(){global.xhr({…}); };}新しい依存オブジェクトのインスタンスを作成しないと、問題は基本的に新しいものと同じであり、テスト時にGlobal.xhrコールをインターセプトする良い方法はありません。テストの最も基本的な問題は、仮想メソッドを呼び出すためにグローバル変数を変更し、変更する必要があることです。その短所の詳細については、http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/をご覧ください。
上記のコードをテストするのは難しいため、グローバル状態を変更する必要があります。
var oldxhr = global.xhr; global.xhr = function mockxhr(){…}; var myclass = new myclass(); // mockxhrがglobal.xhr = oldxhrを呼び出すかどうかを判断します;3)サービスレジストリ
すべてのサービスにレジストリを持つことは、問題を解決し、テストコードで必要なサービスを置き換えるようです。
function myclass(){var serviceregistry = ???; this.dowork = function(){var xhr = serviceregistry.get( "xhr"); …};}しかし、サービスはどこから来たのでしょうか?それが次の場合: *新しくて、テストはテストのためにサービスをリセットする機会がありません *グローバルルックアップのために、返されるサービスもグローバルです(ただし、リセットは1つのグローバル変数しかリセットされません)(ここのテキストはガレッドと同じです...私は理解していませんでした)
この方法によると、上記のクラスを次の方法に変更します。
var oldservicelocator = global.servicelocator; global.servicelocator.set( 'xhr'、function mockxhr(){}); var myclass = new myclass(); myclass.dowork(); // mockxhrがglobal.servicecorator = oldservicecorator; //このステップを忘れた場合、悲しいことを引き起こすのは簡単です。4)依存関係を渡す
最後に、依存関係リソースを引き継ぐことができます。
function myclass(xhr){this.dowork = function(){xhr({…}); };}これは、コードがXHRがどこから来たのかに注意を払う必要がないため、XHRを作成したXHRを誰が渡すかを気にする必要がないため、これは好ましい方法です。したがって、クラスの作成者はクラスの消費者とは別にエンコードできます。
このクラスはテストが簡単で、このようにテストで書くことができます。
関数xhrmock(args){…} var myclass = new myclass(xhrmock); myclass.dowrok(); //いくつかの判断を下す...このテストコードを通して、グローバル変数が破損していないことを認識できます。Angularに含まれている依存関係 - injection(//www.vevb.com/article/91775.htm)は、このように記述されたコードを使用すると、テストコードの作成が容易になります。テスト可能なコードを書きたい場合は、使用する方が適切です。
2。コントローラー
ロジックはすべてのアプリケーションをユニークにし、それがテストしたいことです。ロジックがDOM操作と混合されている場合、これは次の例と同じくらいテストするのが難しいでしょう。
function passwordcontroller(){// domオブジェクトへの参照を取得var msg = $( '。ex1 span'); var input = $( '。ex1 input'); var強度; this.grade = function(){msg.removeclass(strength); var pwd = input.val(); password.text(pwd); if(pwd.length> 8){strength = 'strong'; } else if(pwd.length> 3){strength = 'medium'; } else {strength = 'weak'; } msg.addclass(強さ).text(強さ); }}上記のコードは、テストの実行時に正しいDOMを使用する必要があるため、テスト時に問題が発生します。テストコードは次のとおりです。
var input = $( '<input type = "text"/>'); var span = $( '<span>'); $( 'body')。html( '<div')。( 'div')。 PasswordController(); input.val( 'abc'); pc.grade(); expect(span.text())。
Angularでは、コントローラーはDOM操作ロジックを厳密に分離します。これにより、テストケースを作成することの難しさが大幅に軽減されます。次の例を見てください。
関数passwordcntrl($ scope){$ scope.password = ''; $ scope.grade = function(){var size = $ scope.password.length; if(size> 8){$ scope.strength = 'strong'; } else if(size> 3){$ scope.strength = 'medium'; } else {$ scope.strength = 'weak'; }};}テストコードは簡単です:
var pc = new PasswordController($ scope); pc.password( 'abc'); pc.grade(); expect($ scope.strength).toequal( 'weak');
テストコードはより不連続であるだけでなく、追跡しやすいことは注目に値します。私たちは常に、テストケースが他の無関係なことを判断しているのではなく、物語を語っていると言ってきました。
3。フィルター
フィルター(http://docs.angularjs.org/api/ng.$filter)は、データをユーザーフレンドリー形式に変換するために使用されます。それらは、形式をアプリケーションロジックから変換する責任を分離し、アプリケーションロジックをさらに簡素化するため、重要です。
mymodule.filter( 'length'、function(){return function(text){return( ''+(text || ''))。}}); var length = $ filter( 'length'); aequal(equal( 'and(null))。4。指令
5。モック
6。グローバルな状態隔離
7.優先テスト方法
8。JavaScriptTestDriver
9。ジャスミン
10。サンプルプロジェクト
将来、関連記事を更新し続けます。このサイトへのご支援ありがとうございます!