web-dev-qa-db-ja.com

ユニットテストの失敗が悪いと見なされるのはなぜですか?

一部の組織では、ソフトウェアリリースプロセスの一部はユニットテストを使用することですが、どの時点でもすべてのユニットテストに合格する必要があります。たとえば、すべてのユニットテストが緑色で合格していることを示す画面が表示される場合があります。

個人的には、これは次の理由からそうあるべきではないと思います:

  1. これは、コードは完璧でなければならず、バグが存在してはならないという考えを促進します-現実の世界では、どんなサイズのプログラムでも確かに不可能です。

  2. 失敗する単体テストを考えるのは意欲をそそります。あるいは、修正するのが難しいユニットテストを思いつくでしょう。

  3. いずれかの時点ですべての単体テストに合格した場合、どの時点でもソフトウェアの状態の全体像はわかりません。ロードマップ/目標はありません。

  4. これは、実装前のユニットテストの書き込みを事前に阻止します。

単体テストに失敗したソフトウェアをリリースすることは、必ずしも悪いことではないことを提案します。少なくとも、あなたはソフトウェアのいくつかの側面に制限があることを知っています。

ここで何か不足していますか?なぜ組織はすべての単体テストの合格を期待するのですか?これは夢の世界に住んでいるのではないですか?そして、それは実際にコードの本当の理解を妨げませんか?

94
user619818

この質問にはいくつかの誤解が含まれていますが、私が焦点を当てたいのは、ローカルの開発ブランチ、トランク、ステージング、リリースブランチを区別しないことです。

ローカルのdevブランチでは、ほとんどの場合、ユニットテストに失敗する可能性があります。トランクでは、ある程度許容できるだけですが、すでにできるだけ早く修正するための強力な指標です。トランクでのユニットテストの失敗は、チームの残りのメンバーを混乱させる可能性があることに注意してください。彼らの最新の変更が失敗の原因となっていないかどうかを全員が確認する必要があるためです。

ステージングブランチまたはリリースブランチでは、失敗したテストは「レッドアラート」であり、トランクからリリースブランチにマージされたときに、いくつかのチェンジセットでまったく問題が発生したことを示しています。

単体テストに失敗したソフトウェアをリリースすることは、必ずしも悪いことではないことを提案します。

既知のバグが特定の重大度を下回るソフトウェアのリリースは必ずしも悪いことではありません。ただし、これらの既知のグリッチが原因でユニットテストが失敗することはありません。それ以外の場合は、ユニットテストを実行するたびに、失敗した20個のユニットテストを調べて、失敗が許容できるものかどうかを1つずつ確認する必要があります。これは面倒でエラーが発生しやすくなり、単体テストの自動化の側面の大部分を破棄します。

許容できる既知のバグのテストが本当にある場合は、単体テストツールの無効化/無視機能を使用してください(デフォルトでは実行されず、オンデマンドでのみ実行されます)。さらに、優先度の低いチケットを課題追跡に追加して、問題が忘れられないようにします。

275
Doc Brown

...すべてのユニットテストが緑色で合格-これは良いはずです。

それは良い良いです。それについて「あると思われる」ことはありません。

これは、コードは完璧でなければならず、バグが存在してはならないという考えを促進します-現実の世界では、どんなサイズのプログラムでも確かに不可能です。

いいえ。コードをテストしたことと、この時点までにテストできたことを証明しています。テストがすべてのケースをカバーしているわけではありません。その場合、最終的にはバグレポートでエラーが発生します。[失敗]テストを記述して問題を再現し、テストに合格するようにアプリケーションを修正します。

失敗する単体テストを考えるのは意欲をそそります。

不合格または不合格のテストは、アプリケーションが受け入れるものと受け入れないものに厳しい制限を課します。私が知っているほとんどのプログラムは、2月30日の「日付」に反対します。また、私たちのクリエイティブタイプである開発者は、「彼らの赤ん坊」を壊したくありません。結果として「ハッピーパス」のケースに焦点が当てられると、壊れやすいアプリケーションが頻繁に壊れます。

開発者とテスターの考え方を比較するには:

  • 開発者は、コードがやりたいことを実行するとすぐに停止します。
  • テスターは、コードが壊れなくなると停止します。

これらは劇的に異なるパースペクティブであり、多くの開発者が調整するのが難しいパースペクティブです。

あるいは、修正するのが難しいユニットテストを思いつくでしょう。

あなた自身のために動作するようにテストを書くことはありません。テストを作成して、コードが想定どおりの動作をしていることを確認し、さらに重要なことに、継続する想定どおりの動作を実行する内部実装を変更しました。

  • デバッグは、コードが望んでいることを「証明」しますtoday
  • コードstillが意図したとおりに実行することを「証明」するテスト

いずれかの時点ですべての単体テストに合格した場合、どの時点でもソフトウェアの状態の全体像はわかりません。ロードマップ/目標はありません。

「画像」テストで得られるのは、コードがテストされた時点でコードが「機能する」スナップショットだけです。それがその後どのように進化するかは別の話です。

これは、実装前のユニットテストの書き込みを事前に阻止します。

それがまさにあなたがすべきことです。失敗するテストを記述し(テストするメソッドがまだ実装されていないため)、メソッドコードを記述してメソッドを機能させ、テストに合格します。これが、テスト駆動開発の要点です。

単体テストに失敗したソフトウェアをリリースすることは、必ずしも悪いことではないことを提案します。少なくとも、あなたはソフトウェアのいくつかの側面に制限があることを知っています。

壊れたテストでコードをリリースすると、その機能の一部が以前のように機能しなくなります。バグを修正したり機能を拡張したりしたため、意図的な行為である可能性があります(ただし、最初にテストを変更して失敗したはずですが、その後、修正/拡張機能をコーディングし、テストをプロセスで機能させます)。さらに重要なことは、私たちはすべて人間であり、間違いを犯すことです。コードを壊した場合は、テストを中断する必要があり、それらの壊れたテストでは警報ベルが鳴るように設定する必要があります。

これは夢の世界に住んでいるのではないですか?

どちらかと言えば、それは現実の世界に住んでいて、開発者が全知的でも間違いでもないことを認めて、私たちがdo間違いを犯し、セーフティネットが必要かどうかを確認しますdo失敗しました!
テストを入力してください。

そして、それは実際にコードの本当の理解を妨げませんか?

たぶん。そのためのテストを書くために何かの実装を理解する必要は必ずしもありません(それはそれらのポイントの一部です)。テストは、アプリケーションの動作と制限を定義し、意図的に変更しない限り、それらが同じままであることを確認します。

231
Phill W.

ユニットテストの失敗が悪いと見なされるのはなぜですか?

そうではありません-テスト駆動開発は、失敗したテストの概念に基づいて構築されています。ユニットテストが失敗して開発を推進し、受け入れテストが失敗してストーリーを推進する...

不足しているのはcontext;です。単体テストはどこで失敗することが許可されていますか?

通常の答えは、ユニットテストはプライベートサンドボックスでのみ失敗することが許可されているということです。

基本的な考え方は次のとおりです。失敗したテストが共有される環境では、本番コードへの変更によって新しいエラーが発生したかどうかを理解するために余分な労力が必要です。ゼロと非ゼロの違いは、Nと非Nの違いよりも検出と管理がはるかに簡単です。

さらに、共有コードをクリーンに保つことは、開発者が作業を続けることができることを意味します。コードをマージするときに、支払われている問題からコンテキストをシフトして、テスト数の理解を調整するためにすべき失敗する必要はありません。共有コードがすべてのテストに合格している場合、変更をマージしたときに表示されるエラーmustは、コードと既存のクリーンベースラインとの間の相互作用の一部です。

同様に、オンボーディング中、新しい開発者は、どのテストが「許容可能」であるかを見つけるのに時間を費やす必要がないため、より迅速に生産性を上げることができます。

より正確には、ビルド中に実行されるテストに合格する必要があるという規律があります。

nothingdisabledであるテストが失敗するのは間違いです。

たとえば、「継続的インテグレーション」環境では、高いケイデンスでコードを共有します。 多くの場合を統合しても、変更をリリース対応にする必要があるとは限りません。準備が整うまでトラフィックがコードのセクションにリリースされないようにするさまざまなダークデプロイテクニックがあります。

これらの同じ手法を使用して、失敗したテストを無効にすることもできます。

ポイントリリースで私が経験した演習の1つは、多くの失敗したテストを備えた製品の開発を扱うことでした。私たちが思いついた答えは、スイートを通過して、失敗したテストを無効にし、それぞれdocumentingにすることでした。これにより、すべての有効なテストに合格するポイントにすばやく到達でき、管理/目標提供者/ゴールドオーナーは、そのポイントに到達するために行った取引をすべて確認でき、クリーンアップと新しい作業について情報に基づいた決定を下すことができました。

要約すると、実行中のスイートに一連の失敗したテストを残す以外に、追跡するための他の手法作業は行われませんがあります。

32
VoiceOfUnreason

すばらしい答えはたくさんありますが、まだ十分にカバーされていないと私が信じる別の角度を追加したいと思います。テストを行うことの正確なポイントは何ですか。

ユニットテストは、コードにバグがないことを確認するためのものではありません。

これが主な誤解だと思います。これが彼らの役割だった場合、あなたは実際にいたるところに失敗したテストがあると期待するでしょう。代わりに、

単体テストでは、コードが意図したとおりに機能することを確認します。

極端な場合には、既知のバグがnot修正されていることの確認が含まれる場合があります。ポイントは、コードベースを制御し、偶発的な変更を回避することです。変更を加える場合、問題はなく、実際にはいくつかのテストを中断することが予想されます。コードの動作を変更していることになります。 新しく壊れたテストは、今、変更したものの細かい証跡です。すべての破損が、変更したいものに適合していることを確認してください。その場合は、テストを更新して続行してください。そうでない場合-まあ、あなたの新しいコードは間違いなくバグがあります。提出する前に戻って修正してください!

さて、上記のすべてが機能するのは、すべてのテストが緑で、強力な肯定的な結果が得られる場合のみです。これがまさにコードの動作方法です。赤のテストにはその特性はありません。 「これは、このコードが行わないことです」という情報が役立つことはほとんどありません。

受け入れテストはあなたが探しているものかもしれません。

受け入れテストのようなものがあります。次のマイルストーンを呼び出すために実行する必要がある一連のテストを記述できます。これらは赤のために設計されたものであるため、赤でもかまいません。しかし、それらは単体テストとは非常に異なり、それらを置き換えることはできません。

26
Frax

私はそれを 壊れたウィンドウシンドローム に相当するソフトウェアと見なします。

動作テストは、コードが特定の品質であり、コードの所有者がそれを気にかけていることを教えてくれます。

いつ品質を気にする必要があるかについては、作業しているソースコードのブランチ/リポジトリによって異なります。開発コードには、進行中の作業を示すテストが壊れている可能性があります(うまくいけば!)。

稼働中のシステムのブランチ/リポジトリでテストが壊れると、すぐに警報ベルが鳴ります。壊れたテストが失敗を続けることが許可されている場合、またはそれらが永続的に「無視」としてマークされている場合-時間の経過とともにその数が増加すると予想されます。これらが定期的にレビューされない場合、前例は、壊れたテストが残っていても問題がないと設定されています。

壊れたテストは、多くの店で 壊れたコードをコミットすることさえできるかどうかの制限 を持っているほどに激しく見られています。

23
Robbie Dee

ここに根本的な論理的誤りがあります:

すべてのテストに合格したときに問題がなければ、いずれかのテストが失敗した場合は問題があるはずです。

単体テストでは、すべてのテストに合格すると[〜#〜] is [〜#〜]良好です。テストが失敗した場合、それはALSO GOODです。2つが反対である必要はありません。

失敗したテストは、ユーザーに到達する前にツールによって検出された問題です。公開前に間違いを修正する機会です。そしてそれは良いことです。

良くないとは、失敗したユニットテストが長期にわたって持続することを可能にします。これにより、ツールやレポートを無視するように訓練されます。テストが失敗した場合は、その理由を調査します。時々それはコードのバグです。時々それはテストのバグです。時々それは環境問題であるか、または仮定が変更されました。これらのケースでは、問題は一時的なものである場合もありますが、混乱するほど長く滞ります。このような場合は、問題が解決するまでテストをdisableして(後でどこかに状況を再確認するように注意して)ください。

12
Joel Coehoorn

Phill Wの答えは素晴らしいです。交換できません。

しかし、私は混乱の一部であったかもしれない別の部分に焦点を当てたいと思います。

一部の組織では、ソフトウェアリリースプロセスの一部がユニットテストの使用ですが、どの時点でもすべてのユニットテストに合格する必要があります。

「いつでも」というのはあなたのケースを過大評価しています。重要なのは、単体テストに合格することです変更後特定の変更が実装されました変更前別の変更の実装を開始します。
これは、バグの発生原因となった変更を追跡する方法です。単体テストが失敗し始めたafter変更25を実装しているがbefore変更26を実装している場合、変更25がバグの原因であることがわかります。

During変更の実装。もちろん、単体テストは失敗する可能性があります。 tatは、変更の大きさに大きく依存します。コア機能を再開発しているだけで、マイナーなTweakだけではない場合、新しいバージョンのロジックの実装が完了するまで、しばらくテストを中断する可能性があります。


これにより、チームルールに関して競合が発生する可能性があります。私は実際に数週間前にこれに遭遇しました:

  • すべてのコミット/プッシュはビルドを引き起こします。ビルドは決して失敗してはなりません(失敗したりテストが失敗した場合は、コミットした開発者が非難されます)。
  • すべての開発者は1日の終わりに(たとえ不完全であっても)変更をプッシュする必要があるため、チームリーダーは午前中にコードレビューを行うことができます。

どちらかの規則で結構です。ただし、両方ルールは一緒に機能できません。完了するまでに数日かかる大きな変更が割り当てられている場合、両方のルールを同時に遵守することはできません。私が毎日自分の変更をコメントし、すべてが完了した後でコメントを外してコミットする場合を除いてこれは無意味な作業です。

このシナリオでの問題は、単体テストに目的がないということではありません。 会社は非現実的な期待を持っているです。それらの任意のルールセットはすべてのケースをカバーするわけではなく、ルールを順守できない場合は、盲目的にルールの失敗(私の場合はそうです)ではなく開発者の失敗と見なされます。

9
Flater

すべての単体テストを修正しないと、壊れたテストを誰も修正しない状態にすぐに入る可能性があります。

  1. ユニットテストに合格するとコードが完璧であると表示されないため、不正解です

  2. テストするのも難しいコードを思い付くのは意欲がなく、デザインの観点からは良いことです

  3. コードカバレッジが役立ちます(万能薬ではありません)。また、単体テストはテストの1つの側面にすぎません。統合/受け入れテストも必要です。

6
jk.

これは、コードは完璧でなければならず、バグが存在してはならないという考えを促進します-現実の世界では、どんなサイズのプログラムでも確かに不可能です。

違います。なぜそれは不可能だと思いますか?動作するプログラムの例:

public class MyProgram {
  public boolean alwaysTrue() {
    return true;
  }

  @Test
  public void testAlwaysTrue() {
    assert(alwaysTrue() == true);
  }
}

失敗する単体テストを考えるのは意欲をそそります。あるいは、修正するのが難しいユニットテストを思いつくでしょう。

その場合は単体テストではないかもしれませんが、複雑な場合は統合テストです

いずれかの時点ですべての単体テストに合格した場合、どの時点でもソフトウェアの状態の全体像はわかりません。ロードマップ/目標はありません。

確かに、それはnitと呼ばれ、理由によりテストします。コードの小さな単位をチェックします。

これは、実装前のユニットテストの書き込みを事前に阻止します。

開発者 意志 書くことをやめるany彼らがその利点を理解していないかどうかテストする その性質上(QAからのものを除く)

6
user7294900

すでに良い答えにいくつかのポイントを追加するには...

しかし、いつでもすべての単体テストに合格する必要があります

これは、リリースプロセスを理解していないことを示しています。テストの失敗は、TDDで計画されている機能がまだ実装されていないことを示している場合があります。または、将来のリリースで修正が計画されている既知の問題を示している可能性があります。または、顧客が気づく可能性が低いため、これが修正するのに十分重要ではないと判断した場合もあります。これらすべての重要なことは、経営陣が失敗について判決を下したことです。

これは、コードは完璧でなければならず、バグが存在してはならないという考えを促進します-現実の世界では、どんなサイズのプログラムでも確かに不可能です。

他の回答はテストの限界をカバーしています。

バグを取り除くことがマイナス面だと思う理由がわかりません。確認したコードを(できる限り)提供したくない場合は、想定されていることを実行しますが、なぜソフトウェアで作業しているのですか?

いずれかの時点ですべての単体テストに合格した場合、どの時点でもソフトウェアの状態の全体像はわかりません。ロードマップ/目標はありません。

なぜロードマップが必要なのですか?

単体テストでは、最初に機能が動作することを確認しますが、(回帰テストとして)誤って何も壊していないことを確認します。既存の単体テストのすべての機能について、ロードマップはありません。すべての機能が動作することがわかっています(テストの制限内)。そのコードが完成した場合、それ以上の作業は必要ないため、ロードマップはありません。

プロのエンジニアとして、金メッキの罠を回避する必要があります。愛好家は、機能するもので端をいじくり回す時間を無駄にする余裕があります。私たちはプロとして、製品を提供する必要があります。つまり、何かが機能し、機能していることを確認して、次のジョブに進みます。

6
Graham

コードは完璧でなければならず、バグが存在してはならないという考えを促進します

ほとんど間違いなく。それはあなたのテストが失敗するべきではない、それ以上でもそれ以下でもないという考えを促進します。テストを行うこと(それらの多くでも)が「完全」または「バグなし」について何かを言うと仮定すると、誤りです。テストの深さをどの程度浅くするかを決定することは、優れたテストを作成する上で重要な部分であり、テストのカテゴリ(「単体」テスト、統合テスト、キュウリの意味での「シナリオ」など)が明確に分かれている理由です。

失敗する単体テストを考えるのは意欲をそそります。あるいは、修正するのが難しいユニットテストを思いつくでしょう。

テスト駆動開発では、コーディングを開始する前に、最初にevery単体テストが失敗することが必須です。この理由から、「赤緑サイクル」(または「赤緑リファクターサイクル」)と呼ばれています。

  • テストが失敗しないと、コードが実際にテストによってテストされているかどうかはわかりません。 2つはまったく関連していない可能性があります。
  • コードをexactlyに変更することで、テストが赤から緑に変わり、それ以上でもそれ以下でもないので、コードが本来の動作を実行していることを確信できます。あなたは決して必要ないかもしれません)。

いずれかの時点ですべての単体テストに合格した場合、どの時点でもソフトウェアの状態の全体像はわかりません。ロードマップ/目標はありません。

テストは一種のマイクロゴールです。テスト駆動開発では、プログラマーは最初にテスト(単一)を記述し、次にいくつかのコードを実装する明確な目標を設定します。その後、次のテストなど。

テストの機能は、コードが記述される前に完全に存在することではありません。

エラーメッセージ(例外/スタックトレース)が開発者に作業を実行する必要がある場所を直接示すことができるため、言語およびこのアプローチに適したテストライブラリを正しく使用すると、開発が大幅にスピードアップされます。次。

これは、実装前のユニットテストの書き込みを事前に阻止します。

この発言がどのように真実であるかはわかりません。テストの作成は、理想的には実装のpartである必要があります。

ここで何か不足していますか?なぜ組織はすべての単体テストの合格を期待するのですか?

なぜなら、組織はテストがコードに関連していることを期待しているからです。成功するテストを作成するということは、アプリケーションの一部を文書化し、アプリケーションがテスト(テスト)の内容を実行することを証明したことを意味します。それ以上でもそれ以下でもありません。

また、テストを行うことの非常に大きな部分は「回帰」です。新しいコードを自信を持って開発またはリファクタリングできるようにしたい。大量のグリーンテストがあると、それを行うことができます。

これは組織的レベルから心理的レベルへと進みます。エラーがテストで検出される可能性が高いことを知っている開発者は、解決する必要がある問題に対してインテリジェントで大胆な解決策を思いつくことができます。一方、テストを行わない開発者は、変更を行うと残りのアプリケーションが壊れるかどうかわからないため、しばらくすると(恐怖のため)足踏み状態になります。

これは夢の世界に住んでいるのではないですか?

いいえ。テスト駆動型アプリケーションでの作業は純粋な喜びです。別の質問で議論できる何らかの理由(「より多くの努力」など)でコンセプトが気に入らない場合を除きます。

そして、それは実際にコードの本当の理解を妨げませんか?

絶対にそうではありません。なぜでしょうか。

テストであるだけでなく、実際にテストをソフトウェアのメインドキュメントとして使用している多数の大規模なオープンソースプロジェクト(コードの「理解」とコードに関するノウハウの管理が非常に緊急なトピック)を見つけました。また、アプリケーション/ライブラリのユーザーまたは開発者向けに、実際に機能し、構文的に正しい例を提供します。これはしばしば素晴らしい働きをします。

明らかに、悪いテストを書くことは悪いことです。しかし、それ自体はテストの機能とは何の関係もありません。

4
AnoE

(私の元のコメントから)

必要な機能と将来の目標には違いがあります。テストは必要な機能を対象としています。テストは正確で形式的で実行可能であり、失敗するとソフトウェアは動作しません。将来の目標は、実行可能であることは言うまでもなく、正確でも形式的でもない可能性があるため、課題/バグトラッカー、ドキュメント、コメントなどの自然言語のままにしておく方がよいでしょう。

演習として、質問の「単体テスト」という句を「コンパイラエラー」(またはコンパイラがない場合は「構文エラー」)に置き換えてみてください。リリースは使用できないため、リリースにコンパイラエラーがないことは明らかです。しかし、コンパイラエラーと構文エラーは、開発者のマシンがコードを記述しているときの通常の状態です。エラーは、終了したときにのみ消えます。コードをプッシュする必要があるのはまさにそのときです。この段落の「コンパイラエラー」を「単体テスト」に置き換えます。

3
Warbo

既存の答えは確かに良いですが、質問でこの根本的な誤解に対処する人を見たことはありません。

すべてのユニットテストに合格する必要がある任意の時点

いいえ、確かに、これは真実ではありません。私がソフトウェアを開発している間、NCrunchはほとんどの場合、茶色(ビルドの失敗)または赤(テストの失敗)です。

NCrunchをgreen(すべてのテストに合格)にする必要があるのは、ソース管理サーバーにコミットをプッシュする準備ができたときです。その時点で、他の人が私のコードに依存する可能性があるためです。

これは、新しいテストの作成というトピックにも反映されます。テストはコードのロジックと動作をアサートする必要があります。境界条件、障害条件など。新しいテストを作成するとき、これらの「ホットスポット」をコードで識別しようとします。

単体テストは、コードがどのように呼び出されるかを予測します-前提条件、期待される出力など。

変更後にテストが中断した場合、コードまたはテストのどちらにエラーがあるかを判断する必要があります。


補足として、単体テストはテスト駆動開発と密接に関連していることがあります。 TDDの原則の1つは、壊れたテストが指針になるということです。テストが失敗した場合、テストに合格するようにコードを修正する必要があります。今週初めの具体例を次に示します。

背景:Oracleクエリの検証に使用される開発者が使用するライブラリを作成してサポートします。クエリが期待値と一致することをアサートするテストがあり、大文字と小文字が重要になり(Oracleにはありません)、無効なクエリが期待値と完全に一致する限り、そのクエリは承認されました。

代わりに、私のライブラリはAntlrとOracle 12c構文を使用してクエリを解析し、構文ツリー自体にさまざまなアサーションをラップします。そのようなものは有効です(解析エラーは発生しませんでした)、そのすべてのパラメーターはパラメーターコレクションによって満たされ、データリーダーによって読み取られるすべての予想される列はクエリに存在します。これらはすべて、次のように進んでいます。様々な時に生産。

同僚のエンジニアの1人が、月曜日に週末に失敗した(または、失敗したはずのときに成功した)クエリを私に送信しました。私のライブラリは、構文は問題ないと言っていましたが、サーバーがそれを実行しようとしたときに失敗しました。そして彼がクエリを調べたとき、その理由は明らかでした:

UPDATE my_table(
SET column_1 = 'MyValue'
WHERE id_column = 123;

プロジェクトをロードし、このクエリが無効であることを表明する単体テストを追加しました。明らかに、テストは失敗しました。

次に、失敗したテストをデバッグし、例外をスローすると予想されるコードをステップ実行して、Antlr wasが前のコードとは異なり、開いている括弧でエラーを発生させていることを突き止めました期待していた。私はコードを変更し、テストが緑色(合格)であること、およびプロセスで障害が発生し、コミットされ、プッシュされたものがないことを確認しました。

これにはおそらく20分かかりました。その過程で、以前は無視されていたエラーの全範囲をサポートするようになったため、ライブラリを大幅に改善しました。ライブラリの単体テストがない場合、問題の調査と修正には何時間もかかった可能性があります。

2
GalacticCowboy

自動テストの目的は、何かが壊れた場合に通知することですできるだけ早く。ワークフローは次のようになります。

  1. 変える
  2. 変更をビルドしてテストする(理想的には自動的に)
  3. テストが失敗した場合、それは以前に機能していた何かを壊したことを意味します
  4. テストに合格した場合は、変更によって新しいリグレッションが発生しなかったことを確信できるはずです(テストの範囲によって異なります)。

テストがすでに失敗している場合、ステップ#3は効果的に機能しません。テストは失敗しますが、調査せずに何かが壊れたかどうかはわかりません。失敗したテストの数を数えることはできますが、変更によって1つのバグが修正されて別のバグが壊れるか、別の理由でテストが失敗し始める可能性があります。つまり、すべての問題が修正されるか、失敗した各テストが調査されるまで、何かが壊れているかどうかがわかるまで、しばらく待つ必要があります。

ユニットテストが新しく導入されたバグを可能な限り早期に発見できることは、自動テストの最も価値のあることです。欠陥が発見されなくなるまでの期間が長いほど、修正に費用がかかります。

コードは完璧でなければならず、バグが存在してはならないという考えを促進します
失敗するユニットテストを考えるのは意欲をそそります

機能しないもののテストでは何もわかりません-doが機能するもの、または修正しようとしているものの単体テストを作成します。これは、ソフトウェアに欠陥がないことを意味するのではなく、以前に単体テストを記述した欠陥が再び戻っていないことを意味します。

ユニットテストの事前書き込みを阻止する

それが機能する場合は、事前にテストを記述し、合格するまでマスター/トランクにチェックインしないでください。

いずれかの時点ですべての単体テストに合格した場合、どの時点でもソフトウェアの状態の全体像はわかりません。ロードマップ/目標はありません。

単体テストはロードマップ/目標を設定するためのものではなく、代わりにバックログを使用しますか?すべてのテストに合格した場合の「全体像」は、ソフトウェアが破損していないことです(テスト範囲が良好な場合)。よくやった!

2
Justin

「しかし、いつでもすべての単体テストに合格する必要があります」

それがあなたの会社の態度だとしたら、それは問題です。特定の時点、つまり、コードが次の環境に移動する準備ができていることを宣言すると、すべての単体テストに合格するはずです。しかし、開発中、多くの単体テストが失敗することを日常的に予想する必要があります。

プログラマーが最初の試行で自分の作業を完璧にすることを期待する合理的な人はいません。私たちが合理的に期待していることは、既知の問題がなくなるまで彼がそれに取り組み続けることです。

「失敗する単体テストを考えるのはやる気がありません。あるいは、修正するのが難しいであろう単体テストを考え出すことは確かです。」組織内の誰かが、可能性のあるテストは失敗する可能性があるため言及しない方がよいと考え、テストを修正するためにさらに多くの作業が必要になる場合、その人はその仕事に完全に適格ではありません。これは悲惨な態度です。 「私が手術をしているとき、私は意図的にステッチが正しいかどうかをチェックしません。なぜなら、私がそれらを正しくないと思ったら、戻ってそれらをやり直す必要があるからです。操作の終了が遅くなりますか?」

コードが本番環境に移行する前にエラーを特定するプログラマーに対してチームが敵対的である場合、そのチームの態度に本当に問題があります。配信を遅くするエラーを特定したプログラマーを経営陣が罰する場合、会社が破産に向かっている可能性があります。

はい、時々合理的な人々が「締め切りに近づいている、これは些細な問題であり、それを修正するために必要なリソースを今すぐ投入する価値はない」と言うのは確かに本当です。しかし、あなたが知らなければ、その決定を合理的に行うことはできません。エラーのリストをクールに調査し、優先順位とスケジュールを割り当てて修正することは合理的です。故意に問題を知らないようにして、この決定をする必要がないようにするのはばかげています。あなたが知りたくなかったからといって、顧客はそれを見つけられないと思いますか?

1
Jay

以前の回答から出てきたとは思えない点の1つは、内部テストと外部テストに違いがあることです(多くのプロジェクトは、2つを区別するのに十分注意していないと思います)。内部テストは、一部の内部コンポーネントが本来の方法で機能していることをテストします。外部テストは、システム全体が本来の方法で機能していることを示しています。もちろん、システムに障害が発生しないコンポーネントに障害が発生する可能性は十分にあります(おそらく、システムが使用しないコンポーネントの機能があるか、システムが障害から回復します)成分)。システム障害を引き起こさないコンポーネント障害が発生しても、リリースを止めることはできません。

内部コンポーネントのテストが多すぎて麻痺しているプロジェクトを見てきました。システムの外部から見える動作を実際に変更せずにコンポーネントの動作を変更しているため、パフォーマンスを改善しようとするたびに、数十のテストが失敗します。これは、プロジェクト全体の俊敏性の欠如につながります。外部システムテストへの投資は、特に非常に低レベルのコンポーネントについて話している場合は、内部コンポーネントテストへの投資よりもはるかに良い見返りがあると思います。

失敗した単体テストは本当に問題ではないと示唆したとき、これがあなたが考えていることかどうか疑問に思いますか?おそらく、アプリケーションの外部から見える動作を検証するテストに重点を置きながら、単体テストの価値を評価し、問題の原因となるものよりも価値のあるものを破棄する必要があります。

0
Michael Kay