ユニットテストで同等の二重値を適切に比較するにはどうすればよいですか?


20

私は最近、時系列が本質的にある時系列モジュールを設計しましたSortedDictionnary<DateTime, double>

次に、このモジュールが常に機能し、期待どおりの結果が得られることを確認するための単体テストを作成します。

一般的な操作は、時系列のポイント間のパフォーマンスを計算することです。

したがって、私が行うことは、たとえば{1.0、2.0、4.0}(いくつかの日付)で時系列を作成することであり、結果は{100%、100%}になると予想しています。

問題は、値{1.0、1.0}を使用して時系列を手動で作成し、(各ポイントを比較することにより)等しいかどうかを確認すると、実数のバイナリ表現で作業するときは常に不正確になるため、テストは合格しません数字。

したがって、次の関数を作成することにしました。

private static bool isCloseEnough(double expected, double actual, double tolerance=0.002)
{
    return squaredDifference(expected, actual) < Math.Pow(tolerance,2);
}

そのような場合に対処する別の一般的な方法はありますか?

回答:


10

この問題に対処する他の2つの方法を考えることができます。

以下を使用できますIs.InRange

Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));

以下を使用できますMath.Round

Assert.That(Math.Round(result, sigDigits), Is.EqualTo(expected));

読者は期待値と比較される前にあなたの番号で何が起こっているかを正確に見ることができるので、両方の方法は専用の機能よりも表現力があると思います。


2
この回答はNUnit固有であり、「制約ベース」のアサーションモデルを示していることに注意してください。古典的なアサーションモデルは次のようになります。Assert.AreEqual(expected、actual、tolerance);
リチャードM

1
@RichardM:それを回答として投稿し、それを受け入れることを選択します。
SRKX

@dasblinkenlightによる答えは正しいです。詳細を追加するだけです(明確でない場合があるため-古典的なアサーションモデルもNUnitです)。他のテストフレームワーク(MSTestではない)には、浮動小数点値を処理する独自のアサートモデルがある可能性があります。
リチャードM

1
Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));失敗した場合tolerance/abs(expected) < 1E-16
quant_dev

@quant_devあなたは絶対に正しいです。OPは利益率をパーセンテージとして計算することについて話しているので、私はそれabs(expected)が1桁から2桁になると仮定しました。また、1E-9付近の許容値を仮定しました。これらの仮定の下で、この明らかに単純なアプローチは、合理的に十分に役立つ可能性があります(Is.InRangeテストで使用します)。
-dasblinkenlight


3

数字で何をするかによります。たとえば、いくつかの基準に基づいて入力セットから適切な値を選択することになっているメソッドをテストする場合は、厳密な同等性をテストする必要があります。浮動小数点計算を行う場合、通常、ゼロ以外の許容誤差でテストする必要があります。許容値の大きさは計算に依存しますが、倍精度では、単純な計算には1E-14 相対許容値を、より複雑な計算には1E-8(許容値)を選択するのが適切な出発点です。もちろんYMMVであり、期待される結果が0の場合は、小さな絶対許容値を追加する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.