コードの正確さを証明できる場合、テストを作成する必要がありますか?


8

「TDDについて話すことはほとんど効果がありません。誰かにTDDを説得したい場合は、結果を示してください」と人々は言います。ただし、TDDがなくても、すでにすばらしい結果が得られています。TDDを使用する人が良い結果を得ることが納得できないことを私に示すと、TDDとTDD以外の両方を書く人がTDDでより良い結果を得ることができるようにしたいと思います。

これらすべてにもかかわらず、私はTDDを試してみたいと思っています。しかし、私はこれから何かを得るとは確信していません。それが有用であることが判明した場合、私はそれを私のチームの他のメンバーにプッシュしようとします。

私の主な質問は次のとおりです。コードの正確さを既に証明できる場合、TDDはコードに何らかの目的を果たしますか?

明らかに、どちらも特効薬ではありません。詳細を逃したために証拠が間違っている可能性があり、テストでは、テストに失敗したバグを特定できない可能性があります。結局、私たちは人間であり、誰もが100%バグのないコードを永遠に作ることはできません。私たちはできるだけ近づくように努力することができます。

しかし、TDDは、その正確性が証明されたコードの時間を実際に節約するでしょうか?つまり、コードが動作するステートマシンで、有効なすべての状態とその範囲が開発者によって認識され、すべてが考慮され、コードがすべての例外を渡すホワイトリストスタイルのエラーチェックで設計されているコード予期しないリークがないことを確認するための上位ハンドラー->(理由内の)関連メッセージをクライアントに表示することも、ログ通知を管理者に送信することもありません。

実際の例での回答の方が良いでしょう。


いくつかの説明:

  • この質問は、コードの正当性を証明できるかどうかについてではありません。デフォルトでは、すべてのコードが妥当な時間枠内で正しいことが証明できるとは限らないが、一部のコードはそうであると想定します。たとえば、FizzBu​​zzモジュールの正当性を証明するのは非常に簡単です。クラウドベースのデータ同期サービスではそれほど簡単ではありません。

  • この制限内では、質問は次のように尋ねます。コードベースが2つの部分に分割されているという仮定から始めます。[I]正しいことが証明されている部分[II]正しく証明されていないが、手動で動作するようにテストされている部分。

  • 今までTDDプラクティスがなかったこのコードベースにTDDプラクティスを適用したいと思います。質問は次のように質問します。TDDはすべての単一のモジュールに適用する必要がありますか、それとも、正しくないことが証明されたモジュールにのみ適用すれば十分でしょうか。

  • 「実証済み」とは、このモジュールを完全に機能的なスタイルと見なすことができることを意味します。つまり、このモジュールは外部のグローバルまたは外部状態に依存せず、やり取りする他のモジュールが従う必要のあるI / O用の独自のAPIを完全に備えています。 。モジュールの外のコードを変更して「このモジュールを壊す」ことはできません。最悪の場合、コードを誤用して、フォーマットされたエラーメッセージを返す可能性があります。

  • 明らかに、すべてのルールには例外があり、新しいコンパイラバージョンのコンパイラバグはこのモジュールにバグをもたらす可能性がありますが、同じバグがそれをテストしたテストに導入され、意図したとおりに機能しなくなったテストから誤った安全性をもたらす可能性があります。つまり、テストは魔法のようなソリューションではなく、保護の別のレイヤーであり、この質問は、この保護のレイヤーが、正しいことが証明されたモジュールの特定のケースで努力する価値があるかどうかの問題について説明します(それは確かに)でした。


10
「コードの正しさ」を証明することは、あなたが思っているより難しくなるかもしれません。
πάνταῥεῖ

34
私はあなたの職場とあなたの職歴について学ぶことを楽しんでいましたが、結果を最大化する方法として、そして読者ができるように読者の注意を維持するために、時には本当に本当に重要なのはそれがあなたの知識とコミュニティの知識を強化するために、あなたを助けて、あなたは... 要点に到達する必要があります。質問を最も顕著な点に短縮することを検討してください。
MetaFight

10
あなたが説明するのは、コードの「正確さを証明する」プロセスではありません。そのようなプロセスは大きく異なります。また、見ただけで「正しい」と証明できる方法でコードを作成できることを受け入れるのは難しいと思います。些細で「正しい」と思われる多くのコードを確認しましたが、堅牢な自動テストを行うと完全につぶされました。
陶酔の

8
「上のコードのバグに注意してください。私はそれが正しいことを証明しただけで、試したわけではありません。」-ドナルド・クヌース。
ニール、

6
あなたの質問は意味がありません。TDDは、テストが開発を推進することを意味します。つまり、テストがない限り、デザインもアーキテクチャもコードもありません。だから、世界であなたはどのようにしている非常にでたときに、「コードにTDDを適用する正しい証明されていること」の定義 TDDの、正しい証明するコードはありませんか
イェルクWミッターク

回答:


20

はい。

プルーフは利用可能であれば問題ありませんが、最良の場合でも、コードの1ビットが期待どおりに機能することを証明するだけです(すべての入力に対して?処理の途中での中断を考慮して?)メモリ不足について?ディスク障害?ネットワーク障害?)。

変更するとどうなりますか?

テストはコードが何をすべきかについての暗黙の契約として役立つので素晴らしいです。彼らは足場を提供するので、あなたの新しいインターンは、ある程度の自信を持って入り、変更を加えることができます。すべて迅速かつ明確な結果を介して:合格または不合格。

そして率直に言って、私はインターンを指導して、数か月で実行可能な単体テストを書くことができます。私のチーム(私も含む)の誰もが、重要なコードにとって意味のある何かを保証する証明を作成できるとは思えません。言うまでもなく、迅速かつ正確にそれを行います。


証明するのが簡単ではない同じコードは、テストするのも簡単ではありません。ネットワーク障害またはディスク障害はさまざまな形をとることがありますが、可能なすべてのシナリオがテストでカバーされていることをどのように確信できますか?彼らはおそらくあなたが考えることができるすべての単一のシナリオをカバーしますが、必ずしも実際のすべての単一のシナリオをカバーするわけではありません。テストを実施しているからといって、すべての変更が非破壊的であると盲目的に仮定することはできません。これは単なる保護レイヤーです。テストは重要ですが、特効薬ではありません。
キリー

6
@Kylee-違反はありませんが、正確性の証明に必要な労力とスキルを大幅に過小評価しているようです(またはいくつかの自動化テストをまとめるのに必要な労力とスキルを大幅に過大評価しています)。
Telastyn

たぶんあなたは正しい、そして私はおそらくそれを経験していないためにテストをまとめる努力を過大評価します(正直なところ、私が心配しているのは「テストをまとめる」ことではなく、実際にテストを実行することです。大規模で急速に変化するプロジェクトの場合、それ自体は無視できるほどの時間の遅れではありません)。どちらにしても、これは質問とは関係ありません。質問は明確に述べています、あなたがすでに正しいことが証明されたコードを持っていると仮定して、それのための単体テストを書く必要はまだありますか?
Kylee

1
For large & rapidly changing projects変更するコードの方がテストが必要です。変更するコードは、ほとんど変更しないコードよりも、新しいバグや予期しない動作が原因で失敗する可能性がはるかに高いためです。それは確率の問題です。それが頻繁に変更されなくても、しばらくすると、開発中に得られた知識が失われたり、忘却に陥ったりする可能性があります。また、テストは具体化された知識であり、学習曲線を大幅に削減できます。コーディングテストには時間がかかりますか?はい。プロジェクトはより高価になりますか?いいえ、長期​​的には安くなります。
Laiv

3
@Kyleeコードの一部が正しいことを証明できたとしても、せいぜい、誰もそのコードを変更したり機能を追加したりすることが許可されていない状況になります。そうすることはあなたの証明を無効にするでしょう。この回答ですでに強調されているように、テストを使用すると、自信を持ってコードを変更できます。それを変える人が未経験のインターンでも。ちなみに、コードのブロックが100%正しいとしても、コードを変更する必要がないという意味ではありません(たとえば、顧客が必要とする新しい機能を追加したり、証明で考慮されていない実際の制約を満たすため)。
Brandin

5

わかりません。ご質問にはお答えできません。

あなたが多くの時間を費やして、あなたが今しているプロセスが誰もが満足するように機能しているように思われる一方で、実際に何が起こっているかをほんの少しだけ伝えています。

私の経験から、あなたが説明しているのは非常に珍しいことであり、実際にアプリケーションのバグ数が少ない原因は、実際のプロセスとコーディングへのアプローチであることに懐疑的です。あなたのアプリケーションに影響を与える他の多くの要因があるかもしれません、そしてあなたはそれらの要因について私たちに何も言っていません。

したがって、TDDが役立つかどうかは、正確な開発環境と文化を知らないということを前にしてわかりません。そして、それについて何日も議論し、議論することができます。

お勧めできるアドバイスは1つだけです。それをお試しください。実験。勉強しなさい。私はあなたが決定するために最小限の努力を費やそうとしていることを知っていますが、それは不可能です。TDDがコンテキストで機能するかどうかを本当に知りたい場合、実際にTDDを実行することが唯一の方法です。実際にそれを学び、アプリケーションに適用する場合、それを非TDDプロセスと比較できます。TDDには実際に利点があり、それを維持することにした可能性があります。または、TDDは何も新しいものをもたらさず、あなたを遅くするだけであることが判明する可能性があります。その場合、以前のプロセスにフォールバックできます。


5

(ユニット)テストの主な目的はコードを保護することであり、後の変更のために気付かれずにコードが壊れないようにします。コードが最初に書かれたとき、それは多くの注目を集め、精査されます。そして、あなたはそのためのいくつかの優れたシステムを持っているかもしれません。

6か月後、他の誰かが一見無関係なものに取り組んでいるとき、それは壊れる可能性があり、スーパーデューパーコードの正確性プロバイダーはそれに気付かないでしょう。自動テストします。


1
これは見過ごされがちなことです。はい、コードに単体テストが含まれていることを確認するのに苦労します。しかし、ジュニア開発者が単純な変更を行い、ユニットテストがすぐに他の何かが壊れていることを示すフラグを立てると、これは何回も元が取れます。私は何十年も前にジュニア開発者であり、何かを壊し、リリース全体が遅れています。当時の同僚は非常に寛容で、マネージャーが上下に動き始めたときの背中を抱えていましたが、ユニットテストが実施されていれば、全体のシナリオは後から回避できました。
ロビーディー

5

今までTDDプラクティスがなかったこのコードベースにTDDプラクティスを適用したいと思います。

これがTDDを学ぶ最も難しい方法です。テストが遅れるほど、テストの作成にかかるコストが高くなり、テストを書く手間が減ります。

テストを既存のコードベースに組み込むことが不可能だと言っているのではありません。そうすることで、誰もがTDD信者になる可能性は低いと言っています。これは大変な作業です。

新しいものや家庭で初めてTDDを練習するのが実際には最善です。そのようにして、あなたは本当のリズムを学びます。これを正しく行うと、中毒性があります。

質問は次のことを尋ねます:TDDがすべての単一のモジュールに適用されるべきか、

それが構造的思考です。すべての関数、クラス、モジュールをテストするようなことを言うべきではありません。これらの境界はテストにとって重要ではなく、とにかく変更できるはずです。TDDは、テスト可能な行動ニーズを確立することであり、それがどのように満たされるかを気にすることではありません。そうでなければ、リファクタリングできませんでした。

それとも、正しく証明されなかったモジュールのみに適用するだけで十分でしょうか?

必要に応じて適用すれば十分です。新しいコードから始めます。あなたはテストを遅くするよりも早くテストすることでより多くを取り戻すでしょう。あなたが家でそれを習得するのに十分な練習をするまで、仕事でこれをしないでください。

新しいコードが機能していてTDDが効果的であり、古いコードを引き継ぐのに十分な自信があることを示したら、実証済みのコードから始めます。その理由は、作成しているテストがコードを適切な方向に進めているかどうかをすぐに確認できるからです。

私の主な質問は次のとおりです。コードの正確さを既に証明できる場合、TDDはコードに何らかの目的を果たしますか?

テストは正しさを証明するだけではありません。彼らは意図を示しています。彼らは必要なものを示しています。彼らは変化への道を指摘しています。優れたテストでは、このコードを記述して必要なものを取得する方法はいくつかあるとしています。新しいコーダーがすべてを壊すことなく何ができるかを確認するのに役立ちます。

一度それがダウンしたら、証明されていないコードにさまようべきです。

熱心な人々への警告:あなたは成功を収めたように聞こえるので、頭から飛びつくことはまずありません。しかし、彼ら自身を証明しようとしている他の人はそれほど控えめではありません。TDDはやり過ぎることがあります。トライバルで意味のないものをロックダウンするため、実際にリファクタリングを損なう一連のテストを作成するのは驚くほど簡単です。これはどのように起こりますか?テストを自慢して見たい人はテストを書くだけでリファクタリングをしないからです。解決?それらをリファクタリングします。機能の変更に対応してもらいます。早いほど良い。これは、役に立たないテストをすばやく表示します。屈曲することで柔軟性を証明します。

構造的分類に対する警告:クラスはユニットであると主張する人もいます。2つのクラスを含むテストを統合テストと呼ぶ人もいます。境界xを越えてユニットテストと呼ぶことはできないと主張する人もいます。テストの動作に注意することをお勧めします。ほんの一瞬で実行できますか?他のテストと並行して実行できますか(副作用なし)?依存関係と前提条件を満たすために、他のものを起動したり編集したりせずに実行できますか?DB、ファイルシステム、またはネットワークと通信する場合は、これらの考慮事項を優先します。どうして?これらの最後の3つは、他の問題の原因となるため、単なる問題です。テストの動作をどのように期待できるかに基づいて、テストをグループ化します。彼らがたまたま越えた境界ではありません。次に、各テストスイートに何を期待できるかを理解します。

オーバーヘッドが多すぎるためTDDを使いたくないと人々が言っ​​ているのを見てきました。TDDの支持者は、TDDの記述に慣れれば、オーバーヘッドはほとんどないと言って防御しています。

その質問にはすでに回答があります


1

テスト駆動開発は、テストよりも、APIのプロトタイピングとブレーンストーミングについてです。多くの場合、作成されたテストは質が低く、最終的には破棄する必要があります。TDDの主な利点は、API実装を記述する前に、APIの使用方法を決定することです。この利点は、他の方法でも得られます。たとえば、実装前にAPIドキュメントを作成することで得られます。

正当性の証明は、常にテストよりも価値があります。テストは何も証明しません。ただし、正確性の証明を生産的に使用するには、自動化された証明チェッカーが役立ち、何らかの契約(契約による設計または契約ベースの設計)を使用して作業する必要があります。

以前は、コードの重要なセクションで作業するとき、手動で正当性を証明しようとしました。非公式の証明であっても、自動テストよりも価値があります。しかし、人々が将来あなたのコードを壊すので、証明を自動化できない限り、あなたはまだテストが必要です。

自動テストはTDDを意味しません。


契約によるAPIと設計のブレーンストーミングはすでに問題への取り組み方なので、私はあなたの答えが好きだと言いたいのですが、他の情報源は「テスト駆動開発では、各新機能はテストを書くことから始まります」と言っています。あなたは私が同意することを述べましたが、TDDアプローチを使用するように私を説得しませんでした。「自動テストはTDDを意味するものではありません」わかりましたが、単純な一般的なベストプラクティスに従うのではなく、TDDは何を意味するのでしょうか。
キリー

1
TDDはしばしばAPI、IMOのブレーンストーミングを伴うことに同意しますが、これは時には悪いことです。APIは、テスト可能性のために(必ずしも)設計する必要はありません。クライアントがスムーズに使用できるように設計し、関連するクラス/コードを理解できるようにする必要があります。テストライターが「String getSomeValue()ここに追加して、テストできるようにする」と言っているのは、デザイン全体にとって意味のないことです。もちろん、後でその機能を削除することもできますが、私の経験では、それはまれです。
user949300

1
@ user949300、テスト可能なAPIの設計とクライアントがスムーズに使用できるように設計されたAPIの間には大きな重複があります。テストのために不要なコードを追加すると、設計が悪いことがわかります。多くの場合、API作成者はAPIの問題をデバッグすることを忘れます。テスト可能でユーザーにとって有用な何かを記述すると、実装についての詳細をインターフェースに漏らすことなく、それらについて考える必要があります。
Berin Loritsch

@ user949300 TDDに関する最大の不満はおそらく、通常はカプセル化されているものが公開されるように、APIが「テスト容易性」のために変更される方法です。2番目の不満はおそらく、時間の経過とともにうまく拡張できないことです。
フランクヒルマン

@Kylee自動テストは、流行語「TDD」より古いものです。違いは、自動化されたテストは、テストする必要があると単純に考えられるということです。ドグマも、テストを記述する特定の順序もありません。また、単体テストと統合テストに重点が置かれていません。
Frank Hileman、2018

0

A)コードを読んで、それが正しいことを納得させると、それが正しいことを証明することにはほど遠くはありません。そうでなければ、なぜテストを書くのですか?

B)コードを変更する場合、コードがまだ正しいかどうかを示すテストを実行する必要があります。


これは、数週間前に投稿されたトップアンサーで作成された(そして、よりよく説明された)ポイントを繰り返すだけのようです
gnat

@gnatそれについて書かれた小説を必要としない何かのためのより簡潔な応答です。ここで何か貢献してみてください。
ジョシュ

-1

TDDを効果的に使用することに慣れると、エンドゲームの時間を節約できると言って、警告します。TDDを効果的に使用する方法を学ぶには練習が必要であり、時間の危機に瀕しているときには役に立ちません。それを最大限に活用する方法を学ぶときは、より多くの余裕があり、スケジュールのプレッシャーが少ない個人的なプロジェクトから始めることをお勧めします。

より多くの実験を行い、APIを作成している間は、初期の進行が遅いことがわかります。時間の経過とともに、コードを変更せずに新しいテストに合格し始め、ビルドするベースが非常に安定しているため、進捗が速くなります。後半のゲームでは、TDDを使用してビルドされていないコードでは、何が問題であるかを理解するために必要以上に多くの時間をデバッガーで費やす必要があります。また、以前は新しい変更で機能していた何かを壊すリスクが高まります。 TDDの有効性を、使用しない場合と比較して、完了までの合計時間で評価します。

そうは言っても、町で唯一のゲームはTDDではありません。フルスタックアプリケーションの動作を表現する標準的な方法を使用するBDDを使用し、そこからAPIの正確性を評価できます。

議論全体が「コードの正確さの証明」にかかっているため、コードの正確さを定義するものが必要です。「正しい」の意味を定義するために自動化ツールを使用していない場合、定義は非常に主観的です。正しい定義が仲間のコンセンサスに基づいている場合、それはいつでも変わる可能性があります。正しい定義は具体的かつ検証可能である必要があります。これは、ツールで評価できる必要があることも意味します。なぜ使用しないのですか?

#1の任意の並べ替えの自動テストを使用してからの勝利は、ということであるあなたのコードの遺骨を修正検証できる OSパッチを迅速かつ効率的に適用した場合であっても。スイートを実行してすべてが成功していることを確認してから、パッチを適用してスイートを再度実行します。さらに、自動ビルドインフラストラクチャの一部にします。これで、複数の開発者のコ​​ードをマージした後も、コードが正しいことを確認できます。

TDDを使用した経験から、次のような結論に至りました。

  • 新しいコードには最適ですが、レガシーシステムの変更は困難です
  • あなたはまだ自分が達成しようとしていることを知る必要があります(つまり計画を持っている)
  • 開始が遅いが、後で時間を節約できる
  • ユーザーの観点から正確性とデバッグを検証する方法を考えるように強制します

BDDを使用した経験から、次のような結論に至りました。

  • 従来のコードと新しいコードの両方で機能します
  • スタック全体を検証し、仕様を定義します
  • 立ち上がるのに時間がかかる(ツールセットを知っている人がいるのに役立ちます)
  • 単体テストよりも少ない動作を定義する必要があります

正しい定義:コードは要件に準拠しています。これはBDDで検証するのが最適です。BDDは、人間が読める形式で要件を表現し、実行時にそれらを検証する手段を提供します。

私は数学の証明という点で正しさについて話しているわけではありませんが、それは不可能です。そして、私はその議論をすることにうんざりしています。


TDDを最初に考えるようにさせた問題に対処する素晴らしい投稿:「コードの正確さ」の現在の定義は確かに同業者のコンセンサスです。私の懸念は、将来チームが変わると、この方法が機能しなくなることです。しかし、TDDはこれをどのように解決しますか?古いテストでは、新しいチームメンバーが古い機能を簡単に壊すのを防ぐことができますが、将来の機能の不完全なテストを作成することもあり、それでも問題が発生する可能性があります。結局、どちらの方法もチームを信頼することに依存しています。これまでBDDについて聞いたことがないので、ぜひチェックしてみてください。ありがとう。
キリー

2
「コードが正しいことを確認できる」いいえ。程遠い。せいぜい、実行したテストがまだ合格していると主張できます。
ベント

@ Kylee、BDDはその懸念をよりよく扱います。BDDでは、検証可能な仕様を作成します。仕様は、仕様を検証する実際のテストコードへのフックを作成する手段を使用して、自然言語で記述されています。これにより、2つの懸念が橋渡しされ、実際の要件が伝達されて適用されます。
Berin Loritsch

1
@曲がった、数学的な証明に関して「正確さ」について議論しないでください。それは会話の話題でも、私が伝えようとしていたことでもありません。ただし、経験に基づいて、あなたのようなコメントを投稿する人はそれを念頭に置く傾向があります。コードが要件に準拠していることを完全に確認できます。それが、私が話している正しい定義です。
Berin Loritsch

問題は、コードが定義したテストに合格することが要件である「正しい」の定義に向かっていることです。他の入力のセットは未定義の動作であり、出力は任意です。これは、ほとんどのユーザーが要件であると考えるものと実際には一致しません。
Simon B
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.