単体テストの「単体」で理解されること


9

私が理論上「ユニット」の下で理解しているように、人々は方法(OOP)を意味します。しかし、実際には、いくつかのメソッドを分離して検証するテストは、非常に壊れやすい動作テストです(結果ではなく、いくつかの依存関係メソッドが呼び出されたことを検証します)。そのため、密接に関連するクラスの小さなセットをユニットごとに理解する多くの人々を目にします。この場合、外部の依存関係のみがモック/スタブされ、ユニット内部の依存関係には実際の実装が使用されます。この場合、より多くの状態があり、(仕様によると)意味があり、それほど脆弱なテストではありません。したがって、問題はこれらのアプローチについてどのように感じていますか、2番目のアプローチの単体テストを呼び出すことは有効ですか、それとも何らかの低レベルの統合テストなのでしょうか?

これらのテスト方法のいずれかによるTDDの適用に関する特定の考慮事項が表示された場合は、私はあなたの考えに感謝します。

回答:


11

もともとTDDはアジャイルムーブメントから来たもので、テストコードで明確に定義された仕様を前提として、コーディングした内容が正しいことを確認する方法として、テストが前もって作成されました。これは、リファクタリングの非常に重要な側面としても現れました。コードを変更したときに、テストに依存して、コードの動作を変更していないことを証明できるからです。

それから人々がやって来て、彼らがあなたのコードについての情報を知っていて、それからあなたがあなたのユニットテストを書くのを助けるためにテストスタブを生成できると思ったツール、そして私はそれがすべてうまくいかなかったと私は思います。

テストスタブは、何をしているのかまったくわからないコンピューターによって生成されます。すべてのメソッドに対してスタブを生成するのは、それが指示されているためです。つまり、メソッドの複雑さや、単独でのテストに適しているかどうかに関係なく、各メソッドにテストケースがあります。

これは、TDD方法論の間違った端からのテストに来ています。TDDでは、コードが何をすべきかを理解し、それを実現するコードを生成する必要があります。これは、コードが実行するはずの動作ではなく、コードが実行する動作を証明するテストを作成することになるので、自己実現的です。メソッドベースのテストスタブの自動生成と組み合わせると、コードの小さな各側面を証明するのにかなりの時間を浪費し、小さな部分をすべて組み合わせると簡単に間違っていることがわかります。

ファウラーが本でテストについて説明したとき、彼は独自のメインメソッドで各クラスをテストすることを言及しました。彼はこれを改善しましたが、概念は同じです。クラス全体をテストして全体として機能します。すべてのテストをまとめて、これらすべてのメソッドの相互作用を証明し、定義された期待に応じてクラスを再利用できるようにします。

テストツールキットは私たちに不幸を与えたと思います。ツールキットが実際にコードで最良の結果を得るために自分でもっと考える必要があるときに物事を行う唯一の方法であると考える道に私たちを導いた。小さな部分のテストスタブに盲目的にテストコードを配置するということは、とにかく統合テストで作業を繰り返す必要があることを意味します(そして、そうする場合は、冗長なユニットテスト段階を完全にスキップしないでください)。また、100%のテストカバレッジを取得するために多くの時間を浪費し、大量のモックコードとデータの作成に多くの時間を費やして、コードを統合テストしやすくするために費やした方がよいことも意味します(つまり、データの依存関係、単体テストは最適なオプションではない場合があります)

最後に、メソッドベースの単体テストの脆弱性が問題を明らかにしているだけです。リファクタリングはユニットテストで使用するように設計されています。リファクタリングを行っているためにテストが常に失敗する場合は、アプローチ全体で何かが深刻な問題を起こしています。リファクタリングはメソッドの作成と削除を好むので、メソッドごとのブラインドベースのテストアプローチは本来意図されたものではありません。

多くのメソッドがテストを作成することは間違いありません。クラスのすべてのパブリックメソッドをテストする必要がありますが、単一のテストケースの一部としてそれらを一緒にテストするという概念から逃れることはできません。たとえば、setメソッドとgetメソッドがある場合、データを入力して内部メンバーが正常に設定されていることを確認するテストを作成できます。または、それぞれを使用してデータを配置し、それを再度取り出して、それが正しいかどうかを確認できます。まだ同じで文字化けしていません。これは、各メソッドを個別にではなく、クラスをテストしています。セッターがヘルパーのプライベートメソッドに依存している場合は問題ありません。クラス全体をテストする場合ではなく、プライベートメソッドをモックしてセッターが機能していることを確認する必要はありません。

私は宗教がこのトピックに参入していると思います。したがって、「行動主導型」および「テスト主導型」の開発として現在知られているものへの分裂がわかります。ユニットテストの元の概念は、行動主導型の開発でした。


10

ユニットは最も一般的に「アプリケーションのテスト可能な最小部分」として定義されます。多くの場合、そうです、これは方法を意味します。そして、はい、これは依存メソッドの結果をテストするべきではなく、メソッドが呼び出されることだけを意味します(そのメソッドのすべてのテストではなく、可能であれば一度だけ)。

あなたはこれを壊れやすいと呼びます。それは間違いだと思います。壊れやすいテストとは、無関係なコードへのわずかな変更で壊れるテストです。つまり、テストされる機能に関係のないコードに依存するものです。

しかし、あなたが本当に言っていると私が思うのは、依存関係のないメソッドをテストすることは完全ではないということです。その点で私は同意します。また、アプリケーションを作成するためにコードのユニットが正しくフックされていることを確認するための統合テストも必要です。

これはまさに、振る舞い主導の開発、特に受け入れテスト主導の開発が解決しようとする問題です。ただし、単体テストやテスト駆動開発の必要性がなくなるわけではありません。それを補完するだけです。


私は本当に行動テストは壊れやすいと言いたかった。彼らはしばしばコードベースの変更中に偽陰性になります。状態テストではそれほど発生しません(ただし、単体テストでは状態テストがほとんど行われません)
SiberianGuy

@Idsa:私はあなたの定義に少し迷っています。動作テストは統合テストであり、指定された動作の一部をテストします。元の質問を読んで、州のテストと言っても、同じことを意味しているようです。
pdr 2011

状態とは、ある機能の状態、結果を検証するテストを意味します。行動とは、結果ではなく、いくつかの関数が呼び出されたという事実を検証するテストを意味します
SiberianGuy

@Idsa:その場合、私は完全に反対します。状態テストと呼んでいるものを統合と呼びます。あなたは行動と呼んでいるものをユニットと呼んでいます。まさにその定義による統合テストはより脆弱です。グーグルの「統合テストユニットは壊れやすい」と私だけではないことがわかります。
pdr 2011

テストに関する記事のログがありますが、どれがあなたの意見を共有していますか?
SiberianGuy

2

名前が示すように、各テストでアトミックサブジェクトをテストしています。そのような主題は通常単一の方法です。ハッピーパスや起こり得るエラーなどをカバーするために、複数のテストが同じメソッドをテストできます。内部メカニズムではなく、動作をテストしています。つまり、ユニットテストは、実際にはクラスのパブリックインターフェイス、つまり特定のメソッドをテストすることです。

単体テストでは、メソッドを分離してテストする必要があります。つまり、依存関係をスタブ/モック/偽造することです。それ以外の場合、「実際の」依存関係でユニットをテストすると、統合テストになります。両方のタイプのテストには時間と場所があります。単体テストでは、単一のサブジェクトがスタンドアロンで期待どおりに機能することを確認します。統合テストは、「実際の」被験者が正しく連携することを保証します。


1
完全ではありませんが、自動化ツールがメソッドを処理することを好むからといって、ユニットが孤立したサブジェクトになるわけではありません。ここで重要なのは「分離」です。メソッドをテストする場合でも、プライベートメソッドもテストする必要があります。
gbjbaanb 2013年

1

私の経験則:バグを含むのに十分複雑なコードの最小単位。

これがメソッド、クラス、サブシステムのいずれであるかは、特定のコードに依存するため、一般的な規則はありません。

たとえば、単純なゲッター/セッターメソッドを単独でテストしたり、別のメソッドのみを呼び出すラッパーメソッドをテストしたりするための値は提供されません。クラスが薄いラッパーまたはアダプターのみの場合、クラス全体でさえテストするには単純すぎる場合があります。テストする必要があるのがモックのメソッドが呼び出された場合のみ、テスト対象のコードはシンになります。

他の場合では、単一のメソッドがいくつかの複雑な計算を実行する可能性があり、これを単独でテストするのに役立ちます。

多くの場合、複雑な部分は個々のクラスではなく、クラス間の統合です。したがって、一度に2つ以上のクラスをテストします。これは単体テストではなく統合テストだと言う人もいますが、用語を気にしないでください。複雑さがどこにあるかをテストする必要があり、これらのテストはテストスイートの一部である必要があります。

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