3

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

public Foo ParseMe(string filepath)
{
    // break up filename
    // validate filename & extension
    // retrieve info from file if it's a certain type
    // some other general things you could do, etc

    var myInfo = GetFooInfo(filename);

    // create new object based on this data returned AND data in this method
}

現在、 の単体テストがGetFooInfoありますが、 の単体テストも作成する必要があると思いますParseMe。このような状況では、2 つの異なるプロパティを返す 2 つのメソッドがあり、どちらかを変更すると何かが壊れる可能性があります。出力が期待どおりであることを確認するために、両方の単体テストを作成する必要がありますか?

私は慎重に過ちを犯し、物事が壊れて、後のメンテナンスが容易になるように注意するのが好きですが、テスト プロジェクトに非常によく似たテストを追加することに非常に懐疑的です。これは悪い習慣でしょうか、それともこれをより効率的に行う方法はありますか?

私はこれを言語に依存しないものとしてマークしていますが、念のために C# と NUnit を使用しています - また、これに似た投稿をタイトルのみで見ましたが、質問は異なります。これがすでに尋ねられている場合は申し訳ありません。

4

4 に答える 4

6

ParseMe単体テストが必要なほど自明ではないように見えます。正確な質問に答えるには、「2 つの異なるプロパティを返す 2 つのメソッドがあり、いずれかを変更すると何かが壊れる可能性がある」場合は、絶対に単体テストを行う必要があります。

作業の大部分が にある場合でも、GetFooInfo少なくとも実際に呼び出されることをテストする必要があります。私は NUnit については何も知りませんが、他のフレームワーク (RSpec など) で のようなテストを記述できることは知っていますGetFooInfo.should be_called(:once)

于 2013-05-24T14:38:57.480 に答える
4

別のメソッドを呼び出しているメソッドをテストすることは悪い習慣ではありません。実際、それは良い習慣です。別のメソッドを呼び出すメソッドがある場合は、おそらく追加機能を実行しているため、テストする必要があります。

単体テストされているメソッドを呼び出すメソッドを単体テストしていることに気付いた場合、コードの再利用が発生している可能性がありますが、これは良いことです。

于 2013-05-24T14:40:50.287 に答える
3

私は@tsmに同意します-両方の方法を絶対にテストしてください(両方が公開されていると仮定します)。

これは、メソッドまたはクラスがやりすぎているという匂いかもしれません - 単一責任の原則に違反しています。Extract Class リファクタリングを実行し、2 つのクラスを分離することを検討してください (おそらく依存性注入を使用して)。そうすれば、両方の機能を個別にテストできます。(とは言っても、機能がそれを保証するのに十分に複雑な場合にのみそうします。それは判断の呼びかけです。)

C# での例を次に示します。

public interface IFooFileInfoProvider
{
    FooInfo GetFooInfo(string filename);
}

public class Parser
{
    private readonly IFooFileInfoProvider _fooFileInfoProvider;

    public Parser(IFooFileInfoProvider fooFileInfoProvider)
    {
        // Add a null check
        _fooFileInfoProvider = fooFileInfoProvider;
    }

    public Foo ParseMe(string filepath)
    {
        string filename = Path.GetFileName(filepath);
        var myInfo = _fooFileInfoProvider.GetFooInfo(filename);
        return new Foo(myInfo);
    }
}

public class FooFileInfoProvider : IFooFileInfoProvider
{
    public FooInfo GetFooInfo(string filename)
    {
        // Do I/O
        return new FooInfo();  // parameters...
    }
}
于 2013-05-24T14:42:39.110 に答える