Python - doctest vs. unittest [ปิด]


160

ฉันพยายามเริ่มต้นด้วยการทดสอบหน่วยใน Python และฉันสงสัยว่าใครบางคนสามารถอธิบายข้อดีและข้อเสียของ doctest และ unittest

คุณจะใช้เงื่อนไขอะไรในแต่ละเงื่อนไข

คำตอบ:


177

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

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

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


29
มีจำนวนแผ่นหม้อน้ำน้อยกว่ามากและฉันพบว่าการทดสอบง่ายกว่ามากในการเขียน (และอ่าน) ค่าใช้จ่ายในการเริ่มต้นที่ต่ำในการเขียนการทดสอบ (เช่นเพียงแค่เขียนฟังก์ชั่น "test_foo ()" และไป) ยังช่วยต่อสู้กับสิ่งล่อใจที่จะทำบิตรหัสที่น่าสนใจก่อนที่จะทำการทดสอบของคุณ
Brian

6
ฉันคิดว่านี่เป็นคำตอบที่ยอดเยี่ยม
James Brady

คุณใช้กรอบการทดสอบอื่นใด หรือว่าเป็นจมูกโดยเฉพาะ?
โจ

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

1
FYI จมูกอยู่ใน "โหมดการบำรุงรักษา" เป็นเวลาหลายปีที่ผ่านมาและมีแนวโน้มที่จะหยุดการพัฒนาทั้งหมด (ไม่มีการแทรกแซงจากบุคคลที่สาม) ผู้ดูแลรักษาแนะนำโครงการใหม่ให้ใช้ทางเลือก
หก

48

ฉันใช้ไม่ได้มากที่สุด

นาน ๆ ครั้งฉันจะใส่บางสิ่งใน docstring ที่สามารถใช้ได้โดย doctest

95% ของกรณีทดสอบไม่ได้ทดสอบ

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


คงจะเจ๋งเมื่อเห็นตัวอย่างสิ่งที่คุณคิดว่าเหมาะสมdocstringและอะไรไม่ ฉันชอบ docstring ในระยะที่มันแสดงให้เห็นอย่างชัดเจนถึงวิธีการใช้อินเทอร์เฟซ แต่การใช้ทั้งสำหรับการทดสอบนั้นและการทดสอบหน่วยอาจไม่เหมาะสม
user1767754

33

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


6
1 จากฉัน - จุดที่ยอดเยี่ยม
ดั๊ก

28

ฉันทำงานเป็นชีวสารสนเทศศาสตร์และโค้ดส่วนใหญ่ที่ฉันเขียนคือ "หนึ่งครั้งหนึ่งงาน" สคริปต์รหัสที่จะทำงานเพียงครั้งเดียวหรือสองครั้งและเรียกใช้งานที่เฉพาะเจาะจงเพียงครั้งเดียว

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

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

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


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

14

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

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


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

7

ฉันใช้สิ่งที่ไม่สำคัญ ฉันคิดว่ากลุ่มที่สอนหลักคำสอนขึ้นโมดูลมากเกินไป นี่อาจเกี่ยวกับการเขียนการทดสอบอย่างละเอียด


7

การใช้ทั้งคู่เป็นตัวเลือกที่ถูกต้องและค่อนข้างง่าย doctestโมดูลให้DoctTestSuiteและDocFileSuiteวิธีการที่สร้าง TestSuite UnitTest ได้จากโมดูลหรือแฟ้มตามลำดับ

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

แต่สำหรับกรณีที่ซับซ้อนมากขึ้นและสำหรับชุดทดสอบที่ครอบคลุมมากขึ้นฉันใช้ unittest ซึ่งให้การควบคุมและความยืดหยุ่นที่มากขึ้น


7

ฉันไม่ได้ใช้ doctest เป็นสิ่งทดแทนสำหรับ unittest แม้ว่ามันจะทับซ้อนกันเล็กน้อย แต่โมดูลทั้งสองก็ไม่มีฟังก์ชั่นเหมือนกัน:

  • ฉันใช้unittestเป็นกรอบการทดสอบหน่วยซึ่งหมายความว่ามันช่วยให้ฉันสามารถตรวจสอบผลกระทบของการดัดแปลงใด ๆ ในส่วนที่เหลือของรหัสได้อย่างรวดเร็ว

  • ฉันใช้doctestเป็นหลักประกันว่าข้อคิดเห็น (คือเอกสาร) ยังคงเกี่ยวข้องกับรหัสรุ่นปัจจุบัน

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


4

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


4

Doctestบางครั้งอาจนำไปสู่ผลลัพธ์ที่ผิด โดยเฉพาะอย่างยิ่งเมื่อเอาต์พุตมีลำดับ escape ตัวอย่างเช่น

def convert():
    """
    >>> convert()
    '\xe0\xa4\x95'
    """
    a = '\xe0\xa4\x95'
    return a
import doctest
doctest.testmod()

จะช่วยให้

**********************************************************************
File "hindi.py", line 3, in __main__.convert
Failed example:
    convert()
Expected:
    'क'
Got:
    '\xe0\xa4\x95'
**********************************************************************
1 items had failures:
   1 of   1 in __main__.convert
***Test Failed*** 1 failures. 

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


5
คุณสามารถใช้ raw docstrings ( r""" ... """) เพื่อแก้ไขปัญหาแรก
icktoofay

ทำงานได้ดีใน Python 3.4 เพื่อให้ทำงานใน Python 2.7 เช่นกันใช้'\\xe0\\xa4\\x95'ใน docstring ของคุณ
Cees Timmerman

ฉันยังพบว่าตัวอักษร unicode ยังใช้งานไม่ได้กับ doctests (แม้แต่บรรทัดความคิดเห็น 'coding utf-8' ที่ถูกต้องที่ด้านบนของไฟล์โดยทั่วไป doctests ไม่ได้รับการสนับสนุนเช่นเดียวกับการทดสอบที่ไม่เกี่ยวข้องดังนั้นจึงมีข้อบกพร่องบางอย่าง ที่ไม่ได้รับการแก้ไข
RichVel

2

ฉันชอบระบบที่ใช้การค้นพบ ("จมูก" และ "py.test" โดยใช้ระบบเดิมในปัจจุบัน)

doctest นั้นดีเมื่อการทดสอบนั้นดีเหมือนเอกสารประกอบมิฉะนั้นพวกเขามักจะถ่วงโค้ดมากเกินไป


จมูกดูมีประโยชน์อย่างเหลือเชื่อ ผมยังไม่ได้รับโอกาสที่จะใช้มันยัง แต่ฉันมีความหวังสูง :)
โทนี่ Arkles

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