web-dev-qa-db-ja.com

単体テストは本当に便利ですか?

私はCSの学位を取得して卒業しました。現在、Junior .NET Developer(C#、ASP.NET、およびWebフォーム)として仕事をしています。私がまだ大学にいた頃、単体テストの主題はカバーされていましたが、その利点を実際に見たことがありませんでした。私はそれが何をすることになっているのか、つまり、コードのブロックが使用に適しているかどうかを判断することを理解しています。ただし、ユニットテストを実際に作成する必要はありませんでした。また、その必要性を感じたこともありません。

既に述べたように、私は通常ASP.NET Webフォームで開発しており、最近、いくつかの単体テストを書くことを考えています。しかし、これについていくつか質問があります。

ユニットテストは「モック」を書くことで頻繁に行われることを読みました。私はこの概念を理解していますが、完全に動的で、ほとんどすべてがデータベースからのデータに依存しているWebサイトのモックをどのように記述すればよいのか理解できません。例:私はItemDataBoundイベントなどを持っている多くのリピーターを使用しています(これも「不明」なデータに依存します)。

したがって、質問1:ASP.NET Webフォームの単体テストを作成することは頻繁に行われることであり、その場合、「動的環境」の問題を解決するにはどうすればよいですか。

私が開発しているとき、私は多くの試行錯誤を経験します。それは私が何をしているのかわからないわけではありませんが、私は通常、いくつかのコードを書いて、ヒットします Ctrl F5 何が起こるか見てください。ほとんどの場合、このアプローチでうまくいきますが、(私の経験が少ないため)自分が少し無知であると感じることがあります。私も時々このように多くの時間を浪費します。

それでは、質問番号2:ユニットテストの作成を開始することをお勧めしますか?実際の実装ではそれが役立つかもしれないと思いますが、それでもまた遅くなるかもしれません。

98
Jane Doe

私の意見では、そうです、そうです、そうです。

  1. 彼らはあなたがあなたに加える変更にあなたに自信を与えます(他のすべてはまだ働いています)。この自信は、コードを成形するために必要なものです。それ以外の場合は、物事を変更することを恐れるかもしれません。

  2. それらはあなたのコードをより良くします。ほとんどの単純な間違いは、単体テストで早期に発見されます。バグを早期にキャッチして修正することは、たとえばアプリケーションが本番環境にあるときなど、後で修正するよりも常に安価です。

  3. これらは、コードがどのように機能し、どのように使用されるかに関する他の開発者向けのドキュメントとして機能します。

最初に直面する問題は、ASP.NET自体は単体テストを作成するのに役立つわけではなく、実際にはそれに対して動作することです。選択肢がある場合は、ユニットテストを念頭に置いて作成された ASP.NET MVC の使用を開始します。 ASP.NET MVCを使用できない場合は、少なくともロジックを簡単に単体テストできるように、ASP.NETで [〜#〜] mvp [〜#〜] パターンを使用する必要があります。

それに加えて、単体テストの作成に習熟する必要があります。 TDDを実践する場合、コードはテスト可能な状態、つまりすてきでクリーンな状態で作成されます。

練習してペアプログラムすることをお勧めします。読んでいる間:

または、最初の概要:

124
KeesDijk

番号。

ユニットテストの背後にある概念は、ユニットテストが発明される前から偽であることがわかっていた前提に基づいています。テストは、コードが正しいことを証明できるという考えです。

すべてが合格するテストがたくさんあると、1つだけ証明されます。すべてが合格するテストがたくさんあるということです。テストのテスト内容が仕様に一致していることを証明するものではありません。これは、テストを作成したときに考慮しなかったエラーがコードにないことを証明するものではありません。 (そして、あなたがテストしようと思ったのは、あなたが焦点を合わせていた可能性のある問題だったので、とにかくそれらを正しく理解している可能性が高いです!)そして最後にバグはありません。 (最後の1つを論理的な結論までたどると、最終的に カメがずっと下に になります。)

Djikstra 概念を破棄した 1988年の正しさを証明するテストの方法==、そして彼が書いたものは今日も同じように有効です:

プログラムのテストでバグの存在を説得力をもって実証できるかもしれないが、バグがないことを実証することはできないと指摘されてから、現在は20年です。このよく知られている発言を熱心に引用した後、ソフトウェアエンジニアはその日の順序に戻り、クリソコスミック浄化を洗練し続けた昔の錬金術師のように、彼のテスト戦略を洗練し続けます。

単体テストのもう1つの問題は、コードとテストスイートの間に密結合が生じることです。コードを変更すると、いくつかのバグが発生し、いくつかのテストが失敗することが予想されます。しかし、要件自体が変更されたためにコードを変更している場合、多くの失敗したテストが発生し、それぞれを手動で調べて、テストがまだ有効かどうかを判断する必要があります。 (あまり一般的ではありませんが、shouldであるはずの既存のテストが無効である可能性もあります。これは、変更が必要な変更を忘れたためです。 。)

単体テストは、実際に優れたプログラマーでなくても、作業コードを簡単に作成できることを約束する、開発の流行の最新のものに過ぎません。それらのどれも彼らの約束を成し遂げることができませんでした、そしてこれもどちらもしません。実際に実際に動作するコードを記述する方法を知るためのショートカットはありません。

安定性と信頼性が最も重要である場合に、自動テストが本当に有用であるといういくつかの報告があります。たとえば、SQLiteデータベースプロジェクトです。しかし 信頼性のレベルを達成するために必要なもの はほとんどのプロジェクトにとって非常に不経済です:テストと実際のSQLiteコードの比率はほぼ1200:1です。ほとんどのプロジェクトはそれを買う余裕がなく、とにかくそれを必要としません。

95
Mason Wheeler

学校用にいくつかの小さなコードをテストするメインメソッドを書くことの利点を見たことがあるなら、ユニットテストは同じプラクティスのプロフェッショナル版/エンタープライズ版です。

また、コードの作成、ローカルWebサーバーの起動、問題のページの閲覧、データの入力または適切なテストシードへの入力の設定、フォームの送信、結果の分析などのオーバーヘッドを想像してみてください。 nUnit実行ボタン。

こちらも楽しい画像です... enter image description here

私はこの画像をここで見つけました:
http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/

60
Heath Lilley

ユニットテストは、最近それについて神秘的なものを持っています。 100%テストカバレッジは聖杯のようであり、ユニットテストがソフトウェア開発の真の方法であるかのように人々はそれを扱います。

彼らは要点を逃している。

単体テストは答えではありません。 テストです。

さて、この議論が出てくるときはいつでも、誰か(たいていは私でも)がダイクストラの言葉を引用します:「プログラムのテストはバグの存在を示すことができますが、バグがないことを決して示すことはできません。」ダイクストラは正しい:テストはソフトウェアが意図したとおりに機能することを証明するのに十分ではない。しかし、それは必要です:あるレベルでは、を示すことが可能でなければなりませんそのソフトウェアはあなたがやりたいことをやっています。

多くの人が手でテストします。堅実なTDD愛好家でも手動テストを行いますが、認めない場合もあります。仕方がない:会議室に行ってソフトウェアをクライアント/ボス/投資家などにデモする直前に、手動で実行して、機能することを確認します。これには何の問題もありません。実際、すべてを手動で実行せずにすべてがスムーズに進むことを期待するのはおかしいでしょう-つまり、テストする -100%の単体テストカバレッジとテストに対する最大限の信頼性がある場合でも。

しかし、ソフトウェアの構築に必要であっても、手動テストが十分であることはまれです。どうして?手動テストは面倒で時間がかかり、人間が実行するためです。そして、人間は退屈で時間のかかるタスクを実行することで悪名高いことで知られています。彼らは可能な限りそれらを実行することを避け、強制されたときにうまく実行しないことがよくあります。

一方、マシンは、面倒で時間のかかる卓越 -消費タスク。結局のところ、それがコンピュータの発明でした。

したがって、testingが重要であり、自動テストが唯一の賢明な方法ですテストが一貫して採用されていることを確認してください。そして、ソフトウェアが開発されたら、テストして再テストすることが重要です。ここでの別の回答は、回帰テストの重要性を示しています。ソフトウェアシステムは複雑であるため、システムの一部に一見無害に見える変更が頻繁に発生すると、システムの他の部分に意図しない変更(バグなど)が発生します。何らかのテストを行わないと、これらの意図しない変更を発見できません。また、テストに関する信頼できるデータが必要な場合は、体系的な方法でテストを実行する必要があります。つまり、ある種の自動テストシステムが必要です。

これはすべてユニットテストと何をしているのですか?まあ、その性質上、単体テストは人間ではなくマシンによって実行されます。したがって、多くの人々は、自動テストが等しい単体テストであるという誤った印象を受けています。しかし、それは真実ではありません。単体テストは、非常に小さい自動テストです。

extra small自動テストの値は何ですか?利点は、isolationでソフトウェアシステムのコンポーネントをテストすることです。これにより、より正確なテストのターゲット設定、およびデバッグの支援。ただし、単体テストは、本質的に高品質のテストを意味しません。より詳細なレベルでソフトウェアをカバーするため、多くの場合、より高品質のテストにつながります。しかし、複合部品ではなく、完全なシステムのみの動作を完全にテストし、それを徹底的にテストすることは可能です。

ただし、単体テストのカバレッジが100%であっても、システムは完全にテストされない場合があります。個々のコンポーネントは分離して完全に動作する可能性がありますが、一緒に使用すると失敗します。したがって、単体テストは非常に有用ですが、ソフトウェアが期待どおりに動作することを確認するには十分ではありません。実際、多くの開発者は、ユニットテストを自動統合テスト、自動機能テスト、および手動テストで補完しています。

単体テストで値が表示されない場合は、おそらく別の種類の自動テストを使用するのが最善の方法です。 Web環境では、 Selenium のようなブラウザ自動化テストツールを使用すると、比較的小さな投資で大きな成果が得られることがよくあります。つま先を水に浸すと、自動テストの有用性をより簡単に確認できるようになります。自動化されたテストがあれば、ユニットテストはより大きな意味を持ちます。これは、現在取り組んでいるコンポーネントだけでテストを対象にすることができるため、大きな統合テストやエンドツーエンドテストよりもターンアラウンドが速いためです。

TL; DR:単体テストについてはまだ心配しないでください。最初にソフトウェアをテストすることを心配してください。

49
Daniel Pryden

依存する

これは、ソフトウェア開発に関しては多くのことを理解するであろう答えですが、単体テストの有用性は、それらがどれだけうまく記述されているかに大きく依存します。回帰テストのためにアプリケーションの機能をチェックする単体テストの名目上の数は、非常に役立ちます。ただし、アプリケーションには「多数の単体テスト」があるため、関数の戻りをチェックする多数の単純なテストはまったく役に立たず、誤った安心感を与える可能性があります。

さらに、開発者としてのあなたの時間は貴重であり、単体テストの作成に費やされた時間は、新しい機能の作成に費やされなかった時間です。繰り返しになりますが、これは単体テストを記述すべきではないということではありませんが、すべてのパブリック関数には単体テストが必要ですか?私は答えがノーだと提出します。ユーザー入力検証を実行しているコードには、ユニットテストが必要ですか?それはアプリケーションの一般的な障害点であるため、かなり可能性があります。

これは経験が関係する分野の1つであり、時間の経過とともに、ユニットテストの恩恵を受けることができるアプリケーションの部分を認識しますが、その時点に到達するまでにはしばらくかかります。

41
rjzii

大学の授業のために行われるプロジェクトは、あなたが仕事で書くビジネスアプリケーションとは大きく異なります。違いは寿命です。大学はどのくらいの期間「生きている」と考えていますか?ほとんどの場合、コードの最初の行を記述したときに始まり、マークを取得したときに終了します。事実、それは実際には実装時のみ有効です。 「解放」は通常、「死」と同じです。

ビジネスのために行われるソフトウェアは、大学プロジェクトのそのリリース死点を上回り、ビジネスが必要とする限り存続します。これはvery longです。お金について話すとき、だれもが「冷たくてすっきりしたコード」を持つために壊れたペニーを使うことはありません。 25年前にCで記述されたソフトウェアがまだ機能し、十分に良好な場合(そのビジネスオーナーのニーズによって理解されているとおり)、それを維持するように求められます(新しい機能の追加、古い機能の改善-ソースコードの変更) )。

非常に重要な1つのポイント regression に到達します。私が働いている場所には、2つのチームが2つのアプリを管理しています。 1つは、5〜6年前にコードテストカバレッジがほとんどない状態で書きました*。2つ目は、full-blownテストスイート(ユニット、統合、および他にないもの)。どちらのチームにも専用の手動(人間)テスターがいます。最初のチームに新しい基本的な機能を導入するのにどれくらい時間がかかるか知りたいですか? 3〜4週間。この時間の半分は、「他のすべてがまだ機能するかどうかを確認する」ことです。これは手動テスターに​​とって忙しい時間です。電話が鳴り、人々は動揺し、何かが再び壊れます。通常、2番目のチームはこのような問題に3日未満で対処します。

ユニットテストでは、コードのエラーが発生しやすく、修正されたり、その他の派手な言葉になったりすることは決してありません。バグを魔法のように消すこともありません。しかし、自動化されたソフトウェアテストの他の方法と組み合わせると、他の方法よりもはるかにアプリケーションを保守しやすくなります。これは大きな勝利です。

そして最後に重要なことですが、問題全体を釘付けにすると思うブライアンのコメント:

(...)それらは、コードがあなたが設計したことを実行するというあなたの自信を高めます(またはすべきです...)、そしてそれが今日それが行うことを明日も続けます。

今日と明日の間に、誰かが小さな変更を加える可能性があるため、oh-so-importantレポートジェネレータコードがクラッシュします。テストあなたが顧客があなたの側に少しする前に、あなたがこれを見つけるであろう確率を押し出します。

*彼らは徐々にコードベースにますます多くのテストを導入していますが、私たちは皆、これが通常どのように見えるかを知っています。

38
k.m

は、ASP.NET Webフォームの単体テストを頻繁に実行するものを作成しています。その場合、「動的環境」の問題を解決するにはどうすればよいですか。

それはしばしば行われません。適切なものが画面の適切な場所に配置されることをプログラムで検証する優れた方法がないため、UI要素の操作は単体テストが得意ではありません。

ユニットテストを書き始めることを勧めますか?実際の実装ではそれが役立つかもしれないと思いますが、再び私はそれが私を遅くするかもしれないような気がします。

該当する場合、はい。これらは、特定のケースを再現可能な方法で検証するのに非常に役立ちます。これらは、厄介な変更に対する「摩擦」として、また、より良い変更を行う際のフェイルセーフとして機能するのに役立ちます。

注意すべきことの1つは、通常は遅くなることです

大丈夫です。

少しの時間を費やすことで、(うまくいけば)いくつかのバグをキャッチし、いくつかのバグの再発を防ぎ、腐敗を防ぐためにコードの他の改善をより快適に行えるようになるため、将来の時間を節約できます。

25
Telastyn

私はCSの学位を取得して卒業しました。現在、ジュニア.NET開発者(C#および通常はASP.NET、Webフォーム-ASP.NET MVCではない)としての仕事があります。私がまだ大学にいた頃、単体テストの主題はカバーされていましたが、その利点を実際に見たことがありませんでした。

大きくプログラミングしたことがないからです。

私はそれが何をすることになっているのか理解しています-コードのブロックが使用に適しているかどうかを判断します>しかし、実際にユニットテストを書く必要はありませんでした。 (または>必要性を感じたことはありませんでした。)

単体テストを作成すると、テストが可能で、十分に文書化され、信頼できる特定のメンタル構造にコードが準拠します。それはあなたが主張するものをはるかに超えています。

-私は、ユニットテストが「モック」を書くことによって頻繁に発生することを読みました。私はこの概念を理解していますが、完全に動的で、ほとんどすべてがデータベースからのデータに依存しているWebサイトのモックをどのように記述すればよいのか理解できません。

明確に定義されたハードコードされたデータで満たされたモデルクラスを返すモッククラスを使用して、データベースアクセスをモックします。 または、テストデータベースにフィクスチャデータを入力し、そこから作業します。

-ユニットテストを書き始めることをお勧めしますか?

もちろん。最初にBeckの "Test Driven Development" を読んでください。

実際の実装ではそれが役立つかもしれないと思いますが、再び私はそれが私を遅くするかもしれないような気がします。

それは今あなたを遅くします。しかし、数日ではなく数時間デバッグする必要がある場合は、気が変わります。

任意のアドバイスをいただければ幸いです:)

テスト。私を信じて。残念ながらそれはまた経営方針でなければなりません、しかしそれは時間を節約するものです。テストは残り、現在、そして未来にあります。プラットフォームを変更してテストを実行しても問題が解決しない場合は、想定どおりに機能することを知っています

11
Stefano Borini

編集:もちろん私はTDDプロ/コンドッグパイルに参加し、質問#1をスキップしました:

1-ASP.net Webフォームでの単体テストの実装:

まず第一に、あなたが彼らをMVCで動かすことができると思うなら、狂った洞窟のようにそれのために戦ってください。フロントエンド/ UI開発者として、.net MVCは.netを嫌うのをやめたので、Javaこれまでに遭遇したすべてのWebソリューションを嫌うことに集中することができました。ユニットテストは問題がありますWebフォームはサーバーとクライアント側の間の境界を本当に不鮮明にするためです。ユニットテストを実行する試みでは、データ操作に焦点を当て、(うまくいけば)Webフォームが内部でユーザー入力の正規化を処理すると仮定します。

2-そもそも単体テストに価値があるかどうか:

わかりました、完全開示:

  • 私はほとんど独学です。私の正式なトレーニングは、1つのJavaScript、PHP、C#クラスのようなものに要約され、OOPの原則とデザインパターンのようなものからの読書に関する私自身の個人的な研究です。

しかしながら、

  • 私は主にクライアント側のWeb向けに書きますが、実際のプログラミング部分は、動的型付け、ファーストクラスの関数、およびオブジェクトの可変性に関して、最も速く緩い言語の1つです。

つまり、同じコンパイラまたは仮想マシン用に作成することはありません。私は3つの言語の4-20のさまざまな解釈(そう、そのうちの2つは単に宣言的であるだけでなく、ときどきさまざまな方法で作業しているUIの基本的な物理空間を決定する)について書いており、解釈が彼らは今日よりもはるかに多様です。そして、いいえ、私は使い捨てアプリのためにJQueryのものをプラグインする子供ではありません。 UI要素が非常に複雑で、かなり洗練されたものを構築して維持するのに役立ちます。

だから、はい、設計スキルが完全に駄目だったり、品質の悪い開発者が1〜2個の品質の開発問題で大量に投げたりしている場合、あちこちに微調整を加える機会がたくさんあります。

TDDがあなたのために何をすることになっているのかについての私の理解は、テストは本当にあなたに設計をより注意深く検討し、あなたが要件に集中し続けることを強制することに関するものだということです。十分に公平ですが、ここでの問題は、インターフェースに対して設計している、やるべきことを、インターフェースのテストのために設計している、微妙ではあるが根本的に異なる何かに破壊することです。私との違いは、ママが意味を推測する必要がないという明確な絵を描くことと、ページ全体を非常に速く緑で塗りつぶすことです。そうすれば、最初の子供が彼のクレヨンをテーブルに平手打ちして「完了」と叫ぶことができます。 」プロセスと設計よりも優先順位を結果に移すことで、基本的にガベージコードの継続的な実装を奨励します。これは通常、最初に問題の根本にあったものです。

そしてもちろん、単体テスト自体が「実際には重要ではない」ものの、しばしば評判の良い副次的な利点があり、回帰エラーの検出に役立ちます。 TDDの提唱者は、これが実際に目標なのか、それとも単なる気の利いた副作用IMOなのかについて、少しでも希望に満ちている傾向があります。コード、特にJavaScriptのようなより動的な言語では、依存関係の長いチェーンで考えられるすべてのシナリオを予測できると仮定するのは簡単です。

JSには自動テストの場所がありますが、他のコードと接触するコードのすべての「ユニット」にユニットテストを添付するよりもはるかに時間を有効に活用することで、そもそも、作業を複製するガベージオブジェクト、または使用目的が意味的にあいまいであること。あなたはDRY原則に従います。そうすることの価値が明らかになったとき(そして1分前ではなく)に、再利用/移植性のために物事を抽象化します。一貫したプロセスと物事の方法を確立しますスティックの原則よりも多くのニンジンに従う(つまり、自分の原料を間違った方法でやりたくないという正しい方法で使用するのは簡単すぎる)そして、すべてのものfooとbarの愛のために、大規模なカスケード継承スキームにふけることは決してないコードの再利用の手段としてのアンチパターン。

上記のすべては、コード内の診断が難しいバグを真剣に減らすのに役立ちました。ブラウザセットを開発者として考え、他に何も言うことがない人にとっては、これが大きな優先事項であることは間違いありません。指定されていないファイルのこの架空の行番号で「オブジェクト」タイプのオブジェクトに問題が発生しました。」 (そう、IE6に感謝)TDDは、私の仕事では、これらのことを奨励しませんでした。それが機能するかぎり、ポイントAとBの間にあるものは実際には重要ではないプロセスでは、100%結果にフォーカスが移ります。そもそも、紛らわしい破損がほとんどなく、読みやすく、移植可能で、変更が容易であることを確認するために適用するのは時間の無駄です。

または、私が根付いているパラダイムについてだけ過度に悪口を言っているだけかもしれませんが、私の意見では、最初にそれを正しく行うことは、あなたやあなたの他の全員のためにあなたのお尻を覆うよりもはるかに効果的な時間の使用ですチームはそれを間違っています。そして、物事を実装するだけで設計を検討するように強いるものはありません。デザインはすべてのプログラマーの狂気の祭壇であるべきです。そして、正しいことをするように「強制する」または自分から自分を保護するものはすべて、ヘビ油のボトルIMOと同じ疑惑で見られるべきです。現代のITおよび一般的な開発におけるヘビ油は、まだご存じない場合は、液体トンで販売されています。

8
Erik Reppen

私の経験では、ユニットテストは実際に非常に役立ちます。テストを開始して、それらにとどまるとき、つまりテスト駆動開発です。理由は次のとおりです。

  • ユニットテストでは、実行するコードを記述する前に、必要なもの、およびそれを取得したことを確認する方法について考える必要があります。 TDDシナリオでは、最初にテストを記述します。したがって、コードを次のように記述して「緑」にする「赤」のテストを作成するには、作成しようとしているコードが何を実行する必要があるか、またそれが正常に行われたことを確認する方法を知る必要があります。それを渡します。多くの場合、これにより、このテストに合格するために作成しようとしているアルゴリズムについてもう少し考える必要があります。これは、論理エラーと「コーナーケース」を減らすので、常に良いことです。あなたがテストを書いている間、あなたは「ここで失敗する方法が失敗する可能性がある」および「私は何であるかここではテストしない」と考えています"、これはより堅牢なアルゴリズムにつながります。

  • ユニットテストでは、記述しようとしているコードがどのように消費されるかを考えるように強制されます。 TDDを学ぶ前に、依存関係が一方向に機能することを期待してコードを記述し、まったく異なる方法で機能する同僚から依存関係が与えられることがよくありました。 TDDでもこれは可能ですが、作成中の単体テストでは、作成中のオブジェクトの使用方法を考える必要があります。これは、前述のオブジェクトの使用例だからです。うまくいけば、使いやすく、必要に応じて適応できるようにオブジェクトを記述できます(ただし、事前定義されたインターフェイスへのプログラミングは、TDDを必要としないこの問題に対する総合的な解決策です)。

  • ユニットテストでは、「テストによるコーディング」が可能です。 ReSharperのようなリファクタリングツールは、許可すれば最高の友になることができます。これを使用して、テストでの使用法を定義するときに、新しい機能のスケルトンを定義できます。

    たとえば、新しいオブジェクトMyClassを作成する必要があるとします。まず、MyClassのインスタンスを作成します。 「しかし、MyClassは存在しません!」とReSharperは不平を言います。 Altキーを押しながらEnterキーを押すと、「それを作成します」と言います。そして、あなたはあなたのクラス定義を持っています。テストコードの次の行で、メソッドMyMethodを呼び出します。 「しかし、それは存在しません!」とReSharperは言います。 「それを作成します」と、Alt + Enterを繰り返します。数回のキー操作で、新しいコードの「スケルトン」を定義しました。使用法を具体化し続けると、IDEは何かが合わない場合に通知し、通常はIDEまたはそれに接続するツールはそれを修正する方法を知っています。

    より極端な例は、「Triple-A」モデルに準拠しています。 「アレンジ、アクト、アサート」。すべてを設定し、テストしている実際のロジックを実行してから、ロジックが正しいことをアサートします。このようにコーディングすると、ソリューションをテストにコーディングするのが非常に自然になります。次に、キーを数回押すだけで、そのロジックを抽出して、それを本番コードで使用できる場所に配置し、テストに小さな変更を加えて、ロジックの新しい場所を指すようにすることができます。この方法を使用すると、テストしているユニットに引き続きアクセスできる必要があるため、モジュールを再利用しやすい方法でコードを設計する必要があります。

  • ユニットテストは、考えられる手動テストよりもはるかに高速に実行されます。ユニットテストのオーバーヘッドが発生し始める、より大きなプロジェクトの場合、非常に迅速に満たされるポイントがあります。手動テストに費やす時間を削減することにより、作成したコードは常に実行する必要があります。従来は、大規模なプログラムを起動し、UIをナビゲートして動作を変更した状況を設定し、UIを介して、または生成されたデータの形式で結果を再度確認することにより、手動で行っていました。コードがTDDされている場合は、単体テストを実行するだけです。優れた単体テストを作成している場合は、後者のオプションが前者より何倍も速くなることを保証します。

  • ユニットテストは回帰をキャッチします。繰り返しますが、私がTDDについて学び、コードの一部に外科的な変更を加え、報告された状況で誤った動作を修正した(または新しい望ましい動作を生成した)ことを確認する前に、何度も、それをリリース用にチェックインしましたが、まったく同じコードブロックを再利用してしまった完全に異なるモジュールで、変更が他のコーナーケースに違反していることがわかりました。 TDDされたプロジェクトでは、これから行う変更を検証するテストを作成し、変更を加えてから、スイート全体を実行し、コードの他のすべての使用法がTDDされ、変更が何かを壊した場合、それらのテストを行うことができます他のことは失敗し、私は調査することができます。

    開発者が潜在的な変更の影響を受ける可能性のあるすべてのコード行を手動で見つけてテストしなければならない場合、変更の影響を判断するコストによって変更が実行不可能になるため、何も行われません。少なくとも、何もSOLID=でなく、簡単にメンテナンスできます。複数の場所で使用される可能性のあるものに手を触れることは決してないため、代わりに独自の非常に似ていますが、この1つのケースにマイナーチェンジのソリューションを組み込んで、SRPおよびおそらくOCPに違反し、コードベースをゆっくりとパッチワークキルトに変えます。

  • 通常の方法でユニットアーキテクチャが形状アーキテクチャをテストします。単体テストは、他のロジックから分離して実行されるテストです。コードを単体テストできるようにするには、コードを分離することができるようにコードを記述する必要があります。したがって、疎結合や依存性注入などの適切な設計決定は、当然TDDプロセスから排除されます。テストで「副作用」を作成せずに、テストされる状況の入力を生成または出力を処理する「モック」または「スタブ」を注入できるように、依存関係を注入する必要があります。 TDDの「使用優先」の考え方は一般に、疎結合の本質である「インターフェースへのコーディング」につながります。これらの優れた設計原則により、適応するためにコードベースの大部分を変更する必要なく、クラス全体を置き換えるなど、プロダクションに変更を加えることができます。

  • provingコードが機能するの代わりに、コードが機能することをユニットテストshowします。一見するとデメリットだと思うかもしれません。確かに証明はデモンストレーションよりも優れていますか?理論は素晴らしいです。計算理論とアルゴリズム理論が私たちの仕事の基礎です。しかし、アルゴリズムの正確さの数学的証明は、not実装の正確さの証明です。数学的証明は、アルゴリズムに準拠するコードが正しいであることを示しているだけです。ユニットテストは、実際に書かれたコードがあなたがそれをするだろうと思ったことをすることを示し、したがって、それがそれを証明します正しいです。これは一般に、理論的な証明よりもずっと価値があります。

さて、すべてのことを言いましたが、単体テストには欠点があります。

  • すべてを単体テストすることはできません。ユニットテストでカバーされないLOCの数を最小限に抑えるようにシステムを設計することができますが、ユニットテストできないシステムの特定の領域があるだけです。データアクセスレイヤーは、他のコードで使用するときにモックすることができますが、データアクセスレイヤー自体に多くの副作用が含まれており、通常、リポジトリ(またはDAO)の多く(ほとんど?)を単体テストすることはできません。同様に、ファイルを使用したり、ネットワーク接続を設定したりするコードには、組み込みの副作用があり、それを行うコード行を単体テストすることはできません。多くの場合、UI要素は単体テストできません。イベントハンドラーなどのコードビハインドメソッドをテストしたり、コンストラクターを単体テストしたり、ハンドラーがプラグインされていることを確認したりできますが、ユーザーが特定のグラフィック要素でマウスをクリックしてハンドラーが呼び出されるのを監視するためのコード内の代用はありません。十分にユニットテストできるものとできないものの間のこれらの境界に到達することは、「サンドボックスのエッジをこする」と呼ばれます。それ以降は、統合テスト、自動受け入れテスト、および手動テストを使用して動作を確認することに限定されます。

  • 単体テストの多くの利点はTDDなしでは適用されません。コードを記述してから、コードを実行するテストを記述することは完全に可能です。それらはまだ「単体テスト」ですが、最初にコードを作成することにより、「テストファースト」開発に固有の多くの利点を失うことになります。コードは、簡単にテストしたり、本番環境で使用したりできるように設計されているとは限りません。 ;テストを書いて、あなたが考えていなかったものについて考えることに固有の「ダブルチェック」思考プロセスを得られません。テストによるコーディングは行いません。コードを作成する場合は、手動でテストして機能することを確認してから、失敗した単体テストをコーディングします。主な利点は、退行防止(以前はテストに合格したコードが失敗した場合に警告される)と手動テストと比較した高速検証です。 TDDの他の利点が失われると、単体テストをまったく使用しないようにバランスを崩す可能性があります。

  • 単体テストではオーバーヘッドが発生します。簡単に言うと、コードを書いて、コードをテストしています。これにより、開発プロジェクトのLOCの合計が必ず増加します。そうです。テストのLOCは、実際のプロジェクトのLOCを超える可能性があります。素朴な開発者と非開発者はこの状況を見て、テストは時間の無駄だと言います。

  • 単体テストには規律が必要です。コードベース(適切なコードカバレッジ)を適切に実行するテストを作成し、定期的に実行する必要があります(変更をコミットするときはいつでも、スイート全体を実行する必要があります)。すべてを「グリーン」に保つ必要があります(すべてのテストに合格)。物事が壊れたときは、期待に応えないコードを修正するか、テストの期待を更新することで修正する必要があります。テストを変更する場合は、「理由」を尋ね、自分自身を非常に注意深く監視する必要があります。失敗したアサーションを現在の動作と一致するように変更したり、失敗したテストを削除したりするのは非常に魅力的です。しかし、これらのテストは要件に基づいている必要があり、2つが一致しない場合は問題があります。これらが行われていない場合、各テストを使用して実際に作成しているコードをテストに最後に触れた時点で機能をテストすると、テストに価値がなくなります(これは、最初の開発または外科的変更が思ったとおりに行われたことを証明するためです)あなたが書いたとき)。

  • 単体テストには追加の機器が必要です。上記の規律の必要性、および人間が怠惰で無関心になる傾向の通常の解決策は、単体テストを実行し、計算するTeamCity、CruiseControlなどの「継続的統合」ソフトウェアパッケージを実行する「ビルドボット」です。コードカバレッジメトリック、および「トリプルC」(コーディング規約のコンプライアンス、la FxCop)などの他のコントロールがあります。ビルドボットのハードウェアは適度に機能する必要があり(そうでない場合、平均的なチームが行うコードチェックインの速度に追いつかない)、ボットのチェックイン手順を最新の状態に保つ必要があります。ユニットテストの新しいライブラリが作成されます。ユニットテストを実行するビルドスクリプトは、そのライブラリを参照するように変更する必要があります)。これは思ったより作業量が少ないですが、通常、さまざまなビルドプロセスの要点がどのように機能するかを知っている(したがって、スクリプトでそれらを自動化し、上記のスクリプトを維持できる)チームの少なくとも数人の側に技術的な専門知識が必要です。 。また、ビルドが「壊れる」ときは注意を払い、新しいものがチェックインされる前にビルドが(正しく)壊れる原因を修正するという形での規律も必要です。

  • ユニットテストでは、コードを非理想的な方法で設計する必要があります。 TDDは通常、コードのモジュール性と再利用性に優れていますが、コードの適切なアクセス可能性に悪影響を与える可能性があります。本番ライブラリに配置されたオブジェクトとメンバーは、単体テストで直接使用される場合、プライベートまたは内部にすることはできません。これは、現在オブジェクトを参照している他のコーダーが、ライブラリに存在する何かを代わりに使用する必要があるときにそれを使用しようとすると問題を引き起こす可能性があります。コードレビューはこれを助けることができますが、それは問題になることがあります。

  • 通常、ユニットテストでは「迅速なアプリケーション開発」コーディングスタイルは禁止されています。単体テストを作成している場合は、「速くて緩い」コーディングはしていません。これは通常は良いことですが、コントロールの外部から課せられた期限に達している場合、または非常に小さなスコープの変更を実装していて、利害関係者(または上司)が、なぜこの残酷なことがすべて発生しなければならないのか疑問に思っている場合コードの1行を変更すると、適切な単体テストスイートを作成して維持することは、単に実行不可能になる可能性があります。アジャイルプロセスは、通常、開発者に時間要件の発言権を与えることでこれを支援します。プロセスが実際に仕事をしなければならない人々が「できない」と言って注意を払っている必要がある場合を除いて、セールスマンがしなければならないことは「できる」と言うだけであり、手数料チェックを受けます。しかし、すべての人のアジャイルではなく、アジャイルには独自の制限があります。

5
KeithS

触れられていないように見えることの1つは、さまざまなタイプのコードのテストの複雑さです。

単純な入力と出力を持つものを扱う場合、一般的に単体テストは簡単です。テストが、テストされるコードのEdgeケースを念頭に置いて選択されている場合、それらが正しいことを確信できます。そのようなコードのテストを書かないのはおかしいでしょう。 (ライブラリに入れるほとんどのコードはこの基準を満たしていることに注意してください。)

ただし、他のケースでは、コードが複雑な基礎データ(通常はデータベースですが、そうである必要はありません)で遊んでいるか、非常に複雑な出力データを生成するために、テストするために巨大なモックを構築する必要があります(変換するルーチンを考えてください)かなり極端な例として、ゲームレベルへのシード値)とユニットテストはほとんど役に立ちません。通常、テストケースのすべてをカバーすることは夢のようなことであり、バグを見つけた場合、ほとんどの場合、それはあなたが考えたこともないため、とにかくテストを構築できませんでした。

銀の弾丸はありません。銀の弾丸として描写されているものは、支持者が主張するほど優れていませんが、それが役に立たないという意味ではありません。

4
Loren Pechtel

単体テストは、正しく使用すると便利です。ロジックにはさまざまな問題があります。

「私が開発しているとき、私は多くの試行錯誤を繰り返します」とケビンは言いました。

偶然にプログラミングを見てください。コードが何をすべきかを理解し、ユニットテストを介してそれが機能することを証明することをお勧めします。プログラムを実行したときにUIが壊れなかったからといって、コードが機能するとは限りません。

s writing unit tests for ASP.NET web forms something that is done often

私は人々がどれほど頻繁にウェブフォームをテストするかについて言う統計データの知識がありません。それはどうでもいい事です。 UIのテストは困難であり、単体テストもUIと組み合わせるべきではありません。ロジックをレイヤー、テスト可能なクラスライブラリに分離します。バックエンドロジックとは別にUIをテストします。

So, question number 2: Would you guys advise me to start writing unit tests?

はい。あなたが彼らに慣れると、彼らはあなたをスピードアップします。メンテナンスは、初期の開発フェーズよりもはるかに時間とコストがかかります。ユニットテストでは、初期テストやバグの修復でも、メンテナンスが大幅に支援されます。

4
P.Brian.Mackey

ASP.NET Webフォームアプリケーションの単体テストの記述は一般的ではなく、達成するのは非常に困難です。ただし、プロジェクトがそれをスキップする必要があるという意味ではありません。

単体テストはcorner stonesミッションクリティカルなアプリケーションの数を増やし、コア機能が期待どおりに機能するという信頼性と安心を提供します。

実際には、Webフォーム開発で使用できるASP.NET MVPパターンを使用すると、ユニットテストをはるかに簡単に導入できます。関心の分離とability to write essential unit tests

見るのに役立つかもしれないいくつかの参照は次のとおりです。

4
Yusubov

実用的なレベルでは、ユニットテストは非常に重要な理由で非常に役立ちます。一度に1ビットのコードをテストできます。

一連の複雑なステップ全体を記述し、最後にそれらをデバッグする場合、多くのバグが見つかる傾向があり、プロセスが進んでいるため、プロセスは一般的に難しくなります。 Visual Studioでは、クイックテストを生成し、少し変更して、そのテストのみを実行できます ..次に、たとえば、そのメソッドを呼び出すメソッドがそれに依存できることがわかります。だからそれは自信を高めます。

ユニットテストは、プログラムが正しいことを証明しません!:ユニットテストは、機密コードのリグレッションをチェックし、作成した新しいメソッドをテストできるようにします。

ユニットテストはフロントエンドをテストするためのものではありません:ユニットテストは、コードが必要とするある種の条件ではなく、作成している新しいメソッドまたは何かをテストするために作成する小さなプロジェクトと考えてください。会うために。

ユニットテストはコラボレーション環境に最適です:完全に異なるテクノロジーを使用している同僚にメソッドを提供する必要がある場合(たとえば、iOSから呼び出している場合)、すぐに書くことができます彼が望む方法を確認するための単体テストa)正しいデータを返すb)彼の仕様に従って実行するc)厄介なボトルネックがない.

4
Tjaart

ユニットテストの目的は、システム内の何かを壊す恐れがないように、コードを安全に変更(リファクタリング、改善など)できるようにすることです。これは、(疎結合にもかかわらず)コード変更のすべての影響がわからない場合に、大規模なアプリケーションで非常に役立ちます。

3
m3th0dman

yes、単体テストが役立つのは私の経験です。

ユニットテストでは、記述したコードの一部を分離し、それらが分離して機能することを確認します。この分離には、実際に、テストしているオブジェクトと通信するための偽のオブジェクトまたはモックオブジェクトの作成が含まれる場合と、そうでない場合があります。オブジェクトのアーキテクチャに大きく依存します。

単体テストにはさまざまな利点があります。

主に、これにより、テストするユニットが、開発者であるユーザーが機能する必要があると考える方法で機能することが保証されます。これは意外と少ないですが、必ずしもオブジェクトが正しく機能しているとは限りません。それはあなたがそれがうまくいくと思う方法で機能しているということだけで、ユニットテストなしで必要な試行錯誤法よりもはるかに強力な声明です。

さらに、ユニットは、開発者であるユーザーthoughtが機能するはずの方法で機能し続けることを保証します。ソフトウェアの変更により、予期しない方法でユニットに影響を与える可能性があります。

別の副作用は、テストするユニットdoが単独で機能することを意味します。これは一般に、具体的なクラスではなくインターフェイスへのプログラミングを開始し、結合を減らして凝集度を高めることを意味します。優れた設計のすべての一般的な特徴です。はい:コードのユニットでhaveユニットテストを有効にするだけで、コードの設計が自然に改善されます。

ただし...

単体テストはテストの終わりではありません。他の種類のテストはまだ必要です。たとえば、ユニットが期待どおりに機能することを示した場合でも、各ユニットが、それと通信するユニットが期待どおりに機能することを示す必要があります。つまり、コンポーネントは互いに正しく統合されていますか?

2
Kaz Dragon

これに新しい側面(実際にはかなり古い側面)を追加したいと思います。コードがwell-designedの場合、単体テストはそれほど役に立ちません。

ほとんどのプログラマーはもはやプログラム設計を行わないことを知っています。私はまだそうしています。ユニットテストはTDDカルチャーに適合するためにかなり時間がかかる必要であることがわかりましたが、これまでのところ、わずか1〜2のマイナーにしか会っていません。私のコードの何千行ものテストごとのバグ-私が書いたものだけでなく、公式のテスターも書いたもの。

プログラム設計をもうやらないと思います-現在の人々はそれをしないように型に圧力をかけます-しかし、おそらくユニットテストは設計と比べて非常に効率の低い方法であることを覚えておく価値があります。

これはダイスクトライアンの引数です。単体テストは、実行するのに十分詳細なプログラムに対してのみ実行できます。

実際にコードを記述する前に、フローチャート/状態/アクション図、シーケンス図、オブジェクトインベントリ(および最後のAND最小クラス図)をコードに描画すると、トレースするだけで、潜在的に脅威となる可能性のあるバグのほとんどを取り除くことができます。あなたの行とあなたの名前をチェックします。

現在、クラス図は数百、時には数千のクラスを含むコードから生成され、完全に使用できません。15を超える要素を含むものは、人間の認識を超えています。

10 + -5クラスの重要性や現在何をしているのかを理解し、複数の視点からコードをチェックできる必要があります。各図は、見ている視点を正確に表しており、何千ものバグを取り除くことができます。紙の上に。

  • タイプが満たされているかどうかを動的コードでチェックインします(単にフローチャートに入出力タイプを表示し、鉛筆または別の色でそれらを接続するだけです)
  • すべての状態が処理されているかどうかをチェックします(条件の完全性をチェックすることにより)、
  • ラインをトレースしてすべてが確実に終了するようにします(すべてのフローチャートは、完全に定義された確定的有限状態オートマトンである必要があります。
  • 特定のコンポーネントが相互に何の関係もないようにする(すべての依存関係を抽出することにより)(セキュリティに良い)
  • 依存関係を関連付けに変換することでコードを簡略化します(依存関係は、メンバーメソッドが使用するクラスに由来します)
  • 名前の確認、一般的なプレフィックスの検索、類義語の消去など...

とても簡単です...

また、アプリケーションがユースケースから直接取得された場合、アプリケーションがより使いやすいこともわかりました...ユースケースが適切に記述されている場合(ACTOR動詞の件名、メンテナーが現金自動預け払い機を開くように要求)...

95%以上のコードカバレッジでコードを実行しました。もちろん、私は時々ユニットテストをします、特に。計算の境界チェック用ですが、リファクタリングのためにもユニットテストを使用しないため、深刻な回帰(深刻な:24時間で一掃されない)にはまだ対応できていません。

たまに、1行のコードを3〜4日間続けずに描画するだけです。その後、ある日、1500〜2000行を入力します。翌日までに、それらはほとんど生産準備が整っています。単体テストが記述される(カバレッジの80%以上)こともあれば、テスターがそれを解読するように求められることもあります。毎回、何人かはそれを見てレビューするように求められます。

私はそれらの単体テストが何かを見つけるのをまだ見ていません。

TDDの代わりにデザイン思考を取り入れればいいのですが... TDDの方がはるかに簡単です。それは、ハンマーで行くようなものです...設計について考える必要があり、ほとんどの場合、キーボードはありません。

1
Aadaam

テストするレイヤーの数が少ないシンプルなアプリの場合(メインウィンドウ->サブメニュー)、変更を確認するために実行するようにコンパイルするとよいでしょう。

テストしているページを取得するのに30秒のナビゲーションが必要な大規模なアプリの場合、これはvery高額になります。

1