1

このトピックに関する他のディスカッション (StackOverflow) を見てきましたが、他の質問は言語固有のようですが、これは言語固有ではなく、プライベート メソッド、クラス、およびモジュールを使用しないことを検討しています。

バグをより簡単に見つけられるように、プライベート メソッド、クラス、およびモジュールをテストしたいと考えています。これを可能にするために、プライベート メソッド、クラス、およびモジュールを使用しないことを検討しています。その理由は 2 つあります。 「魔法」と(2)コードの再利用を改善します。データは保護する必要があり、動作を提供しないため、プライベート変数とプロパティを使用しないことを検討していないことに注意してください。したがって、テスト中にパブリックにする必要はありません。

OneOperations下手な例として、 2 つのパブリック メソッドaddOneandsubtractOneと 2 つのプライベート メソッドaddandを持つというモジュールを書いているとしsubtractます。プライベート メソッドを持つことを許可していない場合は、2 つのプライベート メソッドを別のモジュール ( basicOperations) に配置し、そこでそれらをパブリックにして、それらのメソッドをOneOperationsモジュール内にインポートします。これから、コードを挿入することなく、両方のモジュールのすべてのメソッドのテスト コードを記述できるようになります。これの利点は、モジュールをインポートすることにより、メソッドaddとメソッドをsubtract他のモジュールで使用できるようになったことbasicOperationsです (2 - コードの再利用の改善)。

これは悪い考えだと感じていますが、これを行わないことを正当化するための実際の経験が不足しているため、この質問を StackOverflow に投稿しました。

では、プライベート メソッド、クラス、およびモジュールをどのようにテストしますか? プライベート メソッド、モジュール、およびクラスを作成することは潜在的な解決策ではありませんか?

4

2 に答える 2

1

これを調べる別の方法があります。それは、プライベート メソッドをどのように生成するかということです。

TDD プロセスを適切に実行している場合、最初に作成するのはテストです。この時点で、テストにはすべてのコードが含まれているはずです。

public void ShouldAddTwoNumbers()
{
  (1 + 1).ShouldEqual(2);
}

はい、それはぞっとするように見えます。しかし、いくつかの追加のテストを書いているときに何が起こるかを考えてみてください。

public void ShouldAddTwoMoreNumbers()
{
  (2 + 2).ShouldEqual(4);
}

これでリアクターに何かができたので、それは次のようになります

public void ShouldAddTwoNumbers()
{
  Add(1, 1).ShouldEqual(2);
}

public void ShouldAddTwoMoreNumbers()
{
  Add(2, 2).ShouldEqual(4);
}

private int Add(int a, int b)
{
  return a+b;
}

これで、テスト クラス内でテストできるプライベート メソッドができました。プライベートが問題になるのは、コードをアプリケーションに移動するためのさらなるリファクタリングを完了したときだけです。自動化されたリファクタリング ツールのほとんどは、この時点でメソッド シグネチャを変更するオプションを提供します。これにより、プライベート メソッドはプライベートではないため、引き続きアクセスできるようになります。

(上で言い換えたキース・ブレイスウェイトの言葉のように、TDDと呼ばれる素晴らしいエクササイズがあります)

ただし、これでリファクタリングと開発が終了したわけではありません。テストを作成してリファクタリングする際に行うべきことの 1 つは、たとえば機能が重複している場合などに、古いテストを削除することです。もう 1 つは、同じことを繰り返さないように新しい方法を抽出することです。これらは両方とも、非テスト コード ベースにプライベート メソッドが戻ってくるシナリオにつながる可能性があります。

したがって、私のアドバイスは、実際的になり、目の前のコードに対して最善の決定を下すことです。プライベート メソッドを作成しないことはお勧めしませんが、その代わりに、プライベート メソッドを作成する要因を検討します。

于 2013-10-02T00:04:58.573 に答える
1

1) このトピックに関する他の多くの回答と同様に、主な質問は、なぜプライベート メソッドをテストしたいのかということです。クラスの目的は、そのクライアントにいくつかの機能を提供することです。このクラスのパブリック インターフェイスが正しく動作することを証明する包括的な単体テストがある場合、プライベート メソッドで何をしているのか気にする必要はありません。

2) プライベート メソッドをまったく持たないというあなたの考えは、足を切断するように思えます。小規模なプロジェクトの場合、すべての小さな動作を適切に分離してテストすることが可能になる場合があります。しかし、大規模なプロジェクトの場合、それはやり過ぎです。重要なのは、ドメイン ロジックが正しく動作することです。

たとえば、次のメソッドを考えてみましょう。

public double getDistanceSquared(Point other)
{
    return getDifferenceSquared(this.x, other.x)
      + getDifferenceSquared(this.y, other.y); 
}

private double getDifferenceSquared(double v1, double v2)
{
    return (v1 - v2)*(v1 - v2);
}

Ad1)すべてのテスト ケースで正しい結果が返されるgetDifferenceSquared場合、ユニット テスト メソッドは本当に意味があるのでしょうか?getDistanceSquared

Ad2) double 間の二乗距離を計算するための別のクラスを作成する - 使用される場所が 1 つしかない場合、数百万のテストを伴う小さなクラスの群れが発生します。また、ドメイン クラスのコンストラクターは、内部で行っている小さなことごとに 10 の異なるインターフェイスを受け入れます。

これらすべてを維持することは、多くの不必要な作業です。距離の計算方法を変更したいとします (事前に計算された値を使用するなど)。の動作はgetDistanceSquared変わりません。getDifferenceSquaredただし、距離が正しく計算されている限り、距離がどのように計算されるかを気にする必要はありませんが、すべてのテストを変更する必要があります。

必要のないときに些細なことに飛び込むと、自分が実際に何をしているかを忘れてしまいます。「全体像」が失われます。時間を大切にして、重要な問題に集中してください。

補足として、単体テストの主な関心事は、あなたが示唆するように「バグを見つける」ことではありません。それらはクリーンなデザインを課し、コードの動作に関する常に最新のドキュメントを提供し、柔軟性を提供する便利なリファクタリングを可能にします。さらに、コードが期待どおりに機能していることを保証します。

http://artofunittesting.com/definition-of-a-unit-test/

http://en.wikipedia.org/wiki/Unit_testing#Benefits

于 2013-09-22T11:42:56.733 に答える