การทดสอบหน่วย: การยืนยันที่ถูกเลื่อนออกไปด้วย Linq


18

ตกลงหรือไม่ที่จะเพิ่มการยืนยันที่ถูกเลื่อนออกไปเช่นนี้

var actualKittens = actualKittens.Select(kitten => {
    Assert.IsСute(kitten);
    return kitten
});

ทำไม? ดังนั้นฉันสามารถทำซ้ำได้เพียงครั้งเดียวแม้จะมีข้อความที่คาดว่าจะเกิดการรวบรวมที่เป็นรูปธรรมเช่น:

CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

และมันอาจจะไม่ใช่แค่เลือก แต่เป็นวิธีที่กำหนดตัววนซ้ำและมีการตรวจสอบและตรรกะจำนวนมาก (เช่นการนับและการกรอง)

สิ่งที่สงสัยคือความซับซ้อนของการอ่านและการดีบักรหัสดังกล่าวในกรณีที่การทดสอบล้มเหลว


1
ฉันจะไม่ไว้ใจสิ่งนี้เพื่อการทดสอบ แต่บางครั้งมันก็โอเคที่จะทำสิ่งนี้ในรหัสการผลิตถ้าไม่มีวิธีแก้ปัญหาที่ดีกว่า คุณสามารถทำให้ตัวเองเป็นผู้ช่วยที่sequence.WithSideEffect(item => Assert.IsCute(item))จะทำให้มันสะอาดขึ้น
usr

@usr ดูเหมือนว่าคุณจะจับข้อบกพร่องที่สำคัญของวิธีดังกล่าว - ผลข้างเคียงจาก iterator
SerG

คุณยังไม่ต้องวนซ้ำสองครั้งเพื่อสร้างรายการและเปรียบเทียบอีกครั้งexpectedKittensหรือไม่ คุณเพิ่งซ่อนการวนซ้ำหลังการเรียกใช้เมธอด
IllusiveBrian

@IllusiveBrian ในแง่นี้ในตัวอย่างใช่ .All()ก็ยังคงน้อยกว่าที่มีการเพิ่มเติม
SerG

คำตอบ:


37

ตกลงหรือไม่ที่จะเพิ่มการยืนยันที่ถูกเลื่อนออกไปเช่นนี้ [.. ]

ไม่มันไม่ใช่ ทำไม? เพราะถ้าคุณเอาเหตุผลที่สองออกมาการทดสอบก็จะเปลี่ยนเป็นสีเขียวและคุณคิดว่ามันยังใช้งานได้ แต่ก็ไม่ได้ผลเพราะคอลเลกชันจะไม่ได้รับการแจกแจง หากคุณมีการยืนยันอิสระสองหรือมากกว่านั้นพวกเขาจะทำงานต่อไปแม้ว่าคุณจะปิดการใช้งานอย่างใดอย่างหนึ่ง

พิจารณาชุดค่าผสมนี้:

Assert.IsTrue(actualKittens.All(x => x.IsCute());
CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

ตอนนี้แม้ว่าคุณจะปิดการใช้งานหรือลบหนึ่งในการยืนยันอื่น ๆ ที่จะยังคงทำงานของมัน นอกจากนี้หากคุณลืมที่จะเก็บรวบรวมคอลเลกชันที่เป็นรูปธรรมอาจใช้เวลานานกว่า แต่มันจะยังใช้งานได้ การทดสอบอิสระนั้นแข็งแกร่งและเชื่อถือได้มากขึ้น

นอกจากนี้ยังมีสองไม่มี ฉันไม่แน่ใจว่าเฟรมเวิร์กอื่นจัดการอย่างไร แต่ถ้าคุณใช้แพลตฟอร์มทดสอบ MS คุณจะไม่ทราบว่าการทดสอบใดล้มเหลว หากคุณคลิกสองครั้งที่การทดสอบที่ล้มเหลวมันจะแสดงCollectionAssertว่าล้มเหลว แต่ในความเป็นจริงมันซ้อนกันAssertที่ผิดพลาดและมันจะยากมากในการดีบัก นี่คือตัวอย่าง:

    [TestMethod]
    public void TestMethod()
    {
        var numbers = new[] { 1, 2, 3 }.Select(x =>
        {
            Assert.Fail("Wrong number.");
            return x;
        });

        // This will fail and you won't be sure why.
        CollectionAssert.AreEqual(new[] { 1, 2, 3 }, numbers.ToList()); 

    }

ซึ่งหมายความว่าการทดสอบครั้งแรกนั้นไร้ประโยชน์จริง ๆ เพราะไม่ช่วยในการค้นหาข้อบกพร่อง คุณไม่ทราบว่ามันล้มเหลวเพราะหมายเลขไม่ถูกต้องหรือเพราะทั้งสองคอลเลกชันนั้นแตกต่างกัน


ทำไม? ดังนั้นฉันสามารถทำซ้ำได้เพียงครั้งเดียวแม้จะมีข้อความที่คาดว่าจะเกิดการรวบรวมที่เป็นรูปธรรม

ฉันสงสัยว่าทำไมคุณถึงสนใจ นี่คือการทดสอบหน่วย คุณไม่จำเป็นต้องปรับให้เหมาะสมทุกบิตและโดยปกติแล้วการทดสอบไม่จำเป็นต้องมีรายการนับล้านดังนั้นประสิทธิภาพจึงไม่ควรเป็นปัญหา

คุณจะต้องรักษาการทดสอบดังกล่าวดังนั้นทำไมคุณควรทำให้มันซับซ้อนกว่านั้นจึงจำเป็น? เขียนข้อความง่ายๆที่ใช้งานได้


หากด้วยเหตุผลบางอย่างการยืนยันจำเป็นต้องถูกฝังในโฟลว์ควบคุมวิธีหนึ่งเพื่อให้แน่ใจว่าถูกดำเนินการแล้วคือการรักษาตัวนับ / แฟล็กที่เพิ่ม / ตั้งค่าเป็นจริงก่อนการยืนยันแบบซ้อน ต่อมาเราสามารถยืนยันได้ว่ามีการควบคุมโฟลว์ที่คาดหวังไว้โดยการตรวจสอบตัวนับนี้ ไม่สมบูรณ์แบบ แต่ส่วนใหญ่เน้นคำวิจารณ์แรกของคุณ
amon

1
นอกจากนี้คุณหรือคนอื่นจะกลับมาที่การรอการยืนยันที่ถูกเลื่อนออกไปในเวลา 6 เดือนและต้องเสียเวลาคิดออก
DavidTheWin

มีบางอย่างผิดปกติกับตัวอย่างของคุณ การโทรToListจะย้ำสิ่งที่นับได้หรือไม่
RubberDuck

1
@RubberDuck ใช่มันจะและก็จะล้มเหลว แต่ไม่ได้อยู่ที่Assert.Failแต่ที่CollectionAssertและคุณจะไม่สามารถพูดได้ว่าการยืนยันที่ผิดพลาดจริง ๆ ฉันหมายถึง VS จะไม่เน้นAssert.Failแต่อีกอัน ... ตอนนี้คุณสามารถแก้ไขข้อบกพร่องได้
t3chb0t
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.