การทดสอบหน่วยใน Django


12

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

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

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()

    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.key_method(startTime, endTime) for object in objects)

วิธีใดวิธีหนึ่งในการทดสอบบางอย่างเช่นนี้

ที่นี่ฉันอยู่ไกล เกิดขึ้นกับฉันว่าวัตถุประสงค์การทดสอบหน่วยควรได้รับพฤติกรรมเยาะเย้ยby key_methodบนข้อโต้แย้งของมันคือการsummaryกรอง / รวมอย่างถูกต้องเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง?

การเยาะเย้ย datetime.now () ตรงไปตรงมาเพียงพอ แต่ฉันจะเยาะเย้ยส่วนที่เหลือของพฤติกรรมได้อย่างไร

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

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


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

2
นั่นเป็นประโยชน์ แต่ไม่ได้แก้ไขปัญหาของวิธีการทดสอบแอปพลิเคชันแบบ ORM ที่หนักหน่วงที่สุด
acjay

คุณต้องแยกชั้นความเพียรออกไป
Chedy2149

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

ชำระเงินนี้: vimeo.com/43612849และสิ่งนี้: vimeo.com/15007792
Chedy2149

คำตอบ:


6

ฉันจะไปข้างหน้าและลงทะเบียนคำตอบสำหรับสิ่งที่ฉันเกิดขึ้นด้วย

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

นี่คือสิ่งที่กรณีทดสอบของฉันดูเหมือนประมาณใช้ห้องสมุดมาตรฐานจำลอง:

  1. ฉันใช้ ORM มาตรฐานเพื่อตั้งค่าลำดับเหตุการณ์
  2. ฉันสร้างการเริ่มต้นdatetimeและล้มล้างauto_now_addเวลาเพื่อให้พอดีกับช่วงเวลาที่แน่นอนของการออกแบบของฉัน ฉันคิดว่า ORM ไม่อนุญาตสิ่งนี้ แต่ใช้งานได้ดี
  3. ฉันแน่ใจว่าฟังก์ชั่นการทดสอบภายใต้ใช้from datetime import datetimeเพื่อให้ฉันสามารถแก้ไขdatetime.now()ในฟังก์ชั่นนั้น (ถ้าฉันเยาะเย้ยทั้งdatetimeชั้นเรียน, ORM โหมโรงพอดี)
  4. ฉันสร้างการแทนที่ของตัวเองobject.key_method()ด้วยฟังก์ชันที่เรียบง่าย แต่ได้รับการกำหนดไว้อย่างดีซึ่งขึ้นอยู่กับข้อโต้แย้ง ฉันต้องการให้มันขึ้นอยู่กับข้อโต้แย้งเพราะมิฉะนั้นฉันอาจไม่ทราบว่าตรรกะของฟังก์ชั่นภายใต้การทดสอบทำงานได้หรือไม่ ในกรณีของฉันมันก็ส่งกลับจำนวนวินาทีระหว่างและstartTime endTimeผมแก้ไขในห่อไว้ในแลมบ์ดาและปะโดยตรงในการobject.key_method()ใช้new_callablekwarg patchของ
  5. ในที่สุดฉันก็ใช้ชุดของการยืนยันในการเรียกที่summaryแตกต่างกันของที่มีข้อโต้แย้งที่แตกต่างกันเพื่อตรวจสอบความเท่าเทียมกันกับบัญชีผลการคำนวณด้วยมือที่คาดไว้สำหรับพฤติกรรมที่กำหนดของการเยาะเย้ยkey_method

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

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

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