web-dev-qa-db-ja.com

単体テストでファイルの内容/エンコーディングをチェックすることは「悪い習慣」と見なされていますか?

少しコンテキスト:今日の初めに、別の同僚が提供したいくつかのSQLコードを更新する必要がありました。これはかなり大きなスクリプトであるため、別個のファイルとして保存されます(実行時に読み取られて実行されます)。これを行っているときに、数か月前の2つのバグを誤って再導入しました。

  • 何らかの理由でASCIIファイルはUTF-16でエンコードされていました(同僚がファイルをメールで送ってきたため、原因である可能性があります)。
  • スクリプトには最初のSETステートメントがありませんでした(本番環境でのドライバーの問題のために必要ですが、ローカルでのクリーンインストールでは必要ありません)。

これを約1時間(再度)デバッグした後、これが二度と起こらないことを確認するためにいくつかの単体テストを作成することを決定しました(アサーションメッセージにすばやく修正して将来の開発者に簡単な修正を提供する方法を含める)。

ただし、このコードをプッシュすると、別の同僚(私たちのチームリーダーでもある)が私に近づいてきて、次の理由でこれらを作成するべきではないことを教えてくれました。

「これらは単体テストには属していません」

「ユニットテストは、コードのフローをチェックするためにのみ使用する必要があります」

このバグは将来的には再導入されないので、自分のやっていることは間違っていないと私はまだ思っているので、今はかなり葛藤していますが、この同僚は先輩として働いて、最終的に何を決定するようになります私たちは時間を費やしています。私は何をすべきか?このようにするのは間違っているのでしょうか?それは悪い習慣と考えられていますか?

83
Paradoxis

ほとんどの場合、作成したテストは、単体テストよりも統合テストまたは回帰テストに近いものです。この行は非常に曖昧で、ユニットテストの有無に関係なく歩み寄ることもありますが、コードの正確さを保証する付加価値があるので、同僚に戻って、どこにテストを記述すべきかを尋ねます。

単体テストとは何かにあまり焦点を当てず、統合テストであっても、テストにはまだ価値があることに気づきます。

155

技術的には、これは単体テストではなく、検証ステップの詳細です。適切なアプローチは、ワークフローの必要性に依存します。ユニットテストの目的が何であるかについて、チームリーダーは正しいです。私の考えでは、これはまだやらなければならない仕事に間違ったツールを使用する場合だと思います。だからこれから始めましょう:

私が解決しようとしている問題は何ですか?

説明によって、データベーススクリプトがいくつかの標準に準拠していることを検証する必要があります。

問題を解決するために利用できるツール/プロセスは何ですか?

ソースコードの品質は通常静的分析ツールによってチェックされます。 SQLを検証するための静的分析ツールがない場合、渡されたany SQLファイルのチェックを実行する迅速でダーティなツールを作成できます。話している問題を処理できる静的分析ツールがあるかどうかを確認しても問題はありません。

Jenkinsに組み込むなど、ビルドインフラストラクチャの一部を作成すると、プロジェクトのすべてのSQLファイルに適用できます。

単体テストでは、現在のファイルの問題のみが解決されます。

ツールの必要性をどのように伝えますか?

これはとても簡単です。あなたはチームのリーダーと話します。彼は製品の所有者およびあなたと協力して、ツールへの投資のリスク/報酬を決定できます。これが1回限りの問題である可能性がある場合、ツールは多すぎるでしょう。最大の問題を検出するためのツールが簡単な場合は、健全性チェックだけでも価値があるかもしれません。

チームリーダーは、あなた(または私)が考慮していないいくつかのアイデアを持っている可能性があります。

35
Berin Loritsch

ファイルにアクセスするテストを「ユニットテスト」と呼ぶのは悪い習慣です。

彼:「これらは単体テストには属していません」

あなた:「理にかなっているが、私はそれらを置くためのよりよい場所を見つけることができませんでした。それらはどこに属していますか?」

残念ながら、どのような種類のテストが存在し、どのように構成されているかは、完全に会社固有です。したがって、あなたの会社がこれらのテストをどのように処理するかを知る必要があります。

単体テスト以外の自動テストを実行する方法がまだない場合、実用的な方法は、実際には単体テストではない単体テストにプレフィックスを付けることです。あなたが実際に持っている/必要とするテスト。その後、整理を開始できます。

19
Peter

マイケルフェザーズはこれを彼の著書「レガシーコードを効果的に使用する」で述べています。

業界では、特定のテストが単体テストであるかどうかについて、人々は往々にして行き来します。 [...] 2つの特性に戻ります。テストは高速に実行されますか?エラーを迅速に特定するのに役立ちますか?

あなたのテストはエラーを迅速に特定し、高速に実行するのに役立ちますか?はいの場合、それを実行してください!いいえの場合は、しないでください。それはそれと同じくらい簡単です!

そうは言っても、あなたは他の人々と一緒にいる環境で働いており、彼らとうまくやっていく必要があります。あなたが個人的にそれに同意しない場合でも、あなたはそれを彼のやり方でやらなければならないかもしれません。

14
CJ Dennis

ソースコードファイルや構成ファイルなどに対して、時々同様のテストを作成しました。 (a)ファイルシステムにアクセスしており、超高速ではない可能性があるため、私はそれらをユニットテストとは呼びません(b)チェックインのたびに実行されるかどうかは気にしません( CIサーバー)。

それらを統合テストと呼ぶかもしれません。確かに、それらは単体テストよりもその視点に近いです。

それらに対する私自身の用語はresource testsです。私見、CIサーバーで夜間に実行する場合、それらは完全に正当化されます。コストは最小限であり、慎重に使用すると明らかに価値が追加されます。 慎重にの1つの定義:テストが、問題の原因となった問題(言及したエンコードなど)をチェックする場合。

10
Michael Easter

ユニットテストとは、メソッドまたはコードの「ユニット」をテストすることです。ソフトウェアのロジックとコードの最小グループをテストしています。

後で、それを他のユニットと結合すると、統合テストを実行します。

あなたのチームリーダーがあなたのイニシアチブを奨励し、別の提案を提供するべきでしたあなたは間違いなく正しい考えを持っています。

SQLは、C#やJavaなどの下位世代の言語と同じようにコードであり、そのようにテストする必要があります。検証と検証はすべてのテストレベルに属します。したがって、エンコードとSETステートメントは含まれますが、必ず排他的にテストされます。行末や囲みなどの一般的なものは、通常、SCMフックまたは機能のみを使用できます。

ベストプラクティスは、過去のバグが再導入されないようにするための回帰テストを行うことです。通常、テストはバグの解決策とともに作成されます。これらのバグがユニット/統合またはシステムレベルの回帰テストでカバーされず、再導入された場合、それはチームの問題であり、プロセスの問題であり、個別の問題ではありません。

問題は...構文エラー、不足しているステートメント、または「ユニット」内の論理ブロックは通常、テストされません。ユニットの入力と出力をさまざまな組み合わせでテストし、生成される可能性のある多くの可能性をテストします。

欠落しているSETステートメントに戻る-テストする入力と出力の多くの可能性を通知するのに役立ちます。選択したSETが1つでも見つからなかった場合に失敗する、どのようなテストを記述しますか?

4
Ross

製品の一部となるファイルがある場合、その内容は正しい必要があります。これを確認しない理由はありません。たとえば、あるフォルダに1024x 1024の画像が6つ必要な場合は、それが正しいかどうかを確認する単体テストを必ず記述してください。

しかし、おそらくファイルだけではなく、ファイルを読み取るコードもいくつかあります。そのコードの単体テストを作成できます。上記の例で、6つの画像の1つを読み取る関数は、メモリ内の1024 x 1024画像(またはそれが生成するはずのもの)を返しますか?.

とにかく、それは単体テストではないかもしれませんが、それは有用なテストです。また、便利なテスト(単体テストではない)を実行できる単体テストフレームワークを使用している場合は、なぜ単体テストフレームワークを使用しないのですか?

3
gnasher729

おそらく私はあなたの問題を誤解しているかもしれませんが、私にとってこれは、どのような種類の専用テストでもキャプチャする必要はない問題のように聞こえますバージョン管理システムによって。コードベースの変更は、コミットする前にパッチごとに確認する必要があります。 gitでこれを行う簡単な方法は、変更を追加することです

git add -p

これにより、テキストファイルが変更されるたびに、作業ディレクトリで本当に保持するかどうかが尋ねられます。たとえば、これらの「最初のSETステートメント」の削除を確認できます。

ただし、ファイル全体のエンコードが変更された場合は、アルゴリズムが古いファイルと新しいファイルの比較に失敗するため、git add -pは何も追加しません。これは、コミット前に実行する他のコマンド、つまり

git status

ここでは、ファイルが赤で強調表示されており、areの変更があることを示しています。これらがgit add -pに組み込まれなかった理由を調査すると、問題がすぐに明らかになります。

2
leftaroundabout

考慮すべき別の角度:これらの2つの条件はプログラムを実行するための要件であるため、ロジックを実行ロジックの近くに埋め込むべきではありませんか?つまり、ファイルを読み取る前にその存在をテストしたり、ファイルの内容を検証したりしますよね?これはどのように違うのですか?これはコード外部リソースなので、実際に使用する前に、実行時に検証する必要があると思います。結果:より強力なアプリ。追加のテストを作成する必要はありません。

ユニットテストは、コードのユニットを分離して実行し、正しい入力に対して正しい結果が生成されていることを確認することです。分離により、テスト対象のユニットとテスト自体の両方を再現可能にする必要があります。つまり、副作用に依存したり、副作用を導入したりしないでください。

SQLは、個別にテストできるものではないため、SQLのテストは単体テストではありません。また、SELECTステートメントを除いて、副作用があることはほぼ確実です。単体テストではなく、統合テストと呼ぶことができます。

導入される可能性のある欠陥を開発サイクルのできるだけ早い段階で確実に検出できるようにすることは常に賢明であり、欠陥の原因を簡単に特定できるようにして、迅速に検出できるようにすることは有益です。修正。

問題のテストは、「ユニットテスト」の本体からより適切に再配置して別の場所に配置できますが、追跡に数時間かかる可能性のある欠陥の導入を防ぐなどの有用なことをしている場合は、完全に削除しないでください。ダウン。

1
Zenilogix

テストは他のテストと同じコードであり、十分に複雑な場合は、単体テストからも恩恵を受けます。そのような前提条件チェックを直接テストに追加するのが最も簡単なようです。

ほとんどのテストはこれを必要としないほど簡単ですが、いくつかが十分に複雑な場合、これらの前提条件チェックで根本的に問題があるとは思われません。もちろん、テストはそれらなしでも失敗するはずですが、優れたユニットテストはどのユニットも失敗していることを示します。

テストの一部として使用され、特定のコンテンツとエンコーディングが必要なスクリプトは、おそらくユニットです。テストの他の部分よりもはるかに多くのコードとロジックがある場合があります。そのようなスクリプトを使用したテストは、これまでで最高の設計ではなく、可能であれば、より直接的なものにリファクタリングする必要があります(これが統合テストでない限り)。

1
h22

まず、テストの目的の1つは、コードで問題が再発しないようにすることです。つまり、絶対にすべきこの性質のテストを書き続けます。

第二に-命名は難しいです。はい、これらは明らかに「単体テスト」ではありませんが、明らかな間違いからユーザーを保護し、エラーについてより早くフィードバックを返すため(特に、開発ボックスへの影響)。

したがって、実際に問題となるのは、これらのテストをいつどのように実行するかということです。

私は過去にこの種のテストを広範囲に使用しました-それらは私たちにかなりの苦痛を救ってくれました。

1
Murph