Birim testinde eşitlik için çift değerleri nasıl düzgün bir şekilde karşılaştırabilirim?


20

Geçenlerde zaman serilerimin esasen a olduğu bir zaman serisi modülü tasarladım SortedDictionnary<DateTime, double>.

Şimdi bu modülün her zaman çalıştığından ve beklenen sonucu ürettiğinden emin olmak için birim testleri oluşturmak istiyorum.

Yaygın bir işlem, zaman serisindeki noktalar arasındaki performansı hesaplamaktır.

Yaptığım şey, {1.0, 2.0, 4.0} (bazı tarihlerde) ile bir zaman serisi oluşturmak ve sonucun {% 100,% 100} olmasını bekliyorum.

Mesele şu ki, el ile {1.0, 1.0} değerleriyle bir zaman dizisi oluşturursam ve eşitliği kontrol edersem (her noktayı karşılaştırarak), test geçemez, çünkü gerçek ikili gösterimlerle çalışırken her zaman yanlışlıklar olacaktır sayılar.

Bu nedenle, aşağıdaki işlevi oluşturmaya karar verdim:

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

Böyle bir durumla baş etmenin başka bir yaygın yolu var mı?

Yanıtlar:


10

Bu sorunla başa çıkmanın iki yolunu daha düşünebilirim:

Şunları kullanabilirsiniz Is.InRange:

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

Şunları kullanabilirsiniz Math.Round:

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

Her iki yolun da özel bir fonksiyondan daha etkileyici olduğunu düşünüyorum, çünkü okuyucu, beklenen değere kıyasla, numaranızda neler olup bittiğini tam olarak görebiliyor.


2
Bu cevabın NUnit'e özgü olduğunu ve "Kısıtlamaya dayalı" iddia modelini sergilediğini unutmayın. Klasik iddia modeli şöyle görünecektir: Assert.AreEqual (beklenen, gerçek, tolerans);
RichardM

1
@RichardM: Bunu bir cevap olarak gönderin ve kabul edeceğini seçeceğim.
SRKX

@Dasblinkenlight'ın cevabı doğrudur, sadece biraz ayrıntı ekler (açık olmayabilir çünkü klasik iddia modeli de NUnit'tir). Diğer test çerçeveleri (MSTest değil) muhtemelen kayan nokta değerleriyle başa çıkmak için kendi onay modeline sahiptir.
RichardM

1
Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));başarısız olursa tolerance/abs(expected) < 1E-16.
quant_dev

@quant_dev Kesinlikle haklısın. OP, getirileri yüzde olarak hesaplamaktan bahsettiğinden, abs(expected)bunun tek ila çift haneli olacağını varsaydım . Ayrıca toleransı 1E-9 civarında kabul ettim. Bu varsayımlar altında, kuşkusuz bu basit yaklaşım size oldukça iyi hizmet edebilir ( Is.InRangetestlerimde kullanıyorum).
dasblinkenlight


3

Sayılarla ne yaptığınıza bağlıdır. Örneğin, bazı ölçütlere göre bir girdi kümesinden uygun bir değer seçmesi gereken bir yöntemi test ediyorsanız, katı eşitliği test etmeniz gerekir. Kayan nokta hesaplamaları yapıyorsanız, genellikle sıfır olmayan bir toleransla test etmeniz gerekir. Toleransın ne kadar büyük olduğu hesaplamalara bağlıdır, ancak çift hassasiyetle iyi bir başlangıç ​​noktası, basit hesaplamalar için 1E-14 bağıl toleransı ve daha karmaşık olanlar için 1E-8'i (tolerans) seçmektir . Tabii ki YMMV ve beklenen sonuç 0 ise, küçük bir mutlak tolerans eklemeniz gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.