一般に、自動化された単体テスト(JUnit、Karmaなど)を書くときは、次のことを目指します。
誰かが言うのを聞いた:
カバレッジと境界条件は単体テストには十分ではありません。コードを変更した場合に破損するように、それらを記述する必要があります。
これは理論的には私にはいいように思えますが、どのように適用すればよいかわかりません。
私の質問は次のとおりですコードが変更されたときに失敗する自動化された単体テストを作成する必要がありますか?変更する場合、どのようにしてください。
あなたの目的は、codeが変更されたときに失敗する単体テストではなく、動作が変更されたときに失敗する単体テストを記述することです。ここでの動作とは、質問に対する適切な応答を返す、またはデータベースに適切なものを保存するなど、メソッドの外部呼び出し元が実行することを望んでいることを意味します。 方法それはそれ自体の内部実装であり、その動作ではありません。
実装ではなく動作をテストすることで、コードをリファクタリングして改善を行い、テストを実行してコードの動作を誤って変更していないかどうかを即座に確認できます。
実際には、この目標を完全に達成することは不可能です。メソッドがある場合:
int add(int x, int y) {
return x + y;
}
必要なだけユニットテストを記述できますが、次のように変更した場合に失敗することはほとんどありません。
int add(int x, int y) {
if(x==10731 && y == -405571) {
return 0;
}
return x + y;
}
ただし、実用的な範囲で完全な行動範囲に近づくために、いくつかの賢明な手順を実行できます。
テストのセットを記述したら、「既存のメソッドと同じくらい簡単で、すべてのテストに合格するが、動作が間違っているメソッドの実装はありますか」と質問します。これは、行動範囲が十分かどうかを確認するための良い目安です。
上記のadd
メソッドの例に示されているように、メソッドに変更を加えて、メソッドに余分なものを追加することを完全に防ぐことはできません。しかし、はるかに可能性が高いですが、複雑さを増すことなく、パーツを変更または削除することでバグがこっそり入り込むでしょう(なぜ、複雑さを増すような方法で何かをリファクタリングするのですか?)。したがって、「少なくとも同じくらい単純な」条件を追加することで、実際に達成可能なものを取得できます。
与えられた答え-これは間違ったやり方であり、優れたテストのすべての原則に違反している-は正しいです。
しかし、これはプログラミングです。もっとも奇妙なリクエストであっても、常にsomeの合理的な根拠があり、それらを検討することは生産的です。
重要なカーネルコード、またはSSHライブラリの高セキュリティ部分があるとします。これらは、絶対に、いかなる状況下でも、その動作を変更するべきではありません。取るに足らない無限値の小さなサブセットであっても、すべて変更できます。決してテストしないでください。
また、Dev部門が提供するコードに対する単体テストを記述し、ビジネス要件を確実に満たすQA部門が存在するように会社を設立したとします。
この状況では、「重要なコードパスはDevによってのみ変更する必要がありますQAに上層部からのサインオフが通知されている場合」。サインオフと通知のない変更は意図的なものではないため、悪意がある可能性があります。
その場合、イントロスペクションを使用して各メソッドのコンテンツのハッシュを取得し、それを格納されているハッシュと比較するテストは正当なものになる可能性があります。 Method()をシリアライズすることはできませんが、Methodをサブクラス化してシリアライズ可能にすることができます。おそらく、より良いアプローチは、ファイル自体のハッシュを取得することです。または、ファイルをファイルの安全なバックアップと比較します。
ただし、変更が失敗した場合のバージョン管理システムのログを確認して、関連ファイルの変更がダウンロードされたかどうかを確認するのが、おそらく最善の方法です。はいの場合、失敗します。