การยึดมั่นกับหนึ่งยืนยันต่อการทดสอบความมั่นคงโง่ในกรณีนี้?


10

ฉันมีชั้นเรียนที่ฉันกำลังทดสอบ ชั้นเรียนมีฟังก์ชั่น:apply(List<IRule> rules, List<ITarget> targets);

ในการทดสอบหนึ่งครั้งฉันต้องการตรวจสอบให้แน่ใจว่าแต่ละเป้าหมายผ่านไปหนึ่งกฎ a:

rule1.AssertWasCalled(fnord => fnord.Test(target1));
rule1.AssertWasCalled(fnord => fnord.Test(target2));
rule1.AssertWasCalled(fnord => fnord.Test(target3));

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


ฉันเห็นพวกดาบ!
Ross Patterson

คำตอบ:


15

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

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

"กฎ" ยืนยันเดียวคือเพิ่มเติมเกี่ยวกับการยืนยันประเภทต่างๆในวิธีการเดียวกัน (เป็นหลักทดสอบสิ่งต่าง ๆ ) ซึ่งไม่ได้ใช้จริง ๆ ในกรณีนี้ที่คุณกำลังทดสอบพฤติกรรมเดียว


3
แน่นอน: กฎนั้นมีเหตุผลมากกว่าหนึ่งข้อต่อการทดสอบหน่วย คุณสามารถจัดกลุ่มสิ่งเหล่านั้นให้อยู่ในระดับที่สูงกว่าหนึ่งระดับเพื่อยืนยันว่าคุณสามารถนำมาใช้ซ้ำในการทดสอบที่แตกต่างกัน
Laurent Bourgault-Roy

5

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

ในกรณีของคุณฉันคิดว่ามันคงโอเคที่จะยืนยันสามครั้ง หากคุณต้องการทำให้โค้ดของคุณอ่านง่ายขึ้นคุณสามารถแยกการยืนยันทั้งสามออกเป็นวิธีการตั้งชื่อassertWasCalledOnTargets(...)ได้


3

สำหรับตัวอย่างเฉพาะของคุณคุณสามารถออกไปด้วยคำสั่งยืนยัน "หนึ่ง" ถ้าคุณทำสิ่งที่ชอบ:

foreach target in targets
{
     rule1.AssertWasCalled(fnord => fnord.Test(target))
}

มันเป็นสิ่งที่ฉันทำเพื่อหลีกเลี่ยงความรู้สึกผิดเกี่ยวกับการยืนยันหลายชุดในการทดสอบครั้งเดียว


ฉันเคยทำมาก่อน ไม่ใช่วิธีที่เลวร้าย อ่านง่ายและคุณสามารถเข้าใจธรรมชาติของสิ่งที่ทำ
CokoBWare

1

ฉันได้ต่อสู้กับสิ่งนี้เช่นกัน

คนเจ้าระเบียบ (ในตัวฉัน) ยืนยันในการยืนยันหนึ่งข้อต่อการทดสอบดังนั้นฉันจะรู้ได้อย่างแม่นยำว่ามีอะไรเกิดขึ้นบ้าง

จากนั้นฉันก็พบว่าตัวเองตัด / วางรหัสการตั้งค่าการทดสอบซ้ำซ้อนกันจำนวนมาก หลังจากเลเยอร์ที่สามหรือสี่ของสิ่งนี้คุณเริ่มพูดว่า "Oy! Enough!"

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


1
Assumeคุณควรตรวจสอบ ฉันเพิ่งเรียนเกี่ยวกับมันวันนี้
Wayne Werner

1

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

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

หากtarget1และtarget2เป็นการใช้งานที่แตกต่างกันของอินเทอร์เฟซเดียวกันคุณควรจะเพิ่มการทดสอบหน่วยไปยังอินเทอร์เฟซแทน (และให้กรอบการทดสอบของคุณในการสร้างการทดสอบสำหรับทุก ๆ

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