คุณจะเขียนกรณีทดสอบหน่วยได้อย่างไร


14

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

แนวโน้มปกติคืออะไร? นักพัฒนาควรจะเขียนกรณีทดสอบหน่วยสำหรับรหัสที่พวกเขาเขียนเอง?


2
"อาศัย"? "อาศัย" หมายถึงอะไร?
S.Lott

คำตอบ:


12

ลองอ่านบล็อกโพสต์นี้: การเขียนที่ดีหน่วย: ที่ดีที่สุดและการปฏิบัติที่เลวร้ายที่สุด

แต่มีคนอื่นอีกนับไม่ถ้วนบนเว็บ

ตอบคำถามของคุณโดยตรง ...

  1. "แนวโน้มปกติ" - ฉันเดาว่าสิ่งนี้อาจแตกต่างกันไปในแต่ละสถานที่สิ่งที่ปกติสำหรับฉันอาจแปลกสำหรับผู้อื่น
  2. ฉันจะบอกว่า (ในตัวเลือกของฉัน) นักพัฒนาที่เขียนรหัสควรเขียนแบบทดสอบโดยใช้วิธีเช่น TDD ซึ่งคุณจะต้องเขียนแบบทดสอบก่อนรหัส แต่คนอื่นอาจมีวิธีการและความคิดที่แตกต่างกันที่นี่!

และวิธีที่คุณอธิบายการเขียนแบบทดสอบ (ในคำถามของคุณ) นั้นผิดทั้งหมด !!


9

วิธีการนี้ทำให้การทดสอบหน่วยไม่มีราคา

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


8
สิ่งนี้ไม่เป็นความจริงเลย หรือค่อนข้างเป็นเรื่องจริงในโลกอุดมคติ แต่อนิจจาบ่อยครั้งที่เราอยู่ห่างไกลจากสิ่งนั้น พิจารณาการมีรหัสดั้งเดิมโดยไม่ต้องทดสอบและไม่มีข้อกำหนดและไม่มีใครที่สามารถบอกรายละเอียดของคุณได้อย่างน่าเชื่อถือว่าสิ่งใดที่ควรระบุรหัสที่แน่นอน (นี่คือความเป็นจริงในโครงการขนาดใหญ่ที่มีอยู่) แม้ในกรณีนี้มันอาจจะคุ้มค่าที่จะเขียนการทดสอบหน่วยเพื่อล็อคสถานะปัจจุบันของรหัสและเพื่อให้แน่ใจว่าคุณจะไม่ทำลายสิ่งใดด้วยการเปลี่ยนโครงสร้างในอนาคตการแก้ไขข้อบกพร่องหรือส่วนขยาย
PéterTörök

2
นอกจากนี้ฉันคิดว่าคุณหมายถึง "เขียนการทดสอบหลังจากรหัสเพื่อทดสอบ" คุณ?
PéterTörök

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

ใช่, ถ้าคุณหมายความว่าเราต้องมีการยืนยันที่มีความหมายในการทดสอบหน่วยของเรา, เพื่อตรวจสอบว่ารหัสที่ทดสอบจริง ๆ แล้วทำในสิ่งที่เราคิดว่าเป็นเช่นนั้น, ฉันเห็นด้วยอย่างเต็มที่.
PéterTörök

3

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


3

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

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

สมมติว่าคุณมีวิธีที่คำนวณสแควร์รูทของจำนวนจุดลอยตัว ใน Java อินเตอร์เฟสจะนิยามเป็น:

public double squareRoot(double number);

ไม่สำคัญว่าคุณจะเขียนการนำไปใช้หรือว่ามีคนอื่นทำคุณต้องการยืนยันคุณสมบัติบางอย่างของ squareRoot:

  1. สามารถคืนค่ารูตแบบง่ายๆเช่น sqrt (4.0)
  2. สามารถหารูทจริงเช่น sqrt (2.0) ได้อย่างแม่นยำ
  3. พบว่า sqrt (0.0) เท่ากับ 0.0
  4. มันจะโยน IllegalArgumentException เมื่อป้อนจำนวนลบเช่นบน sqrt (-1.0)

ดังนั้นคุณเริ่มเขียนสิ่งเหล่านี้เป็นแบบทดสอบรายบุคคล:

@Test
public void canFindSimpleRoot() {
  assertEquals(2, squareRoot(4), epsilon);
}

โอ๊ะการทดสอบนี้ล้มเหลวแล้ว:

java.lang.AssertionError: Use assertEquals(expected, actual, delta) to compare floating-point numbers

คุณลืมเลขคณิตจุดลอยตัว ตกลงคุณแนะนำdouble epsilon=0.01และไปที่:

@Test
public void canFindSimpleRootToEpsilonPrecision() {
  assertEquals(2, squareRoot(4), epsilon);
}

และเพิ่มการทดสอบอื่น ๆ : ในที่สุด

@Test
@ExpectedException(IllegalArgumentException.class)
public void throwsExceptionOnNegativeInput() {
  assertEquals(-1, squareRoot(-1), epsilon);
}

และอุ๊ปส์อีกครั้ง:

java.lang.AssertionError: expected:<-1.0> but was:<NaN>

คุณควรทดสอบ:

@Test
public void returnsNaNOnNegativeInput() {
  assertEquals(Double.NaN, squareRoot(-1), epsilon);
}

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

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

@Test
public void throwsNoExceptionOnNegativeInput() {
  assertNotNull(squareRoot(-1)); // Shouldn't this fail?
}

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

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


1

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

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


1

ดูเหมือนว่าคุณกำลังทำงานกับนักพัฒนาคนอื่น ๆ (หรือการบำรุงรักษาโค้ดที่เขียนโดยนักพัฒนารายอื่น) ซึ่งไม่ทำการทดสอบหน่วย ในกรณีนี้ฉันคิดว่าคุณต้องการทราบอย่างแน่นอนว่าวัตถุหรือวิธีการทดสอบที่คุณควรทำคืออะไรจากนั้นสร้างการทดสอบ

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

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