27

次の方法があるとします。

public function setFoo($foo) {
    $this->_foo = $foo;
    return $this;
}

public function getFoo() {
    return $this->_foo;
}

将来、より複雑なものに変更される可能性があると仮定します。

  • これらのメソッドの単体テストをどのように記述しますか?
  • テスト方法は 1 つだけですか?
  • それらのテストをスキップする必要がありますか?
  • コードカバレッジはどうですか?
  • @covers注釈はどうですか?
  • 抽象的なテストケースに実装する普遍的なテストメソッドでしょうか?

(私は Netbeans 7 を使用しています)

これは時間の無駄のように思えますが、IDE がこれらのテスト メソッドを自動的に生成するかどうかは気にしません。

Sebastian Bergman のブログのコメントから引用するには:

(ゲッターとセッターをテストするようなものです -- 失敗します!)。いずれにせよ、失敗した場合。それらに依存するメソッドは失敗しませんか?

では、コード カバレッジはどうでしょうか。

4

3 に答える 3

8

TDD を行う場合は、ゲッターとセッターのテストを作成する必要があります。それも。コードが非常に単純であっても、テストなしでコードを 1 行も書かないでください。

テストにゲッターとセッターのタンデムを使用するか、ユニットテストフレームワーク機能を使用して保護されたクラスメンバーにアクセスしてそれぞれを分離することは、一種の宗教戦争です。ブラック ボックス テスターとして、私は単体テスト コードを具体的な実装の詳細に結び付けるのではなく、公開 API に結び付けることを好みます。変化を期待しています。開発者には、既存のコードをリファクタリングするよう奨励したいと思います。また、クラスの内部は「外部コード」(この場合は単体テスト) に影響を与えるべきではありません。内部が変更されたときに単体テストを中断したくありません。パブリック API が変更されたとき、または動作が変更されたときに中断したいと考えています。わかりました、わかりました、失敗した単体テストの場合、唯一の問題の原因を特定しないでください。問題の原因を突き止めるには、ゲッターとセッターを調べる必要があります。ほとんどの場合、getter は非常に単純です (コードは 5 行未満です。たとえば、return と例外を伴うオプションの null チェック)。したがって、これを最初に確認することは大したことではなく、時間もかかりません。また、setter のハッピー パスのチェックは、ほとんどの場合、もう少し複雑です (たとえいくつかの検証チェックがあったとしても)。

テスト ケースを分離するようにしてください。他の方法に依存せずにその正確性を検証する SUT (Subject Under Test) のテストを作成してください (上記の例を除く)。テストを分離すればするほど、テストはより多くの問題を発見します。

テスト戦略によっては、ハッピー パスのみをカバーしたい場合があります (プラグマティック プログラマー)。または悲しい道も。すべての実行パスをカバーすることを好みます。すべての実行パスを発見したと思ったら、コード カバレッジをチェックしてデッド コードを特定します (カバーされていない実行パスがあるかどうかを特定するためではなく、100% のコード カバレッジは誤解を招く指標です)。

ブラック ボックス テスターが厳密モードで phpunit を使用し、@covers を使用して付随的なカバレッジを非表示にすることは、ベスト プラクティスです。

単体テストを作成する場合、クラス A のテストはクラス B とは独立して実行する必要があります。したがって、クラス A の単体テストは、クラス B のメソッドを呼び出したりカバーしたりしないでください。

廃止された getter/setter およびその他の「デッド」メソッド (プロダクション コードでは使用されていない) を特定する場合は、そのために静的コード分析を使用します。あなたが興味を持っている指標は、「メソッドレベルでの求心性結合(MethodCa)」と呼ばれています。残念ながら、このメトリック (ca) は PHP 依存のメソッドレベルでは利用できません (参照: http://pdepend.org/documentation/software-metrics/index.htmlおよびhttp://pdepend.org/documentation/software-metrics /afferent-coupling.html)。本当に必要な場合は、お気軽に PHP Depend に投稿してください。同じクラスからの呼び出しを除外するオプションは、「付随的な」呼び出しなしで結果を得るのに役立ちます。「死んだメソッド」を特定した場合は、それが近い将来に使用されることを意図しているかどうかを確認してください (@depricated アノテーションを持つ他のメソッドの対応物)、そうでない場合は削除してください。同じクラスでのみ使用する場合は、private/protected にしてください。このルールをライブラリ コードに適用しないでください。

プラン B: 受け入れテスト (統合テスト、回帰テストなど) がある場合は、単体テストを同時に実行せずに、また phpunits の厳密モードを使用せずに、そのテストを実行できます。これにより、製品コードを分析した場合と非常によく似たコード カバレッジ結果が得られます。しかし、ほとんどの場合、非単体テストは本番コードほど強力ではありません。意味のある結果を得るために、このプラン B が製品コードと「十分に等しい」かどうかは、分野によって異なります。

さらに読む: - 書籍: Pragmatic Programmer - 書籍: きれいなコード

于 2013-06-30T10:00:38.217 に答える
6

良い質問、

実際に何かを行うメソッドのみをテストすることで大きなメリットが得られるため、私は通常、ゲッターとセッターを直接テストしないようにしています。

特にTDDを使用していない場合、これには、単体テストで使用していないセッターが表示されるという追加の利点があり、テストが不完全であるか、セッターが使用されていない/必要がないことが示されます。「そのセッターを使用せずにすべての「実際の」コードを実行できる場合、なぜそこにあるのですか。」

流暢なセッターを使用する場合、セッターの「流暢」な部分をチェックするテストを書くことがありますが、通常は他のテストでカバーされています。

あなたのリストに答えるには:

  • テスト方法は 1 つだけですか?

それは私の最も嫌いなオプションです。すべてまたはなし。1 つだけをテストすることは、他の人が理解するのは簡単ではなく、「ランダム」に見えるか、何らかの方法で文書化する必要があります。

コメント後に編集:

はい、「簡単な」get/set テストでは、プロパティごとに 1 つのメソッドのみを使用します。場合によっては、クラス全体で 1 つのメソッドのみを使用することもあります (多くの getter と setter を持つ値オブジェクトの場合、作成/維持したくありません) 多くのテスト)

  • これらのメソッドの単体テストをどのように記述しますか?
  • それらのテストをスキップする必要がありますか?

私はそれらをスキップしません。持っているゲッターの数によってはゲッターかもしれませんが(実際に必要なゲッターだけを書く傾向があります)、クラスを完全にカバーするというタスクは、ゲッターのために失敗するべきではありません。

  • コードカバレッジはどうですか?
  • @covers アノテーションはどうですか?

私の見解で@coversは、常に「どこでも使用するか、まったく使用しないか」です。テストの 2 つの「スタイル」を混在させると、注釈の利点の一部が失われ、「未完成」に見えます。

  • おそらく、抽象的なテストケースに実装する普遍的なテスト方法はありますか?

うまく機能する値オブジェクトのようなもののために。型ヒントを使用してオブジェクト/配列を渡すと、壊れる (またはより複雑になる) 可能性がありますが、500 個のゲッターとセッターの手動テストを作成するよりも、個人的にはそれを好みます。

于 2011-02-14T08:45:01.970 に答える
3

これはよくある質問ですが、不思議なことに SO でだまされた人を見つけることができません。

アクセサーの単体テストを作成できますが、大多数の実践者は作成しません。つまり、アクセサーにカスタム ロジックがない場合、フィールド アクセスが機能するかどうかを検証する単体テストは作成しません。代わりに、これらのアクセサーのコンシューマーに依存して、アクセサーが確実に機能するようにします。たとえば、getFoo と setFoo が機能しない場合、これらのメソッドの呼び出し元は壊れる必要があります。したがって、呼び出しメソッドの単体テストを作成することで、アクセサーが検証されます。

これは、コード カバレッジが問題にならないことも意味します。すべてのテスト スイートを実行した後にカバーされていないアクセサーが見つかった場合、それらは冗長または未使用である可能性があります。それらを削除します。

クライアントがそのアクセサーを使用するシナリオを示すテストを作成してみてください。たとえば、以下のスニペットは、一時停止ボタンのツールチップ (プロパティ) が現在のモードに基づいてどのように切り替わるかを示しています。

[Test]
public void UpdatesTogglePauseTooltipBasedOnState()
{
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons));

    _mainViewModel.TogglePauseCommand.Execute(null);
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_ResumeAllBeacons));

    _mainViewModel.TogglePauseCommand.Execute(null);
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons));
}
于 2011-02-14T05:43:15.937 に答える