ユニットテストを勉強してコードに適用することを計画していましたが、同僚と話した後、一部の人はそれは必要ではなく、ほとんど利益がないと私に提案しました。また、実稼働ソフトウェアを使用して単体テストを実際に行っている企業はごくわずかであると主張しています。
私は、人々が職場で単体テストをどのように適用し、それらを使用することで得られるメリット、たとえば、コード品質の向上、長期的な開発時間の短縮などに興味があります。
ユニットテストを勉強してコードに適用することを計画していましたが、同僚と話した後、一部の人はそれは必要ではなく、ほとんど利益がないと私に提案しました。また、実稼働ソフトウェアを使用して単体テストを実際に行っている企業はごくわずかであると主張しています。
私は、人々が職場で単体テストをどのように適用し、それらを使用することで得られるメリット、たとえば、コード品質の向上、長期的な開発時間の短縮などに興味があります。
回答:
それらのいくつかは、それが必要ではないことを私に示唆しています
まあ、厳密な意味では正しいです。テスト、コードレビュー、ソース管理なども厳密には必要ありません。非常に少数の賢明な開発者だけが、長期的にこれらなしで作業を行います。私たちのほとんどは、これらがベストプラクティスである理由を(多くの場合、私たち自身の間違いから難しい方法で)学びました。
そして、それはほとんど利点がありません。
ほとんどの場合、これは当てはまりません。つまり、今後数年間、使用中(つまりメンテナンス中)になるはずの製品ソフトウェアについて話している場合です。
また、本番ソフトウェアで単体テストを行う企業はごくわずかであると主張しています。
これは本当かもしれませんが(私の経験ではますます少なくなっていますが)、単体テストの価値については何も言えません。これとは対照的に、古い冗談「たわごとは良いです-500億個のハエは間違ってはいけません!」;-)
仕事で単体テストを適用しましたか。それから何を得ますか?(たとえば、コード品質の向上、長期的な時間の短縮など)
私は、可能であればいつでも、10年以上にわたってユニットテストを仕事に適用しています。それが機能することを知っている私のコードに対するその自信感-そして、それを信じるだけでなく、いつでも、どこでも、数秒で、何度も何度もそれを証明することができます-貴重です。既存の機能を壊す心配をせずに、コードをリファクタリングしたり、デザインを改善したり、バグを修正したりする勇気を与えてくれます。昔の「コードと祈り」には決して戻らないでしょう。
私は単体テストを行いますが、仕事ではありません(またはほとんどありません)
私が得たテストの主な利点は、リファクタリングが非常に簡単になり、リグレッション(つまり、すでに修正されたエラーの再導入)に気付くことです。
「ビルド」を使用してテストを実行します。実行中のテストでソフトウェアをチェックアウトし、変更を加えてすべてのテストが実行されるまでチェックインしません。
そのため、私の経験では、テストを書くことは、孤独な方法で行われた場合、ほとんど役に立ちません。他の人が行った変更に対応するために常にテストを修正する必要がある場合、テストが同僚によって削除される可能性がある場合(以前のジョブで発生します)チームの残りのメンバーによって即座に燃え上がる利点。
チーム全体が同意する場合(そして、簡単な1人のチームの場合)、私の経験では、テストはプロジェクトの品質、スタイル、堅牢性にとって大きな利点です。
しかし、「少数の企業だけがコードを自動的にテストする」と正直に信じており、とにかく時間の無駄だと確信しているチームでは、利益を得る希望はほとんどないように見えますが、エラーを指摘する際の「時間のロス」の原因となります。
テストを導入する最良のチャンスは、あなた自身の責任の範囲内の小さなプロジェクトです。そこで、あなたは輝いて、テストの価値を示す機会を得るでしょう。
私はあなたの同僚に味方する傾向がありますが、それはある程度までです。
単体テストの問題は、コードの大まかな調査によって、それが何があっても機能することが明らかになっている些細なケースに、頻繁にかつ無意識に書かれていることです。例えば:
def add(x, y)
x + y
end
追加が実際に任意に選択されたユースケースで機能することを確認するための12個のテストとともに。ああ...
単体テストの背後にある一般的な前提は次のとおりです。コードにバグが含まれていない場合、それは十分にテストしていないためです。さて、いつ適切なユニットテストを書くか。回答:
あなたが何らかの種類のWebアプリを開発していると仮定して、それぞれを見ていきましょう。
新しい機能にいくつかのコードを書くと、それは今のところ合理的に機能するはずです。次に、ブラウザに手を伸ばして、より集中的にテストすることで動作することを確認しますか?Bzzzt!...間違った答え。単体テストを作成します。あなたが今そうしないならば、あなたはおそらく決してそうしないでしょう。そして、これは単体テストが非常にうまく機能する場所の1つです。つまり、高レベルの機能をテストすることです。
次に、バグを見つけます(誰も見逃しませんか?)。これにより、ポイント2が得られます。コードに戻り、手順を開始します。一貫性のある正しいデータを保持することが重要な主要なブレークポイントでユニットテストを作成します。
最後のポイントは、その逆です。あなたは、メタプログラミングの負荷を伴ういくつかの毛深い機能を設計しています。数千の潜在的なシナリオを含む意思決定ツリーがすぐに生成されるため、最後のシナリオがすべて機能することを確認する必要があります。そのようなことを書くとき、ここまたはそこにある単純な見た目の変化は、食物連鎖のさらに下に想像を絶する結果をもたらす可能性があります。SQLトリガーを使用してMPTT実装を設計しているとしましょう。これにより、複数行のステートメントで動作できるようになります。
この種の厄介な環境では、通常、テストを高度に自動化する必要があります。したがって、テストデータの生成を自動化するスクリプトを作成し、このテストデータに対して単体テストのボートロードを実行します。これを行う際に見失うことのない重要なことの1つは、ユニットテストジェネレーターのユニットテストも記述する必要があることです。
ボトムライン:ユニットテスト、間違いなくはい。ただし、基本的な機能については、デバッグのために実際に必要になるまで、または毛深い機能が適切に動作することを確認するまで(後者の場合、テスト自体を含めて)ください。
すべてのコードをテストする必要があります。それについての選択はありません。
テストされていないコードは役に立たない:何もすることが信頼できない。
単体テストを作成することも、高レベルの統合テストや受け入れテストを作成することもできます。
単体テストは、記述しやすく、デバッグしやすく、管理しやすいです。
統合テストは、ユニットが実際に機能するという前提に基づいています。ユニットテストなしで、ユニットがどのように機能するかをどのように知っていますか?統合される個々のユニットが実際に機能することがわからない場合、統合テストをどのようにデバッグできますか?
同様に、受け入れテストは、動作するすべての部品に依存します。一連の単体テストがなくても、どのように部品や部品が機能するかを知ることができますか?
テストは必須です。上位レベルのテストはすべて、実際に動作しているユニットに依存しています。
そのため、ユニットテストは論理的に必要です。他に選択肢はありません。
私は書くすべてに単体テストを使用しますが、テストケースなしでは、テストされていないコードをレビューに合格させません。(しかし、カバレッジツールがないため、テストカバレッジについて推論する必要があります。
それは非常に簡単です:コードが機能することを実証できない場合(およびテスト形式の実行可能仕様よりも良い方法はありますか?)、それは機能しません。
これは私に与えます:
単体テストは規律です。コードが機能する必要はないため、多くの場合破棄されます。
ただし、堅牢でバグの少ないコードにつながる実証済みの方法です。あなたが既にいくつか言及したように、私はあなたに利益を説明する必要はないと思います。Javascriptライブラリ、フルスタックフレームワーク、または単一目的のアプリケーションなど、主要なオープンソースプロジェクトを見ると、すべてユニットテストを使用しています。
使用を推奨しない同僚はプログラマーではないと思います。もしそうなら、マーティン・ファウラーやケント・ベックのような人よりも私が高く評価している人はあまりいないとだけ言っておきましょう;)。
ほとんどのベストプラクティスと同様に、利点は長期的であり、それに時間をかける必要があります。手続き型コードの長いスクリプトを書くこともできますが、2年後にリファクタリングする必要がある場合は、オブジェクト指向スタイルで記述したいと思っています。
同じことがユニットテストにも当てはまります。アプリケーションの重要な部分の単体テストを作成すると、コードをリファクタリングした後でも、常に意図したとおりに機能することを確認できます。たぶん、あなたはリグレッションのバグがないようにあなたがとても上手にコーディングします。しかし、そうでない場合、または新しいプログラマーがチームに加わった場合、過去のバグが二度と起こらないようにする必要があります。半年前に解決されたと思われるバグレポートを提出するのではなく、あなたの上司もそれに満足していると思います。
単体テストには、単体テストに優しい言語、単体テストに優しいデザイン、単体テストに優しい問題が必要です。
C ++、マルチスレッド設計、GUIは悪夢であり、問題の範囲は恐ろしいものになります。
.NET、再利用可能なシングルスレッドdllアセンブリ、純粋な計算ロジックが簡単になります。
それは価値があるか、私は本当に言うことはできません。
リファクタリングしますか?コードに「off by one」のような「愚かなバグ」がたくさんありますか?
あなたが何をするにしても、「あなたはユニットテストを持っていないので、あなたは吸う」と他人を批判するその男にならないでください。テストがあなたを助けるなら、それのために行きなさい、そうでなければ、それは銀の弾丸のようではない。
したいのですが、私は品質を気にしない企業でほぼ完全に仕事をするという不幸を経験しました。ユニットテストについて言及しましたが、「ハァッ?」ある種の外観(SOLID原則、ORM、または「すべての静的メソッドを備えたクラス」を超えたデザインパターン、または.NET命名規則に言及したときと同じ外観)。私はそのようなことを理解している会社にだけ行ったことがありますが、残念なことにそれは短期契約であり、部門はコストを削減するためにトリミングされたので、実際に学ぶ時間はありませんでした。
私は使い捨てのダミープロジェクトの単体テストに手を出しましたが、本格的なTDD / BDDについて頭を悩ませたことはありません。
それらを使用します。私たちが得る大きな利点の1つは、ユニットテストフレームワークがメモリリークと割り当てエラーをチェックすることです。問題は単体テストコード自体にある場合もありますが、多くの場合、プロダクションコードにあります。
コードレビューで見逃しているものを見つけるのに最適な方法です。
単体テスト(非常に高速)も実行する必要があり、コミットのたびに、また開発者がコミットする前に、継続的な統合の一部として実行できます。実行するのに20秒もかからない1,000を超えています。
システムレベルの自動化テストでは40分以上、手動テストでは数時間/日と比較してください。もちろん、単体テストは、実行する必要がある唯一のテストではありませんが、きめ細かいコードレベルでは、バグを見つけたり、システム/統合テストでは処理できないエッジケースをテストしたりできます。私たちのコードは、75%以上の意思決定カバレッジと100%の関数カバレッジでテストする必要があります。これは、単体テストなしでは達成するのが非常に困難です。
ユニットテストは価値を高めると思いますが、私はTDDの大弟子ではありません。計算エンジン、または実際にあらゆる種類のエンジンを実行するときにユニットテストを使用すると最も効果的で、ユーティリティクラスを使用すると、ユニットテストが非常に役立ちます。
より多くのデータ依存ブロックの自動統合テストを好むが、それはすべてデータビジネスに依存しているため、多くのエラーは私たちの環境で他の何よりもデータに関連しているため、自動統合テストはうまく機能している。これらのテストの前後にデータをチェックし、例外レポートを生成します。
したがって、特にテスト対象のユニットに必要なすべての入力を提供し、指定された入力で単独で動作できる場合、ユニットテストは本当に価値を高めます。繰り返しますが、私の場合、計算エンジンとユーティリティクラスはこれらの完璧な例です。
ユニットテストをコーディングし、毎日のビルドプロセスの一部としてユニットテストの実行を行うことの本当の利点を見たのは、 3つの異なる大陸で働く30人以上の開発者のプロジェクトでした。単体テストが本当に輝いたのは、誰かがそのクラスをどのように使用しているかを理解せずに、彼らが維持しているクラスを微妙に変更するときでした。コードがテストグループにヒットするのを待つ代わりに、変更の結果として他の人のユニットテストが失敗し始めたときに即座にフィードバックがありました。[だから、コード用に書いたものだけでなく、すべての単体テストを定期的に実行する必要があります。]
単体テストのガイドラインは次のとおりです。