TDDを行うときにロギングが必要ですか?


40

赤、緑、リファクタリングのサイクルを実行するときは、常にテストに合格するための最小限のコードを記述する必要があります。これは私がTDDについて教えられてきた方法であり、ほとんどすべての本がプロセスを説明する方法です。

しかし、ロギングはどうですか?

正直なところ、実際に複雑なことが起こっていない限り、アプリケーションでのログ記録はほとんど使用していませんが、適切なログ記録の重要性に関する多くの投稿を見てきました。
そのため、例外をログに記録する以外に、適切にテストされたアプリケーション(ユニット/統合/受け入れテスト)にログを記録することの本当の重要性を正当化できませんでした。

だから私の質問は:

  1. TDDを実行している場合、ログを記録する必要がありますか?テストに失敗しても、アプリケーションのどこが悪いのかわかりませんか?
  2. 各クラスの各メソッドにロギングプロセスのテストを追加する必要がありますか?
  3. たとえば、実稼働環境でいくつかのログレベルが無効になっている場合、テストと環境の間に依存関係が生じませんか?
  4. 人々はログがデバッグを容易にする方法について話しますが、TDDの主な利点の1つは、テストの失敗によって何が間違っているかを常に知っていることです。

私がそこに欠けているものはありますか?


5
ロギングは非常に多くのルールの特殊なケースだと思います。クラス/関数は、ロギングを除いて、1つのことと1つのことだけを行う必要があります。ロギングを除いて、関数は純粋であることが望まれます。などなど。ロギングはルールに違反します。
Phoshi

1
ロギングは、使用されているソフトウェア開発手法とほとんど直交していませんか?したがって、おそらくそれを絞り込んで、質問する必要があります。
ハイド14

回答:


50

1)TDDを行う場合、ログを記録する必要がありますか?テストに失敗しても、アプリケーションのどこが悪いのかわかりませんか?

これは、アプリケーションに必要なすべての可能なテストがあることを前提としていますが、これはほとんど真実ではありません。ログは、まだテストを作成していないバグを追跡するのに役立ちます。

2)各クラスの各メソッドにロギングプロセスのテストを追加する必要がありますか?

ロガー自体をテストする場合、他の依存関係と同様に、各クラスでロガーを再テストする必要はありません。

3)たとえば、実稼働環境で一部のログレベルが無効になっている場合、テストと環境の間に依存関係が生じませんか?

人間(およびログアグリゲーター)はログに依存しています。テストはログに依存すべきではありません。通常、いくつかのログレベルがあり、いくつかは実稼働で使用され、いくつかの追加レベルは開発で使用されます。

「Railsログレベルは、プロダクションモードでは情報であり、開発およびテストではデバッグです」-http://guides.rubyonrails.org/debugging_rails_applications.html

他のアプリケーションも同様のアプローチを使用します。

4)人々はログがどのようにデバッグを容易にするかについて話しますが、TDDの主な利点の1つは、テストの失敗により何が間違っているかを常に知っていることです。

実稼働のバグはすべてのテストに合格するため、これらの問題を調査するには他の参照が必要になる場合があります。


26
完璧に厳密に実行されたTDDでさえ、パフォーマンス、システムの相互作用、サードパーティの相互作用に関する生産上の問題を防ぐことはできません。並行性の問題もテストで完全にカバーすることは非常に困難です。100%のテストカバレッジ「のみ」とは、コードの100%が実行されたことを意味し、すべての状態または環境で正しいわけではありません。
ホルスタブロ14

34

ロギングは、アプリケーションの非例外的な動作を説明するのに役立ちます。

イベントログは、システムのアクティビティを理解し、問題を診断するために使用できる監査証跡を提供するために、システムの実行中に発生するイベントを記録します。特に、ユーザーとの対話が少ないアプリケーション(サーバーアプリケーションなど)の場合、複雑なシステムのアクティビティを理解するために不可欠です。

アプリケーションがどのようにテストされても、例外がどれだけうまくログに記録されても、そのユーザーは、

プログラムの出力は0ですが、1になると予想していましたが、なぜですか?

アプリケーションの構成、パラメーター、その他のランタイムの詳細を検証して、その(例外的ではない)動作を説明するためにログを記録する必要があります。

上記の観点から、ロギングは開発よりもサポートを重視しています。アプリケーションが公開された後、プログラマーがさらなる開発に集中できるように、ユーザーからの質問を他の誰かが処理できるようにすることが望ましいです。

アプリケーションの動作をログに記録することで、他の誰かがコードを掘り下げたり、何が起こっているのかを説明する要求によって開発者の注意をそらすことなく、プログラムの動作を理解できます。


5
「ロギングはサポートを重視している」ための+1。本当に頭に釘を打ちます。
ティボス14

1
「例外的ではない動作」および「ログはサポートを重視する」ために+1。しかし、引用文のソースをリストするために回答を編集してください。
logc 14

引用の@logcソースは、ここの最初の単語「Logging」のリンクで参照されます。クリックすると、Wikipediaの記事にアクセスできます:en.wikipedia.org/wiki/Logfile
gnat

16

ここでのほとんどの答えは、正確さの側面に焦点を当てています。ただし、ロギングには別の目的もあります。ロギングは、パフォーマンス関連のデータを収集する方法です。そのため、システムがエラーなしで機能している場合でも、ログが遅い理由を知ることができます。すべての側面を完全にテストでカバーしても、テストスイートではわかりません。

もちろん、パフォーマンスが重要なシステムは、一部の運用ダッシュボードに主要なパフォーマンスメトリックを提供できますが、「クラシック」ロギングは異なるレベルの詳細を提供できます。


2
また、監査証跡を目的としたロギングについても忘れないでください。または請求。または、さまざまな種類の統計。または、他のシステムの他の種類の統計と照合するためのイベントロギング。
PlasmaHH

ロギングなしでプロファイリングを行うことはありませんか?または、プロファイリングの結果を継続的に記録できるということですか?
ベルギ14

@Bergi:アプリケーションの動作に完全に依存します。Webアプリケーションなどの場合、各リクエストのサービス時間をログに記録し、後で「パフォーマンスの悪いユーザー」のイベントをクラスター化することもできます。
PlasmaHH 14

@Bergiプロファイリングは、開発に起こりますが、遅くなることができ、CPUがよりロードすることができ、サービスがない応答時間で、並列スレッドがロックの問題に遭遇することもありますディスクを使用して、心に留めておか電子へのライブ系への影響は、あります...
ヨハネス14

@PlasmaHH監査はコア要件の一部であり、テストでカバーする必要があります。ほとんどの場合、「通常の」ロギングルートでは実行しません。通常のロギングは失敗する場合がありますが、監査は失敗します。「さまざまな統計」私はパフォーマンスの下で収集しました;)
ヨハネス14

8

主な質問に対する簡単な答えは、一般的なルールとして、コードのバグはTDDによって公開されないということです。いくつかのかもしれませんが、理想的に多く、しかし失敗テストの不在は、バグがないことを意味するものではありません。これは、ソフトウェアテストにおいて非常に重要な格言です。

システムの動作が間違っているかどうかはわからないので、たまにまれな状況では、ロギングは必然的に問題が発生したときに何が問題なのかを理解するのに役立つ便利なツールです。

ロギングとTDDは異なる懸念に対処します。


7
  1. 通常はそうではない100%のテストカバーがない限り、ソフトウェアがクラッシュしないことを知ることはできません(編集:およびコメントで述べたように、たとえそれがあったとしても、ソフトウェアに依存しない何かが原因でクラッシュ); まったくバグのないソフトウェアを実行できると考えるのと同じです(NASAでさえも実行できません)。そのため、少なくとも、プログラムがクラッシュした場合に発生する可能性のある障害をログに記録して、理由を知る必要があります。

  2. ロギングは、使用しているテクノロジーに応じて、外部ライブラリまたはインターンフレームワークで実行する必要があります。それが意味するのは、それは既に以前にテストされたものであるべきであり、あなた自身をテストする必要がないということです。すべてのメソッドが想定されていることを記録することをテストするのはやり過ぎです。

  3. ログはテスト用ではなく、依存関係は一切ありません。ただし、環境に対応するファイルにログを保存する必要がありますが、テストのロギングが制約のように感じられる場合は、ログを無効にする必要はありません(テスト、開発、および本番環境用に別のファイルが必要です)少なくとも)。

  4. エラーは非常に不明確である可能性があり、TDDテストの1つが失敗したときに何が問題になったかは必ずしも明らかではありません。ログはより正確である必要があります。たとえば、ソートアルゴリズムを実行しているときにテストケース全体が失敗した場合、問題の実際の場所を特定するのに役立つアルゴリズムのすべてのテストのログが必要です。


3
たとえ100%のカバー率を持っているとしても、起こりうるあらゆることに対してカバーしていますか?データベースへのネットワーク接続がダウンした場合はどうなりますか?あなたのテストはそれを教えてくれますか?
ザカリーK 14

カバレッジが100%であっても、ソフトウェアがクラッシュすることは決してありません。100%のカバレッジは望ましいものの、見た目よりも正確さについての情報がはるかに少ない。
アンドレスF. 14

はい、あなたもそれについて正しいです。ポイントは、クラッシュの可能性がないことは実行不可能です。編集します。
ピエールアラード14

1
編集はまだ正しくありません。テストカバレッジが100%であっても、コードにバグがある場合があります(外部の原因を責める必要はありません)。テストはコードの動作を意味するものではありません。彼らが確実に暗示している唯一のことは、バグを見つけるテストを書くことに失敗したことです:)
アンドレスF. 14

3
「合格するテストカバレッジは100%!=バグなし」であることを証明するのは簡単です。反例:(add(x, y) = 2常に2を返します)。次のテストに合格し、完全なカバレッジを提供しますassert(2 == add(1,1))。バギー関数の100%テストカバレッジ:)
Andres F. 14

5

はい、一般的な場合、ログが必要です。

ロギングはデバッグに関するものではありません。ロギングの一部はデバッグに関することもあるので、開発中に必要ない場合はスキップできます。

ただし、ロギングのより重要な部分は保守性です。適切に設計されたロギングは、次の質問に答えることができます。

  • アプリケーションはまだ生きており、起動していますか?(1000秒ごとにハートビートを記録します。)
  • 過去10か月でアプリケーションのパフォーマンスは変化しましたか?(ユースケースのパフォーマンスの統計を記録することにより。)
  • 過去10か月でアプリケーションの負荷は変化しましたか?(要求タイプごとの要求数を記録することにより。)
  • インターフェースのいずれかがパフォーマンス特性を変更しましたか?
  • 新しいリリースは、一部のサブシステムに対して異なる使用特性を引き起こしますか?
  • DoS攻撃を受けていますか?
  • どのようなエラーが発生していますか?

これはすべてロギングによって実現できます。そして、はい、それは計画され、設計され、テストされるべきです。

ロギングは、他の機能と同様に、治療に値する機能です。


4

TL; DR:ロギングとTDDは直交しています。片方を持っていることは、もう片方を必要とすることには関係ありません。

TDDを実行している場合、ログを記録する必要がありますか?テストに失敗しても、アプリケーションのどこが悪いのかわかりませんか?

概して、私が実装し、実装したほとんどのロギングは、開発のデバッグ用ではなく、運用上のトラブルシューティング用でした(それは役立つかもしれませんが)。このログの主な対象者は、サーバーを実行する管理者と運用担当者、分析のためにログを送られてくる人をサポートする人、ログを見て何が起こっているのかを試してみたい顧客です。

これらのログは、主に統合ポイントで発生する問題のトラブルシューティングに役立ちます。これにより、ネットワークサービス(データベース、SOAPなど)、ローカルリソース(ディスク、メモリなど)、不良データ(顧客入力、不良/破損データソースなど)などが発生する可能性があります。 (設定、構成など)はすべてトラブルシューティングに役立ちます。

各クラスの各メソッドにロギングプロセスのテストを追加する必要がありますか?

ロギングをテストするために必要な場所にテストを追加します。情報をログアウトするためのアドホックコールがある場合は、テストする必要があります。アスペクト指向プログラミングまたはメタプログラミングを使用してロギングとログテストを実装する場合、テストの負担を軽減できます。

たとえば、実稼働環境でいくつかのログレベルが無効になっている場合、テストと環境の間に依存関係が生じませんか?

IoCを使用してコードを記述していて、モックを使用している場合、特定の環境設定に依存することなく、すべてのロギングを効果的にテストできるはずです。


3

TDDは通常、コーディングのバグを減らすのに役立ちます。仕様のバグや、物事の仕組みについての誤解ではあまり役立ちません。

「ああ?ログオンが成功したことを確認する前にデータメッセージを取得できますか?それを知らなかったので、うまく処理できません!」...そのようなこと。ロギングは、ソフトウェアが何をしようとしたかを伝えるのに非常に役立ち、間違ったことを見つけることができます。


2

私の経験では、TDDを実行しないと、アプリケーションに大きなレベルのログが追加されます。その後、不確実性のレベルが高くなるため、ロギングを追加して何が起こっているのかを確認します。

一方、TDDを実行する場合(またはテストを行う場合はいつでも)、ログステートメントの追加はずっと少なくなります。これは、LOCが少ないことを意味し、(常にではないが)パフォーマンスに影響を与える可能性があります。

ただし、開発方法に関係なく、ほとんどの場合、私の会社では、関数の入力終了ログを半自動で追加します。私が知っているように、これは生産問題の分析に必須であると考えられていました。

たとえば、パブリックインターフェイスに存在するEJBサービスBeanのメソッドがあります。もう1つは、関数が複雑な計算を行う場合です。メソッドに数値を入力しておくと非常に役立ちます(たとえば、ユニットテストを書いて、手近にある一般的なトピックに戻ることができます)。


機能に出入りログを追加する理由を説明してください。なぜこれがあなたの会社で必要なのですか?
gnat 14

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