ฉันจะเปรียบเทียบค่าสองเท่าเพื่อความเท่าเทียมในการทดสอบหน่วยได้อย่างไร


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

ฉันสามารถคิดถึงวิธีอื่นสองวิธีในการจัดการกับปัญหานี้:

คุณสามารถใช้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 (คาดว่าจะเกิดขึ้นจริงอดทน);
RichardM

1
@RichardM: โพสต์นั้นเป็นคำตอบและฉันจะเลือกให้ยอมรับมัน
SRKX

คำตอบโดย @dasblinkenlight ถูกต้องเพียงแค่เพิ่มรายละเอียด (เนื่องจากอาจไม่ชัดเจน - โมเดลการยืนยันแบบคลาสสิกคือ NUnit) กรอบการทดสอบอื่น ๆ (ไม่ใช่ MSTest) น่าจะมีรูปแบบการยืนยันของตัวเองเพื่อจัดการกับค่าทศนิยม
RichardM

1
Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));tolerance/abs(expected) < 1E-16จะล้มเหลวถ้า
quant_dev

@quant_dev คุณพูดถูก เนื่องจาก OP พูดคุยเกี่ยวกับการคำนวณผลตอบแทนเป็นเปอร์เซ็นต์ฉันจึงสันนิษฐานว่าabs(expected)เป็นตัวเลขหลักเดียวถึงสองหลัก ฉันยังถือว่าความอดทนในบริเวณใกล้เคียงของ 1E-9 ภายใต้สมมติฐานเหล่านี้วิธีการที่เรียบง่ายซึ่งเป็นที่ยอมรับนี้สามารถให้บริการคุณได้ดีพอสมควร (ฉันใช้Is.InRangeในการทดสอบ)
dasblinkenlight


3

มันขึ้นอยู่กับสิ่งที่คุณทำกับตัวเลข หากคุณกำลังทดสอบวิธีที่ควรจะเป็นเช่นเลือกค่าที่เหมาะสมจากชุดอินพุตตามเกณฑ์บางอย่างคุณควรทดสอบความเท่าเทียมกันอย่างเข้มงวด หากคุณทำการคำนวณจุดลอยตัวโดยปกติคุณจะต้องทดสอบด้วยความอดทนที่ไม่เป็นศูนย์ ความอดทนใหญ่ขึ้นอยู่กับการคำนวณ แต่ด้วยความแม่นยำสองเท่าจุดเริ่มต้นที่ดีคือการเลือกความอดทนสัมพัทธ์ 1E-14 สำหรับการคำนวณอย่างง่ายและ 1E-8 (ความทนทาน) สำหรับความซับซ้อนมากขึ้น แน่นอนว่า YMMV และคุณต้องเพิ่มความอดทนแบบสัมบูรณ์เล็กน้อยหากผลลัพธ์ที่คาดหวังคือ 0

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.