8

コードのテストに役立つ NUnit 理論を作成しました。テストされる実際のコードは、テストに使用しているデータほど重要ではありません。つまり、24 時間制の時間と分です。

機能を活用し、NUnit 2.6 Theory 機能内の制限に準拠するために、この方法でフィクスチャを作成しました。特に、データポイントが正確な型で引数に一致するという機能を回避するために、Hour や Minute などのクラスを作成する必要があると感じました。

[TestFixture]
public class TimeWindowParserTheoryFixture
{
    public class Hour
    {
        public int Value;
    }

    public class Minute
    {
        public int Value;
        public string AsString { get { return Value.ToString("00"); } }
    }

    [Datapoints]
    public IEnumerable<Hour> Hours
    {
        get
        {
            return Enumerable
                .Range(0, 25)
                .Select(v => new Hour() { Value = v })
                .Union(Enumerable.Repeat((Hour)null, 1));
        }
    }

    [Datapoints]
    public IEnumerable<Minute> Minutes
    {
        get
        {
            return Enumerable
                .Range(0, 60)
                .Select(v => new Minute() { Value = v })
                .Union(Enumerable.Repeat((Minute)null, 1));
        }
    }

    [Datapoints]
    public IEnumerable<string> Separators
    {
        get { return new[] { " ", "-" }; }
    }

    [Theory]
    public void ValidHours(Hour startHour,
        Minute startMinute,
        Hour endHour,
        Minute endMinute,
        string separator)
    {
        Assume.That(startHour != null);
        Assume.That(endHour != null);

        var parser = new TimeWindowParser();
        var startMinutesString = String.Format("{0}{1}", startMinute == null ? "" : ":", startMinute == null ? "" : startMinute.AsString);
        var endMinutesString = String.Format("{0}{1}", endMinute == null ? "" : ":", endMinute == null ? "" : endMinute.AsString);
        var pattern = String.Format("{0}{1}{2}{3}{4}{5}{6}", startHour, startMinutesString, "", separator, endHour, endMinutesString, "");
        //Console.WriteLine(pattern);
        var result = parser.Parse(pattern);
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Start, Is.EqualTo(startHour));
        Assert.That(result.End, Is.EqualTo(endHour));
    }
}

私が見つけたのは、NUnit のデフォルトの組み合わせロジックで生成されるデータ セットのサイズが非常に大きくなり、メモリが不足することです。私がテストをセットアップした方法とデータが問題になるようには思えませんが、明らかにそうであるため、この問題を別の方法で考える方法についてアドバイスを求めています。これは、取得した OutOfMemoryException スタック トレースです。

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Text.StringBuilder.ExpandByABlock(Int32 minBlockCharCount)
at System.Text.StringBuilder.Append(Char* value, Int32 valueCount)
at System.Text.StringBuilder.AppendHelper(String value)
at System.Text.StringBuilder.Append(String value)
at NUnit.Core.MethodHelper.GetDisplayName(MethodInfo method, Object[] arglist)
at NUnit.Core.Builders.NUnitTestCaseBuilder.BuildSingleTestMethod(MethodInfo method, Test parentSuite, ParameterSet parms)

この例外は、単に Test メソッドの名前を取得しようとしただけで生成されたように見えるという点で奇妙です (GetDisplayName を参照)。これがバグであるかどうかはわかりません (既知またはその他)。ところで、パラメータ化されたテストで使用される実験的ではない Range および Value 属性を使用してこのフィクスチャを書き直したときに、非常によく似た OOM 例外が発生します。

4

1 に答える 1

13

あなたの質問は理論を使用する仕組みについてですが、まず「理論の理論」について話したいと思います。その後、実装の詳細に戻ります。

理論の理論

開始する理論がある場合にのみ、理論を使用する必要があります。それ以外の場合は、Datapoints を使用して、従来のサンプル駆動型テストを推進しているだけです。「理論を持っている」とは、いくつかの入力セットに対して証明したい、真実の一般的な声明を持っていることを意味します。一般的に、理論 (コード) は可能な入力を調べて、想定に合わないものを除外します。優れた理論の例は次のとおりです。正の実数の場合、平方根を掛けると同じ数になります。」

あなたのテストを見ると、あなたの理論が証明しようとしている理論がわかりません。DataPoints を使用していることを除いて、標準のパラメーター化されたテストのように見えます。必要な唯一の前提は、議事録が null ではないということです。これは、最初に議事録を提供するため、奇妙です。

結論: これは理論の良い使い方だとは思いません。

力学

24*24*60*60*2 DataPoints を生成しています。すごいデータですね。あなたの解析アルゴリズムが 24:13 では機能するが、 24:14 では失敗すると信じる理由はありますか?

データポイントが組み合わせて使用​​されるのは事実であり、ペアで使用した方がよい場合があります。ただし、DataPoints は Theory にデータを投げる多くの方法の 1 つにすぎないことを覚えておいてください。Theories は、与えられたデータを処理する必要があるという考えです。

あなたのパーサーまたは一般的なパーサーについて適用できる理論が思い浮かばないので、これをテストとして書きます。おそらく、有効な文字列を生成したメソッドまたは単に文字列の大きな配列を指す TestCaseSourceAttribute を使用して、テストに有効なデータのみを提供します。さまざまな種類の無効なデータを処理する別のテストが必要です。

チャーリー

于 2013-11-05T01:53:20.917 に答える