タグ付けされた質問 「tdd」

TDDは、テスト駆動開発またはテスト駆動設計の略です。Red-Green-Refactorサイクルとして知られている、それを満たすためにコードを書く前に単体テストを書く習慣です。

10
ユニットテストアプリケーションロジックと不信な言語構成要素の境界線はどこですか?
次のような関数を考えてみましょう。 function savePeople(dataStore, people) { people.forEach(person => dataStore.savePerson(person)); } 次のように使用できます。 myDataStore = new Store('some connection string', 'password'); myPeople = ['Joe', 'Maggie', 'John']; savePeople(myDataStore, myPeople); 独自の単体テストがあるか、ベンダーが提供していると仮定しましょうStore。いずれにせよ、私たちは信頼していStoreます。さらに、エラー処理(たとえば、データベースの切断エラーなど)はの責任ではないと仮定しましょうsavePeople。実際、ストア自体が魔法のようなデータベースであり、何らかのエラーが発生する可能性はないと仮定しましょう。 これらの仮定を考えると、問題は次のとおりです。 savePeople()単体テストする必要がありますか、それとも組み込みのforEach言語構成のテストに相当しますか? もちろん、モックdataStoreを渡し、dataStore.savePerson()各人に1回呼び出されることをアサートすることもできます。このようなテストは実装の変更に対するセキュリティを提供するという議論を確かに行うことができます。たとえば、forEach従来のforループや他の反復方法に置き換えることを決めた場合です。そのため、テストは完全に簡単ではありません。そしてそれでもひどく近いようです... より実りの多い別の例を次に示します。他のオブジェクトや機能を調整する以外の何もしない機能を考えてください。例えば: function bakeCookies(dough, pan, oven) { panWithRawCookies = pan.add(dough); oven.addPan(panWithRawCookies); oven.bakeCookies(); oven.removePan(); } このような機能は、どのようにユニットテストされるべきでしょうか?私は単純にモックていないユニットテストのいずれかの種類を想像するのは難しいdough、panとovenして、メソッドがそれらに呼ばれていると主張します。しかし、そのようなテストは、関数の正確な実装を複製する以上のことはしていません。 意味のあるブラックボックスの方法で関数をテストできないことは、関数自体の設計上の欠陥を示していますか?もしそうなら、どのように改善できますか? bakeCookies例の動機となる質問をさらに明確にするために、より現実的なシナリオを追加します。これは、テストを追加してレガシーコードをリファクタリングしようとしたときに遭遇したシナリオです。 ユーザーが新しいアカウントを作成するとき、いくつかのことを行う必要があります:1)新しいユーザーレコードをデータベースに作成する必要がある2)ウェルカムメールを送信する必要がある3)ユーザーのIPアドレスを詐欺のために記録する必要がある目的。 そこで、すべての「新規ユーザー」ステップを結び付けるメソッドを作成します。 function createNewUser(validatedUserData, emailService, dataStore) …

10
なぜアジャイルがテスト駆動開発(TDD)であり、開発駆動テスト(DDT)ではないのですか?
したがって、アジャイルは初めてですが、テスト駆動開発ではありません。大学の私の教授は、テスト、コード、そしてテストのアイデアについてすべてでした。理由がわかりません。私の観点からは、多くの初期費用であり、おそらくコードが進化するにつれて変更されるでしょう。 これが私がTDDを想像し、それが私を混乱させる理由です。TDDの請負業者として家を建てる場合。 すべての仕様(ストーリー)を教えてください。 仕様の承認を取得します。 すべての仕様を検査に分解します(今後参照してください)。 検査官に電話してそれらの点を見て、今私は検査に失敗していると教えてください(ありがとう)。 家を建て始めます。 インスペクタを毎日コールバックします(2/100を渡します)。 ああ、私の理解に問題があったので、今度は9つの検査を追加して、27を変更する必要があります。 1/109を渡すインスペクターを呼び出します。 畜生。なぜインスペクターはこのようなものではないのでしょうか...ああ、そのメソッド名を更新しました... さらにビルドします。 UGGGGHHHHのその他の変更により、いまいましいインスペクタを更新できます。ああ、私は失敗していません。 もう終わった? さて、それは奇妙なことかもしれませんが、すべてのメソッドをどのように知るべきか、そしてコードがそこに来るまでどのように機能するかはわかりません。99%の時間、戻ってユニットテストを更新する必要があります。ただ逆に思えます。 より適切と思われるのは、DDTまたは開発主導のテストです。これは、コミュニティが忘れてしまったことのように思えます。 私の理解では、家のDDTは次のようになります。 すべての仕様(ストーリー)を教えてください。 仕様の承認を取得し、それらを分割します。 ユニット(基礎)を開始します。 トリッキーなロジックのメモ(コメント)を取ります。 最後に次のユニットの検査を開始します(テストを作成します)。 見つかった問題を修正し、再度検査します。 このユニットが次のユニットに移動することを承認しました。 私たち全員が正直であるならば、それはより人間的で、開発者とビジネスに集中しているとは思わないでしょうか?変更をより速く行うことができ、オーバーヘッドなしでTDDが作成されるようです。

7
既存のコードのテストを書く
比較的大きなプログラム(C#で900k SLOCなど)があり、すべてが十分にコメント/文書化され、適切に組織化され、適切に機能しているとします。コードベース全体は、もはや会社にいない単一の上級開発者によって作成されました。すべてのコードはそのままテスト可能であり、IoCが全体で使用されます(ユニットテストを作成しなかった奇妙な理由を除く)。今、あなたの会社はコードを分岐させ、変更がコア機能を壊すときを検出するために単体テストを追加したいと考えています。 テストの追加は良いアイデアですか? もしそうなら、どのようにしてこのようなものから始めるのでしょうか? 編集 わかりました、それで私は反対の結論に対して良い議論をする答えを期待していませんでした。とにかく問題は私の手に負えないかもしれません。私も「重複した質問」を読みましたが、一般的なコンセンサスは「テストを書くのは良い」ということです...ええ、しかしこの特定のケースではあまり役に立ちません。 レガシーシステムのテストを書くことをここで考えているのは私だけではないと思います。どれだけの時間を費やし、新しいテストが問題をキャッチする回数(および、そうでない回数)のメトリックを保持します。私は戻って来て、私の結果でこれから1年かそこらを更新します。 結論 そのため、正統性に似た既存のコードに単体テストを追加することは基本的に不可能です。コードが動作すると、テストを赤信号/緑信号にすることは明らかにできません。通常、テストする必要がある動作が明確ではなく、どこから始めればよいか、完了したら明確ではありません。本当にこの質問をすることでさえ、そもそもテストを書くことの主要なポイントを見逃しています。ほとんどの場合、意図した機能を解読してユニットテストを遡及的に追加するよりも、TDDを使用してコードを書き直す方が実際に簡単であることがわかりました。問題を修正したり、新しい機能を追加したりするのは別の話であり、ユニットテストを追加するときだと思います(以下で指摘するように)。最終的には、ほとんどのコードが書き直され、多くの場合、予想よりも早くなります。

7
単体テストとテスト駆動開発の違い
説明を読むことで、TDDテストでは関数を記述する前に行われ、ユニットテストでは後に行われることを理解しています。 これが主な違いですか、それとも2つの用語を比較することすらできませんか。おそらく、ユニットテストはTDDに統合された部分です。

7
テスト容易性を設計する際に静的ユーティリティクラスを処理する方法
TDDを使用して開発されたほとんどの部分で、テスト可能なシステムを設計しようとしています。現在、次の問題を解決しようとしています。 さまざまな場所で、ImageIOやURLEncoder(標準Java APIの両方)などの静的ヘルパーメソッド、および大部分が静的メソッド(Apache Commonsライブラリなど)で構成されるその他のさまざまなライブラリを使用する必要があります。しかし、このような静的ヘルパークラスを使用するメソッドをテストすることは非常に困難です。 この問題を解決するためのアイデアがいくつかあります。 静的クラス(PowerMockなど)をモックできるモックフレームワークを使用します。これは最も簡単な解決策かもしれませんが、どういうわけかあきらめたように感じます。 これらのすべての静的ユーティリティの周りにインスタンス化可能なラッパークラスを作成して、それらを使用するクラスに注入できるようにします。これは比較的クリーンなソリューションのように聞こえますが、これらのラッパークラスを大量に作成することになると思います。 これらの静的ヘルパークラスへのすべての呼び出しをオーバーライド可能な関数に抽出し、実際にテストするクラスのサブクラスをテストします。 しかし、TDDを行う際に多くの人が直面しなければならない問題であるに違いないと私は考え続けます。したがって、この問題の解決策はすでに存在しているはずです。 これらの静的ヘルパーを使用するクラスをテスト可能に保つための最良の戦略は何ですか?

7
単体テストの代わりに受け入れテストと統合テストを使用するだけで十分ですか?
この質問の簡単な紹介。私は現在TDDと最近BDDを1年以上使用しています。私は、モックなどの手法を使用して、テストをより効率的に記述します。最近、私は自分のために小さなお金管理プログラムを書くための個人的なプロジェクトを始めました。レガシーコードがなかったため、TDDから始めるのに最適なプロジェクトでした。残念ながら、TDDの喜びはあまり経験しませんでした。それは私の楽しみを台無しにし、プロジェクトをあきらめました。 なにが問題だったの?さて、TDDのようなアプローチを使用して、テスト/要件がプログラムの設計を進化させました。問題は、テストの作成/リファクタリングに関して、開発時間の半分以上がかかっていたことです。したがって、リファクタリングして多くのテストに書き込む必要があるため、最終的にはこれ以上機能を実装したくありませんでした。 職場では、レガシーコードがたくさんあります。ここでは、統合テストと受け入れテストを増やし、単体テストを減らしていきます。ほとんどのバグは受け入れテストと統合テストによって検出されるため、これは悪いアプローチではないようです。 私の考えは、最終的には単体テストよりも多くの統合テストと受け入れテストを書くことができるということでした。バグを検出するために言ったように、単体テストは統合/受け入れテストよりも優れていません。単体テストも設計に適しています。私はそれらの多くを書いていたので、私のクラスは常にテストしやすいように設計されています。さらに、テスト/要件が設計をガイドできるようにするアプローチは、ほとんどの場合、より良い設計につながります。単体テストの最後の利点は、高速であることです。ユニットテストとほぼ同じ速度で実行できることを知るために、十分な統合テストを作成しました。 ウェブを調べた後、私の考えによく似たアイデアがあちこちであることがわかりました。この考えをどう思いますか? 編集 質問には、デザインは良かったが、次の要件のために大規模なリファクタリングが必要な例の1つに答えました。 最初は、特定のコマンドを実行するためのいくつかの要件がありました。拡張可能なコマンドパーサーを作成しました。これは、ある種のコマンドプロンプトからコマンドを解析し、モデル上で正しいものを呼び出しました。結果は、ビューモデルクラスで表されました。 ここには何も問題はありませんでした。すべてのクラスは互いに独立しており、新しいコマンドを簡単に追加し、新しいデータを表示できました。 次の要件は、すべてのコマンドに独自のビュー表現(コマンドの結果の何らかのプレビュー)が必要であることです。新しい要件に対してより良い設計を実現するために、プログラムを再設計しました。 これは、すべてのコマンドに独自のビューモデルがあり、したがって独自のプレビューがあるためです。 問題は、コマンドパーサーがコマンドのトークンベースの解析を使用するように変更され、コマンドを実行する機能が削除されたことです。すべてのコマンドには独自のビューモデルがあり、データビューモデルは、表示する必要があるデータを知っている現在のコマンドビューモデルのみを知っています。 この時点で私が知りたかったのは、新しいデザインが既存の要件を満たさなかった場合のみです。受け入れテストを変更する必要はありませんでした。ほぼすべての単体テストをリファクタリングまたは削除する必要がありましたが、これは膨大な作業の山でした。 ここで見せたかったのは、開発中によく発生する一般的な状況です。古いデザインでも新しいデザインでも問題はありませんでした。要件に応じて自然に変更されただけでした。私がどう理解したか、これはTDDの利点の1つであり、デザインが進化します。 結論 すべての答えと議論をありがとう。この議論の要約として、次のプロジェクトでテストするアプローチを考えました。 まず、いつものように何かを実装する前に、すべてのテストを作成します。 要件については、最初にプログラム全体をテストする受け入れテストをいくつか作成します。次に、要件を実装する必要があるコンポーネントの統合テストをいくつか作成します。この要件を実装するために別のコンポーネントと密接に連携するコンポーネントがある場合、両方のコンポーネントが一緒にテストされる統合テストも作成します。最後になりましたが、アルゴリズムまたは他のクラスを高い順列(シリアライザーなど)で記述する必要がある場合は、この特定のクラスの単体テストを記述します。他のすべてのクラスはテストされませんが、単体テストが行​​われます。 バグについては、プロセスを簡素化できます。通常、バグは1つまたは2つのコンポーネントによって引き起こされます。この場合、バグをテストするコンポーネントの統合テストを1つ作成します。アルゴリズムに関連する場合は、ユニットテストのみを記述します。バグが発生したコンポーネントを簡単に検出できない場合、受け入れテストを作成してバグを特定します。これは例外です。

10
すべてのメソッドをテストする必要がありますか?
それで今日、チームメイトとユニットテストについて話しました。全体が始まったのは、彼が「ねえ、そのクラスのテストはどこにありますか、1つしか見えないのですか?」クラス全体がマネージャー(または、そのように呼び出したい場合はサービス)であり、ほとんどすべてのメソッドが単にものをDAOに委任しているため、次のようになりました。 SomeClass getSomething(parameters) { return myDao.findSomethingBySomething(parameters); } ロジックを持たない種類のボイラープレート(または、少なくともロジックのような単純な委任を考慮していない)ですが、ほとんどの場合(レイヤー分離など)に便利なボイラープレートです。そして、ユニットテストを行うかどうかについてかなり長い議論がありました(DAOの完全なユニットテストを行ったことは言及する価値があると思います)。彼の主な議論は、TDDではないこと(明らかに)、誰かがこのメソッドが何をするかを確認するためにテストを見たいと思うかもしれない(それがどのようにもっと明白になる可能性があるのか​​わかりません)、または将来誰かが変更したいかもしれないということです実装し、それに新しい(または「より多く」のような)ロジックを追加します(この場合、誰かが単純にそのロジックをテストする必要があると思います)。 しかし、これは私に考えさせられました。最高のテストカバレッジ%を目指して努力する必要がありますか?それとも、それは単に芸術のための芸術ですか?私は、次のようなテストの背後にある理由をまったく見ていません。 ゲッターとセッター(実際に何らかのロジックがある場合を除く) 「定型」コード 明らかに、このようなメソッド(モックを使用)のテストには1分もかかりませんが、それでも時間の無駄であり、CIごとに1ミリ秒長くなると思います。 コードのすべての(または彼ができる限り)行をテストする必要がある理由について、合理的/「可燃性でない」理由はありますか?

16
TDDを行うときにすべてのテストを一度に書いてみませんか?
TDDの赤-緑-リファクタリングサイクルは十分に確立され、受け入れられています。失敗した単体テストを1つ作成し、できるだけ単純に合格させます。クラスに対して失敗する多数の単体テストを記述し、それらすべてを一度に合格させることに対するこのアプローチの利点は何ですか。 テストスイートは、リファクタリング段階で誤ったコードを記述したり、ミスを犯したりすることからあなたを保護します。クラス(またはモジュール)のすべてのテストを「ブレインダンプ」の形式として最初に記述して、予想されるすべての動作を一度に書き留めることが簡単な場合があります。

5
テスト可能なコードを促進する設計原則とは何ですか?(テスト可能なコードの設計とテストによる設計の推進)
私が取り組んでいるプロジェクトのほとんどは、開発と単体テストを分離して考えているため、後のインスタンスで単体テストを書くのは悪夢です。私の目的は、高レベルおよび低レベルの設計フェーズ自体の間にテストを念頭に置くことです。 テスト可能なコードを促進する明確に定義された設計原則があるかどうかを知りたい。私が最近理解するようになったそのような原則の1つは、依存性注入と制御の反転による依存性反転です。 SOLIDとして知られているものがあることを読みました。SOLIDの原則に従うと間接的に簡単にテストできるコードになるかどうかを理解したいですか?そうでない場合、テスト可能なコードを促進する明確に定義された設計原則はありますか? テスト駆動開発と呼ばれるものがあることを認識しています。ただし、テストを通じて設計を推進するよりも、設計段階でテストを念頭に置いてコードを設計することにもっと興味があります。これが理にかなっていることを願っています。 このトピックに関連するもう1つの質問は、既存の製品/プロジェクトをリファクタリングし、各モジュールのユニットテストケースを作成できるようにするためにコードとデザインを変更してもよいかどうかです。

4
TDD-アウトサイドインとインサイドアウト
アプリケーションをOutside Inで構築することとTDDを使用してInside Outで構築することの違いは何ですか? これらはTDDとユニットテストについて読んだ本です: テスト駆動開発:例による テスト駆動開発:実用ガイド:実用ガイドMicrosoftでの 高品質PHPフレームワークとアプリケーションの開発のための実世界ソリューション NET xUnitテストパターン:テストコード のリファクタリングユニットテストの技術:.Net Growing Object-Oriented Softwareでの例、テストによるガイド ---> JAVAは私の主要言語ではないため、これを理解するのは非常に困難でした:) それらのほぼすべてがTDDの基本と単体テストを一般的に説明しましたが、アプリケーションを構築するさまざまな方法についてはほとんど言及しませんでした。 もう1つ気づいたのは、これらの書籍のほとんど(すべてではないにしても)が、アプリケーションの作成時に設計段階を無視していることです。彼らは、テストケースを迅速に記述し、設計を単独で出現させることに重点を置いています。 しかし、私は人々がTDDにアプローチする方法を議論したxUnitテストパターンのパラグラフに出会いました。Outside InとInside Outの 2つの学校があります。 悲しいことに、この本はこの点について詳しく説明していません。これら2つのケースの主な違いは何かを知りたいです。 それらのそれぞれをいつ使用する必要がありますか? 握りやすいTDD初心者には? 各方法の欠点は何ですか? このトピックを具体的に説明している資料はありますか?

10
テストのテスト方法は?
コードをテストして、コードをより正確にします(実際、不正確になる可能性は低くなります)。ただし、テストはコードでもあり、エラーが含まれることもあります。また、テストにバグがある場合は、コードが改善されることはほとんどありません。 テストで考えられる3種類のエラーを考えることができます。 プログラマーが目前のタスクを誤解し、テストが実行すべきだと思ったとおりにテストを実行する場合の論理エラー。これは誤りです。 基礎となるテストフレームワークのエラー(例えば、漏れやすいモックの抽象化)。 テストのバグ:テストは、プログラマーが考えていることとは少し異なっています。 タイプ(1)のエラーを防ぐことは不可能と思われます(プログラマーが...賢くならない限り)。ただし、(2)および(3)は扱いやすい場合があります。これらのタイプのエラーにどのように対処しますか?それらを避けるための特別な戦略はありますか?たとえば、テスト作成者の前提条件のみをチェックする特別な「空の」テストを作成しますか?また、壊れたテストケースのデバッグにどのように取り組みますか?

14
TDDは複雑なプロジェクトで本当に機能しますか?
私はTDDプロジェクトで経験した問題に関してこの質問をしています。単体テストを作成するときに、次の課題に気付きました。 モックデータの生成と維持 大きなモックデータを維持するのは難しく、非現実的です。データベース構造が変更されると、さらに難しくなります。 GUIのテスト MVVMとGUIのテスト機能を備えていても、GUIシナリオを再現するには多くのコードが必要です。 ビジネスをテストする TDDを単純なビジネスロジックに限定するとうまくいくという経験があります。ただし、テストの組み合わせ(テスト領域)の数が非常に多いため、複雑なビジネスロジックのテストは困難です。 要件の矛盾 実際には、分析および設計中のすべての要件を把握するのは困難です。プロジェクトが複雑であるため、多くの場合、1つのノートの要件が矛盾につながります。矛盾は、実装フェーズの後半で見つかります。TDDでは、要件が100%正しいことが要求されます。このような場合、テストの作成中に競合する要件がキャプチャされることが予想されます。しかし、問題は複雑なシナリオではそうではないということです。 私はこの質問を読みました:なぜTDDは機能するのですか? TDDは本当に複雑なエンタープライズプロジェクトで機能しますか、それともプロジェクトタイプに実質的に制限がありますか?
53 tdd 

11
テストを開始するためにデザインが必要な場合、TDDがどのように優れたデザインを取得するのに役立つかがわかりません。
TDD、特に開発の部分に頭を包み込もうとしています。私はいくつかの本を見てきましたが、私が見つけた本は主にテストの部分に取り組んでいます-NUnitの歴史、テストが良い理由、レッド/グリーン/リファクタリング、文字列計算機の作成方法。 良いものですが、それはTDDではなく「単なる」単体テストです。具体的には、テストを開始するためにデザインが必要な場合、TDDが優れたデザインを取得するのにどのように役立つか理解できません。 例として、次の3つの要件を想像してください。 カタログには製品のリストが必要です カタログは、ユーザーが閲覧した製品を記憶する必要があります ユーザーは製品を検索できる必要があります この時点で、多くの本は魔法のうさぎを帽子から引き出して「ProductServiceのテスト」に飛び込みますが、そもそもProductServiceがあるという結論に至った経緯については説明していません。それが私が理解しようとしているTDDの「開発」の部分です。 既存の設計が必要ですが、エンティティサービス以外のもの(つまり、Productがあるため、ProductServiceが必要です)はどこにも見つかりません(たとえば、2番目の要件では、ユーザーですが、思い出させる機能をどこに配置しますか?また、検索はProductServiceの機能または別のSearchServiceの機能ですか?どちらを選択すべきかをどのように知ることができますか?) SOLIDによると、UserServiceが必要になりますが、TDDなしでシステムを設計すると、単一メソッドサービスが大量に発生する可能性があります。TDDは、最初に自分のデザインを発見することを意図したものではありませんか? 私は.net開発者ですが、Javaリソースも機能します。実際のビジネスアプリケーションを扱う実際のサンプルアプリケーションや本はないようです。TDDを使用して設計を作成するプロセスを示す明確な例を提供できますか?
50 java  c#  .net  tdd 

11
自動テストの欠点は何ですか?
このサイトには、自動テストから得られる利点に関する多くの情報を提供する多くの質問があります。しかし、私はコインの反対側を表すものを見ませんでした:欠点は何ですか?人生のすべてはトレードオフであり、特効薬はありませんので、自動テストを行わない正当な理由が必ずあるはずです。彼らは何ですか? ここに私が思いついたいくつかがあります: 特定の機能に対して初期開発者の時間がさらに必要です チームメンバーの高いスキルレベルが必要 ツールのニーズを増やす(テストランナー、フレームワークなど) 失敗したテストが発生した場合に必要な複雑な分析-このテストは私の変更により廃止されたのですか、それとも間違いを犯したと言っているのですか? 編集 私は自動化されたテストの巨大な支持者であると言っておくべきであり、私はそれをすることを納得させるつもりはありません。欠点が何なのかを理解したいと思っているので、会社に行って主張するとき、次の想像上の銀の弾丸を投げているようには見えません。 また、上記の私の例に異議を唱える人を探していないことを明確にしています。私は、いくつかの不利な点(すべてにトレードオフがある)がなければならないことを真実と考えており、それらが何であるかを理解したいと思います。

9
単体テストまたはテスト駆動開発は価値がありますか?
仕事中の私のチームはスクラムに移行しており、他のチームは単体テストとユーザー受け入れテストを使用してテスト駆動開発を始めています。私はUATが好きですが、テスト駆動開発または一般にテスト駆動開発の単体テストで販売されていません。 テストを書くことは余分な作業であり、実際のコードを書くときに人々に松葉杖を与えるようで、あまり効果的ではないかもしれません。 ユニットテストがどのように機能し、どのように記述するかを理解していますが、それは本当に良いアイデアであり、努力と時間の価値があると主張することができますか? また、スクラムにとってTDDが特に優れているものはありますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.