การทดสอบหน่วย Python จะไปที่ไหน


490

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

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

มีวิธีปฏิบัติที่ดีที่สุดที่นี่?


4
มีคำตอบที่ยอมรับได้สำหรับคำถามนี้มากมายและนั่นไม่ใช่คำถามสำหรับเว็บไซต์ Q / A ผู้คนต้องเข้าใจว่าไม่ใช่คำถามที่เป็นประโยชน์ที่ดีทั้งหมดสามารถถูกถามใน SO ผู้สร้างเลือกสิ่งนั้นและเราจะต้องปฏิบัติตามกฎ
Wouter J

121
ผู้คนจำเป็นต้องเข้าใจว่าเมื่อหน้า SO จบลงด้วยการเป็นที่นิยมที่สุดสำหรับการค้นหาของ Google นั่นอาจจะเป็นการดีกว่าถ้าไปตามกระแสมากกว่าที่จะยึดหลักคำสอนอย่างเป็นทางการของ SO
Christopher Barber

6
@ChristopherBarber ผู้คนก็ต้องเข้าใจด้วยว่าการตัดสินใจและการปิดเชิงรุกคือสิ่งที่ได้รับชื่อเสียงที่น่ากลัวในฐานะที่เป็นเว็บไซต์ที่ฉันไม่อยากไปถามคำถามถ้าฉันไม่มีตัวเลือกที่ดีกว่าจริงๆ
Stefano Borini

คำตอบ:


200

สำหรับไฟล์module.pyการทดสอบหน่วยควรได้รับการเรียกตามปกติตามtest_module.pyแบบแผนการตั้งชื่อของ Pythonic

มีสถานที่ที่ยอมรับกันทั่วไปหลายแห่งที่จะนำtest_module.py:

  1. module.pyในไดเรกทอรีเดียวกันกับ
  2. ใน../tests/test_module.py(ที่ระดับเดียวกับไดเรกทอรีรหัส)
  3. ในtests/test_module.py(หนึ่งระดับภายใต้ไดเรกทอรีรหัส)

ฉันชอบอันดับที่ 1 สำหรับความง่ายในการค้นหาแบบทดสอบและนำเข้า test_สิ่งที่สร้างระบบที่คุณกำลังใช้สามารถกำหนดค่าให้เรียกใช้ไฟล์ที่เริ่มต้นด้วย ที่จริงเริ่มต้นunittesttest*.pyรูปแบบที่ใช้สำหรับการค้นพบการทดสอบ


12
load_tests โปรโตคอลการค้นหาชื่อไฟล์ทดสอบ * .py โดยค่าเริ่มต้น นอกจากนี้ผลลัพธ์ของ Google ที่ได้รับความนิยมสูงสุดนี้และเอกสารที่ไม่ได้ลงลายมือชื่อทั้งคู่ใช้รูปแบบ test_module.py
dfarrell07

6
การใช้ foo_test.py สามารถบันทึกการกดแป้นพิมพ์หรือสองครั้งเมื่อใช้การเติมแท็บเนื่องจากคุณไม่มีไฟล์จำนวนมากที่ขึ้นต้นด้วย 'test_'
juniper-

11
@juniper การทำตามความคิดของคุณ module_test จะปรากฏขึ้นโดยอัตโนมัติเมื่อคุณกำลังเขียนโปรแกรม ที่อาจสร้างความสับสนหรือน่ารำคาญ
Medeiros

11
เมื่อปรับใช้รหัสเราไม่ต้องการปรับใช้การทดสอบไปยังสถานที่ผลิตของเรา ดังนั้นการมีพวกมันไว้ในไดเรกทอรีเดียว './tests/test_blah.py' นั้นง่ายต่อการดึงเมื่อเราทำการปรับใช้ นอกจากนี้การทดสอบบางอย่างใช้ไฟล์ข้อมูลตัวอย่างและการมีไฟล์เหล่านั้นในไดเรกทอรีทดสอบนั้นมีความสำคัญเพราะเราจะปรับใช้ข้อมูลทดสอบ
เควินเจไรซ์

1
@ KevinJ.Rice คุณไม่ควรทำการทดสอบว่ารหัสนั้นใช้งานได้กับสถานที่ผลิตของคุณหรือไม่?
endolith

67

ไฟล์ทดสอบ 1 ไฟล์เท่านั้น

หากมีไฟล์ทดสอบเพียง 1 ไฟล์แนะนำให้วางไว้ในไดเรกทอรีระดับบนสุด:

module/
    lib/
        __init__.py
        module.py
    test.py

รันการทดสอบใน CLI

python test.py

ไฟล์ทดสอบมากมาย

หากมีไฟล์ทดสอบมากมายให้วางไว้ในtestsโฟลเดอร์:

module/
    lib/
        __init__.py
        module.py
    tests/
        test_module.py
        test_module_function.py
# test_module.py

import unittest
from lib import module

class TestModule(unittest.TestCase):
    def test_module(self):
        pass

if __name__ == '__main__':
    unittest.main()

รันการทดสอบใน CLI

# In top-level /module/ folder
python -m tests.test_module
python -m tests.test_module_function

ใช้ unittest discovery

unittest discovery จะพบการทดสอบทั้งหมดในโฟลเดอร์แพ็คเกจ

สร้าง__init__.pyในtests/โฟลเดอร์

module/
    lib/
        __init__.py
        module.py
    tests/
        __init__.py
        test_module.py
        test_module_function.py

รันการทดสอบใน CLI

# In top-level /module/ folder

# -s, --start-directory (default current directory)
# -p, --pattern (default test*.py)

python -m unittest discover

การอ้างอิง

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


51

วิธีปฏิบัติทั่วไปคือการวางไดเรกทอรีการทดสอบในไดเรกทอรีหลักเดียวกันกับโมดูล / แพ็คเกจของคุณ ดังนั้นหากโมดูลของคุณถูกเรียกว่า foo.py รูปแบบไดเรกทอรีของคุณจะมีลักษณะ:

parent_dir/
  foo.py
  tests/

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

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


16
ฉันต้องการทำสิ่งนี้ แต่ไม่สามารถใช้งานได้ ในการรันการทดสอบฉันอยู่ใน parent_dir และพิมพ์: "python tests \ foo_test.py" และใน foo_test.py: "จาก .. foo นำเข้าสิ่งนี้นั่นคืออีก" ที่ล้มเหลวด้วย: "ValueError: พยายาม การนำเข้าที่เกี่ยวข้องในแพคเกจที่ไม่ใช่ "parent_dir ทั้งสองและการทดสอบมีinit .py อยู่ในตัวดังนั้นฉันไม่แน่ใจว่าทำไมพวกเขาถึงไม่ใช่แพ็คเกจ ฉันสงสัยว่าเป็นเพราะสคริปต์ระดับบนสุดที่คุณเรียกใช้จากบรรทัดคำสั่งไม่สามารถพิจารณาแพคเกจ (ส่วนหนึ่งของ) แม้ว่าจะอยู่ใน dir ที่มี init .py ดังนั้นฉันจะรันการทดสอบได้อย่างไร ฉันกำลังทำงานบน Windows วันนี้อวยพรถุงเท้าผ้าฝ้ายของฉัน
Jonathan Hartley

4
วิธีที่ดีที่สุด - ฉันพบ - การทดสอบหน่วยคือติดตั้งไลบรารี / โปรแกรมของคุณจากนั้นเรียกใช้การทดสอบหน่วยด้วยจมูก ฉันจะแนะนำ virtualenv และ virtualenvwrapper เพื่อให้ง่ายขึ้นมาก
Cristian

@Tartley - คุณต้องมีไฟล์init .py ในไดเรกทอรี 'tests' ของคุณเพื่อให้การนำเข้า absolution ทำงาน ฉันใช้วิธีนี้ทำงานร่วมกับจมูกดังนั้นฉันไม่แน่ใจว่าทำไมคุณมีปัญหา
cmcginty

4
ขอบคุณ Casey - แต่ฉันมีไฟล์init .py ในไดเรกทอรีที่เกี่ยวข้องทั้งหมด ฉันไม่รู้ว่าฉันทำอะไรผิด แต่ฉันมีปัญหานี้ในโครงการ Python ทั้งหมดของฉันและฉันไม่เข้าใจว่าทำไมไม่มีใครทำ โอ้ที่รัก
Jonathan Hartley

8
ทางออกหนึ่งสำหรับปัญหาของฉันด้วย Python2.6 หรือใหม่กว่าเราจะทำการทดสอบจากรากของโครงการของคุณโดยใช้: python -m project.package.tests.module_tests (แทนที่จะเป็นงูหลามโครงการ / แพ็คเกจ / การทดสอบ / module_tests.py) . สิ่งนี้จะทำให้ไดเร็กทอรีของโมดูลการทดสอบอยู่บนพา ธ ดังนั้นการทดสอบจึงสามารถทำการนำเข้าแบบสัมพัทธ์ไปยังไดเร็กทอรีพาเรนต์เพื่อรับโมดูลการทดสอบภายใต้
Jonathan Hartley

32

เรามีคำถามเดียวกันเมื่อเขียน Pythoscope ( https://pypi.org/project/pythoscope/ ) ซึ่งสร้างการทดสอบหน่วยสำหรับโปรแกรม Python เราสำรวจผู้คนในการทดสอบในรายการไพ ธ อนก่อนที่เราจะเลือกไดเรกทอรีมีความคิดเห็นที่แตกต่างกันมากมาย ในที่สุดเราเลือกที่จะวางไดเรกทอรี "การทดสอบ" ในไดเรกทอรีเดียวกันกับซอร์สโค้ด ในไดเรกทอรีนั้นเราจะสร้างไฟล์ทดสอบสำหรับแต่ละโมดูลในไดเรกทอรีหลัก


2
! น่ากลัว เพิ่งรัน Pythoscope (โลโก้ที่ยอดเยี่ยม) ในรหัสเดิมและมันก็น่าอัศจรรย์ แนวปฏิบัติที่ดีที่สุดในทันทีและคุณสามารถให้ผู้พัฒนารายอื่นกรอกข้อมูลในส่วนทดสอบที่ล้มเหลวในขณะนี้ ทีนี้ลองเอามันมาใส่ในไม้ไผ่? :)
จะ

27

ฉันมักจะทำการทดสอบหน่วยของฉันในไฟล์ด้วยตัวเองเนื่องจาก Jeremy Cantrell อยู่เหนือบันทึกย่อแม้ว่าฉันมักจะไม่ใส่ฟังก์ชั่นการทดสอบในเนื้อหาหลัก แต่แทนที่จะใส่ทุกอย่างไว้ใน

if __name__ == '__main__':
   do tests...

บล็อก. นี่คือการเพิ่มเอกสารลงในไฟล์ในชื่อ 'โค้ดตัวอย่าง' สำหรับวิธีการใช้ไฟล์ไพ ธ อนที่คุณกำลังทดสอบ

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

if __name__ == '__main__':
   import tests.thisModule
   tests.thisModule.runtests

สิ่งนี้จะช่วยให้ใครก็ตามที่อ่านซอร์สโค้ดของคุณรู้ว่าต้องมองหาโค้ดทดสอบที่ไหน


"เป็น Jeremy Cantrell เหนือบันทึก" ที่ไหน?
endolith

ฉันชอบวิธีการทำงานนี้ เครื่องมือแก้ไขที่ง่ายที่สุดสามารถกำหนดค่าให้เรียกใช้ไฟล์ของคุณด้วยปุ่มลัดดังนั้นเมื่อคุณดูรหัสคุณสามารถเรียกใช้การทดสอบได้ทันที น่าเสียดายในภาษาอื่นที่ไม่ใช่ Python สิ่งนี้อาจดูน่ากลัวดังนั้นหากคุณอยู่ในร้าน C ++ หรือ Java ผู้ร่วมงานของคุณอาจขมวดคิ้วในเรื่องนี้ มันยังทำงานได้ไม่ดีกับเครื่องมือครอบคลุมรหัส
Keeely

19

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

เหตุผลหลักสำหรับการทำเช่นนี้คือ: refactoring refactoring

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

คำถามหลักที่คุณควรถามตัวเองคือ:

ฉันกำลังเขียน:

  • ก) ห้องสมุดที่นำมาใช้ซ้ำหรือ
  • b) การสร้างโครงการมากกว่าการรวมโมดูลบางส่วนเข้าด้วยกัน?

หาก:

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

แต่ก็เป็นเรื่องง่ายเหมือนกันที่จะแยกการทดสอบออกจากการแจกจ่ายเมื่อผสมกับโฟลเดอร์หลัก วางสิ่งนี้ไว้ใน setup.py :

find_packages("src", exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) 

ถ้า b:

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

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

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


1
ปัญหาของการปรับใช้การทดสอบกับการผลิตจริงหรือไม่ จากประสบการณ์ของฉันมันมีประโยชน์มาก: อนุญาตให้ผู้ใช้ทำการทดสอบบนสภาพแวดล้อมจริง ... เมื่อคุณได้รับรายงานข้อผิดพลาดคุณสามารถขอให้ผู้ใช้เรียกใช้ชุดทดสอบเพื่อให้แน่ใจว่าทุกอย่างเรียบร้อยและส่งฮอตแพตช์สำหรับการทดสอบ ห้องสวีทโดยตรง ... นอกจากนี้ก็ไม่ได้เพราะคุณใส่การทดสอบของคุณใน module.tests ว่ามันจะจบลงในการผลิตเว้นแต่คุณจะทำอะไรบางอย่างที่ไม่ถูกต้องในการติดตั้งไฟล์ของคุณ ...
anarcat

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

15

ฉันใช้tests/ไดเรกทอรีแล้วนำเข้าโมดูลแอปพลิเคชันหลักโดยใช้การนำเข้าแบบสัมพัทธ์ ดังนั้นใน MyApp / tests / foo.py อาจมี:

from .. import foo

เพื่อนำเข้าMyApp.fooโมดูล


5
"ValueError: พยายามนำเข้าที่เกี่ยวข้องในแพ็คเกจที่ไม่ใช่"
cprn

12

ฉันไม่เชื่อว่ามี "แนวปฏิบัติที่ดีที่สุด" ที่จัดตั้งขึ้นแล้ว

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


3
ฉันเพิ่มไดเรกทอรีแอปหลักไปยัง sys.pathปัญหาคือหากการทดสอบของคุณมีโมดูลตัวช่วย (เช่นทดสอบเว็บเซิร์ฟเวอร์) และคุณต้องนำเข้าโมดูลตัวช่วยดังกล่าวจากภายในการทดสอบที่เหมาะสมของคุณ
Piotr Dobrogost

นี่คือสิ่งที่ดูเหมือนว่าสำหรับฉัน:os.sys.path.append(os.dirname('..'))
แมตต์เอ็ม

11

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

                              <Main Package>
                               /          \
                              /            \
                            lib           tests
                            /                \
             [module1.py, module2.py,  [ut_module1.py, ut_module2.py,
              module3.py  module4.py,   ut_module3.py, ut_module.py]
              __init__.py]

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


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

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

11

ฉันแนะนำให้คุณตรวจสอบโครงการหลักของ Python บน GitHub และรับแนวคิด

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

ตัวอย่างเช่นถ้าคุณมีโครงสร้างไดเรกทอรีเช่น:

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
setup.py

หลังจากเพิ่มโฟลเดอร์ทดสอบคุณจะมีโครงสร้างไดเรกทอรีเช่น:

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
test/
   unit/
      myapp/
         moduleA/
            module_A_test.py
         moduleB/
            module_B_test.py
   integration/
          myapp/
             moduleA/
                module_A_test.py
             moduleB/
                module_B_test.py
setup.py

แพ็คเกจ Python ที่เขียนอย่างถูกต้องจำนวนมากใช้โครงสร้างเดียวกัน ตัวอย่างที่ดีมากคือแพ็คเกจ Boto ตรวจสอบhttps://github.com/boto/boto


1
ขอแนะนำให้ใช้ "การทดสอบ" แทน "การทดสอบ" เพราะ "การทดสอบ" เป็น Python ในโมดูล docs.python.org/2/library/test.html
brodul

ไม่เสมอไป .. ตัวอย่างเช่นmatplotlibอยู่ภายใต้matplotlib/lib/matplotlib/tests( github.com/matplotlib/matplotlib/tree/ … ) sklearnมีไว้ใต้scikitelearn/sklearn/tests( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )
alpha_989

7

ฉันจะทำอย่างไร ...

โครงสร้างโฟลเดอร์:

project/
    src/
        code.py
    tests/
    setup.py

Setup.py ชี้ไปที่ src / เป็นตำแหน่งที่มีโมดูลโครงการของฉันจากนั้นฉันเรียกใช้:

setup.py develop

ซึ่งเพิ่มโครงการของฉันลงในแพ็คเกจไซต์ชี้ไปที่สำเนาการทำงานของฉัน เพื่อรันการทดสอบของฉันฉันใช้:

setup.py tests

ใช้ตัวทดสอบที่ฉันกำหนดค่า


ดูเหมือนว่าคุณจะมีคำว่า "โมดูล" มากเกินไป code.pyโปรแกรมเมอร์หลามส่วนใหญ่อาจจะคิดว่าโมดูลเป็นไฟล์ที่คุณเรียกว่า มันจะเหมาะสมกว่าถ้าจะเรียกไดเรกทอรี "โครงการ" ระดับบนสุด
blokeley

4

ฉันชอบไดเรกทอรีทดสอบระดับสูง นี่หมายถึงการนำเข้ายากขึ้นเล็กน้อย เพื่อที่ฉันมีสองวิธี:

  1. ใช้ setuptools จากนั้นคุณสามารถผ่านtest_suite='tests.runalltests.suite'เข้าไปsetup()และสามารถทำการทดสอบได้อย่างง่ายดาย:python setup.py test
  2. ตั้งค่า PYTHONPATH เมื่อทำการทดสอบ: PYTHONPATH=. python tests/runalltests.py

นี่คือวิธีการที่โค้ดรองรับใน M2Crypto:

หากคุณต้องการเรียกใช้การทดสอบด้วย nosetests คุณอาจต้องทำสิ่งที่แตกต่างกันเล็กน้อย


3

เราใช้

app/src/code.py
app/testing/code_test.py 
app/docs/..

ในไฟล์ทดสอบแต่ละเราแทรกใน../src/ sys.pathมันไม่ใช่ทางออกที่ดีที่สุด แต่ใช้ได้ ฉันคิดว่ามันจะดีถ้ามีใครมาด้วย waven คล้ายจาวาที่ให้การประชุมมาตรฐานที่ใช้งานได้ไม่ว่าคุณจะทำงานโครงการอะไร


1

หากการทดสอบนั้นง่ายเพียงใส่ไว้ใน docstring - กรอบการทดสอบส่วนใหญ่สำหรับ Python จะสามารถใช้งานได้:

>>> import module
>>> module.method('test')
'testresult'

สำหรับการทดสอบอื่น ๆ ที่เกี่ยวข้องมากขึ้นผมจะนำพวกเขาทั้งในหรือ../tests/test_module.pytests/test_module.py


1

ใน C # ฉันมักจะแยกการทดสอบเป็นชุดประกอบที่แยกต่างหาก

ใน Python - จนถึง - ฉันมักจะเขียน doctests โดยที่การทดสอบอยู่ใน docstring ของฟังก์ชั่นหรือวางไว้ในif __name__ == "__main__"บล็อกที่ด้านล่างของโมดูล


0

เมื่อเขียนแพ็คเกจที่เรียกว่า "foo" ฉันจะทดสอบหน่วยลงในแพคเกจแยกต่างหาก "foo_test" โมดูลและแพ็กเกจย่อยจะมีชื่อเหมือนกับโมดูลแพ็กเกจ SUT เช่นการทดสอบสำหรับโมดูล foo.xy พบได้ใน foo_test.xy ไฟล์ __init__.py ของแต่ละแพ็คเกจการทดสอบจะมีชุด AllTests ซึ่งรวมถึงชุดทดสอบทั้งหมดของแพ็คเกจ setuptools มีวิธีที่สะดวกในการระบุแพ็คเกจการทดสอบหลักดังนั้นหลังจาก "python setup.py พัฒนา" คุณสามารถใช้ "python setup.py test" หรือ "python setup.py test -s foo_test.x.SomeTestSuite" เพื่อ เพียงชุดเฉพาะ


0

ฉันวางการทดสอบของฉันในไดเรกทอรีเดียวกันกับรหัสที่อยู่ภายใต้การทดสอบ (CUT); สำหรับfoo.pyการทดสอบจะอยู่ในfoo_ut.pyหรือคล้ายกัน (ฉันปรับแต่งกระบวนการค้นพบทดสอบเพื่อค้นหาสิ่งเหล่านี้)

วิธีนี้จะทำให้การทดสอบข้างรหัสในรายการไดเรกทอรีทำให้เห็นได้ชัดว่ามีการทดสอบและทำให้การเปิดการทดสอบง่ายที่สุดเท่าที่จะเป็นไปได้เมื่ออยู่ในไฟล์แยกต่างหาก (สำหรับผู้แก้ไขบรรทัดคำสั่งvim foo*และเมื่อใช้เบราว์เซอร์ระบบไฟล์กราฟิกให้คลิกที่ไฟล์ CUT แล้วเลือกไฟล์ทดสอบที่อยู่ติดกันทันที)

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

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


-2

ฉันเพิ่งเริ่มโปรแกรมใน Python ดังนั้นฉันยังไม่มีโอกาสได้รู้จักวิธีปฏิบัติที่ดีที่สุด แต่ฉันได้เขียนโมดูลที่จะไปและค้นหาการทดสอบทั้งหมดและเรียกใช้พวกเขา

ดังนั้นฉันมี:

app /
 appfile.py
ทดสอบ/
 appfileTest.py

ฉันจะต้องดูว่ามันจะเป็นอย่างไรเมื่อฉันพัฒนาโครงการขนาดใหญ่


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