กำลังทดสอบรายการ ... ทั้งหมดในการทดสอบเดียวกันหรือหนึ่งการทดสอบสำหรับแต่ละเงื่อนไข?


21

ฉันกำลังทดสอบว่าฟังก์ชั่นทำตามที่คาดไว้ในรายการ ดังนั้นฉันต้องการทดสอบ

f(null) -> null
f(empty) -> empty
f(list with one element) -> list with one element
f(list with 2+ elements) -> list with the same number of elements, doing what expected

วิธีที่ดีที่สุดคืออะไร?

  • การทดสอบทุกกรณีในการทดสอบ (method) เดียวกันภายใต้ชื่อ "WorksAsExpected"
  • วางหนึ่งการทดสอบสำหรับแต่ละกรณีจึงมี
    • "WorksAsExpectedWhenNull"
    • "WorksAsExpectedWhenEmpty"
    • "WorksAsExpectedWhenSingleElement"
    • "WorksAsExpectedWhenMoreElements"
  • อีกทางเลือกหนึ่งที่ฉันไม่ได้คิด :-)


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

5
หากคุณเขียนการทดสอบของคุณในรูปแบบที่กำหนด ... เมื่อ ... รูปแบบจากนั้นจะปรากฏชัดเจนว่าพวกเขาควรได้รับการทดสอบแยกต่างหาก ...
Robbie Dee

1
ฉันต้องการเพิ่ม: IMO เป็นการดีที่จะแยกกรณีขอบ (เช่นว่างและว่างเปล่า) เป็นการทดสอบแยกต่างหากเพราะสิ่งเหล่านี้มักจะเกี่ยวข้องกับตรรกะกรณีพิเศษในการใช้งานที่แตกต่างกันและหากการทดสอบเหล่านี้ล้มเหลวพวกเขาจะระบุอย่างชัดเจน วิธีการที่รหัสภายใต้การทดสอบล้มเหลว (คุณไม่ต้องขุดลึกลงไปหรือแก้จุดบกพร่องกรณีทดสอบเพื่อดูว่าเกิดอะไรขึ้น)
Filip Milovanović

1
แสดงรายการที่มีองค์ประกอบซ้ำกันหรือไม่
atayenel

คำตอบ:


30

กฎง่ายๆที่ฉันใช้เพื่อว่าจะทำการทดสอบในหนึ่งกรณีการทดสอบหรือมากเป็น: มันเกี่ยวข้องกับการตั้งค่าเพียงหนึ่ง?

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

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

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


14

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

เครื่องมือที่เป็นไปได้ตามกรอบงานของคุณ:

  • ทฤษฎี ทฤษฎีช่วยให้คุณทดสอบข้อเท็จจริงต่างๆเกี่ยวกับชุดข้อมูล เฟรมเวิร์กจะฟีดการทดสอบของคุณด้วยสถานการณ์ข้อมูลการทดสอบที่หลากหลาย - โดยฟิลด์หรือโดยวิธีสแตติกที่สร้างข้อมูล หากบางส่วนของข้อเท็จจริงของคุณนำไปใช้ขึ้นอยู่กับปัจจัยพื้นฐานบางอย่างและคนอื่นทำไม่ได้กรอบเหล่านี้นำเสนอแนวคิดของนั้นสมมติฐาน คุณAssume.that()เพียงแค่ข้ามการทดสอบสำหรับข้อมูลถ้ามันล้มเหลวสิ่งที่จำเป็น สิ่งนี้ช่วยให้คุณกำหนด "ทำงานได้ตามที่คาดหวัง" จากนั้นป้อนข้อมูลจำนวนมาก เมื่อคุณดูผลลัพธ์คุณมีรายการสำหรับการทดสอบพาเรนต์แล้วรายการย่อยสำหรับข้อมูลแต่ละชิ้น
  • การทดสอบ parameterized การทดสอบแบบ Parameterized เป็นตัวตั้งต้นของทฤษฎีดังนั้นอาจไม่มีการตรวจสอบเงื่อนไขเบื้องต้นที่คุณสามารถทำได้กับทฤษฎี ผลลัพธ์ที่ได้ก็เหมือนกัน คุณดูผลลัพธ์คุณมีรายการผู้ปกครองสำหรับการทดสอบตัวเองแล้วรายการที่เฉพาะเจาะจงสำหรับแต่ละจุดข้อมูล
  • การทดสอบหนึ่งที่มีหลายอ้าง ใช้เวลาน้อยลงในการตั้งค่า แต่คุณจะพบปัญหาการเปิดเผยครั้งละน้อย หากการทดสอบยาวเกินไปและมีการทดสอบสถานการณ์ที่แตกต่างกันมากเกินไปมีความเสี่ยงใหญ่สองประการ: จะใช้เวลาในการรันนานและทีมของคุณจะเบื่อกับมันและปิดการทดสอบ
  • การทดสอบหลายกับการดำเนินการที่คล้ายกัน สิ่งสำคัญคือต้องทราบว่าหากการยืนยันแตกต่างกันการทดสอบจะไม่ทับซ้อนกัน อย่างไรก็ตามนี่จะเป็นภูมิปัญญาดั้งเดิมของทีมที่มุ่งเน้น TDD

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

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


5

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

พยายามหลีกเลี่ยงการแยกแยะด้วยการวนซ้ำในกรณีทดสอบหนึ่งกรณีเพราะทำให้ยากต่อการพิจารณาว่าชุดข้อมูลใดที่ทำให้เกิดข้อผิดพลาด

ใน TDD red – green – refactor cycle ของคุณคุณควรเพิ่มชุดข้อมูลตัวอย่างทีละชุด การรวมกรณีทดสอบหลายรายการเข้ากับการทดสอบแบบมีพารามิเตอร์จะเป็นส่วนหนึ่งของขั้นตอนการปรับสภาพใหม่

วิธีการที่แตกต่างกันค่อนข้างเป็นการทดสอบคุณสมบัติ คุณจะสร้างการทดสอบต่างๆ (parametrized) ที่ยืนยันคุณสมบัติต่างๆของฟังก์ชั่นของคุณโดยไม่ต้องระบุข้อมูลอินพุตที่เป็นรูปธรรม เช่นคุณสมบัติอาจเป็น: สำหรับรายการทั้งหมดรายการxsนั้นys = f(xs)มีความยาวเท่าxsกัน กรอบการทดสอบจะสร้างรายการที่น่าสนใจและรายการแบบสุ่มและยืนยันว่าคุณสมบัติของคุณมีไว้สำหรับพวกเขาทั้งหมด สิ่งนี้จะย้ายไปจากการระบุตัวอย่างด้วยตนเองเนื่องจากการเลือกตัวอย่างด้วยตนเองอาจทำให้เกิดกรณีขอบที่น่าสนใจ


ไม่ควร "พลาด" ในประโยคสุดท้ายเป็น "ค้นหา"?
Robbie Dee

@RobbieDee English ไม่ชัดเจนแก้ไขได้
amon

3

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

ดูโพสต์นี้: มีการยืนยันหลายชุดในการทดสอบหน่วยเดียวหรือไม่? . มีการอภิปรายที่เกี่ยวข้องและมีรายละเอียดที่นั่นเช่นกัน:

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

[ ... ]

การทดสอบควรล้มเหลวด้วยเหตุผลเดียวเท่านั้น แต่นั่นไม่ได้หมายความว่าควรมีคำสั่ง Assert เพียงคำเดียวเท่านั้น IMHO มันสำคัญกว่าที่จะถือเป็นรูปแบบ "การจัดเรียงการกระทำการยืนยัน"

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


0

ในความคิดของฉันมันขึ้นอยู่กับเงื่อนไขการทดสอบ

  • หากการทดสอบของคุณมีเพียง 1 เงื่อนไขในการตั้งค่าการทดสอบ แต่มีผลข้างเคียงมากมาย multi-assert เป็นที่ยอมรับ
  • แต่เมื่อคุณมีหลายเงื่อนไขหมายความว่าคุณมีหลายกรณีทดสอบแต่ละกรณีควรได้รับการคุ้มครองโดยการทดสอบ 1 หน่วยเท่านั้น

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