3

テスト コミュニティの一般的なコンセンサスは、private メソッドをテストしないことのようです。代わりに、それらを呼び出すパブリック メソッドをテストして、プライベート メソッドをテストする必要があります。しかし、何かが私には正しくありません。たとえば、次の方法を考えてみましょう。

/**
 * Returns the base name of the output generator class. If the class is named
 * Reno_OutputGenerator_HTML, this would return "HTML".
 *
 * @return string
 */
protected function getName()
{
    $class = get_class($this);
    $matches = array();

    if (preg_match('/^Reno_OutputGenerator_(.+)$', $class, $matches))
    {
        return $matches[1];
    }
    else
    {
        throw new Reno_OutputGenerator_Exception('Class name must follow the format of Reno_OutputGenerator_<name>.');
    }
}

この特定の関数は、私のクラスのいくつかの場所で使用されています。この関数のステートメントの両方のブランチをテストしたいと思いifます。つまり、パブリック関数ごとに、これら 2 つの状況に加えて、パブリック メソッド自体が行うすべてのことをテストする必要があります。

これは私にとって奇妙に感じるものです。getName()特定の特定の条件が満たされたときに が例外をスローするかどうかをテストしている場合、それはプライベート メソッドの実装の詳細を知る必要があることを意味します。それを知る必要がある場合は、クラスを拡張し、メソッドをパブリックにして、そのようにテストしないのはなぜですか?

(ところで、なぜこのような奇妙なメソッドが存在するのか疑問に思っているなら、これは、このクラスのテンプレートファイルが保存されているディレクトリを自動的に把握するために使用されます)。

4

2 に答える 2

2

私がユニットテストを理解する方法では、これはまさに私がやりたいと思う種類のテストです。私は常にユニットテストをホワイトボックステストと見なしてきました。コードに分岐点がある場合、それに対処するには2つの単体テストが必要です。私がこれまでに経験した最悪のケースは、32の順列を持つ単一の方法だったと思います。

単体テストの課題は、コードを調べてさまざまなパスをすべて把握してすべてのエッジケースを調査しないと、1つ以上のケースが欠落し、アプリケーションに微妙なバグが発生する可能性があることです。

だから、いや、あなたが提案しているものが奇妙だとは思わない。メソッドは内部にとどまることができ、テストケースを追加することができます-おそらく例外を除いて必要なのは1つだけですよね?

または、機能を別のオブジェクトにリファクタリングして、ジェネレータオブジェクトを取得し、その名前を返すこともできます(上記のアルゴリズムに基づく)。これは、名前抽出オブジェクトと出力ジェネレーターの実装があるため、テストを分離することを正当化します。名前エクストラクタが正しく使用されていることを確認するために出力ジェネレータをテストする必要があるため、これで大幅に節約できるかどうかはまだわかりませんが、機能とテストの問題が分離されます。

于 2010-09-28T01:17:29.787 に答える
0

次のようにテストクラスのクラスから派生させて、この関数をテストすることもできます。

namespace TheProject
{
    public class ClassUnderTest
    {
        protected string GetName()
        {
            return "The name";
        }
    }
}

namespace TestProject
{
    [TestClass]
    public class TheTest:TheProject.ClassUnderTest
    {
        [TestMethod]
        public void TestGetName()
        {
            string expected = "The name";
            string actual = GetName();
            Assert.AreEqual(expected, actual);
        }
    }
}

そうすれば、メソッドを非公開に保つことができ、コードを別のクラスにリファクタリングする必要がなくなります。

于 2010-09-28T05:44:20.603 に答える