ใน pytest การใช้ไฟล์ conftest.py คืออะไร?


217

pytestฉันเพิ่งค้นพบ มันดูดีมาก อย่างไรก็ตามฉันรู้สึกว่าเอกสารอาจจะดีกว่า

ฉันพยายามที่จะเข้าใจว่าconftest.pyไฟล์อะไรที่ควรใช้

ในชุดทดสอบ (ปัจจุบันเล็ก) ของฉันฉันมีconftest.pyไฟล์หนึ่งไฟล์ที่รูทโปรเจ็กต์ ฉันใช้มันเพื่อกำหนดการแข่งขันที่ฉันฉีดเข้าไปในการทดสอบของฉัน

ฉันมีสองคำถาม:

  1. นี่เป็นการใช้งานที่ถูกต้องconftest.pyหรือไม่? มันมีประโยชน์อื่น ๆ ?
  2. ฉันสามารถมีมากกว่าหนึ่งconftest.pyไฟล์ได้หรือไม่ เมื่อไหร่ที่ฉันจะทำเช่นนั้น? ตัวอย่างจะได้รับการชื่นชม

โดยทั่วไปแล้วคุณจะกำหนดวัตถุประสงค์และแก้ไขการใช้conftest.pyไฟล์ในชุดทดสอบ py.test อย่างไร


9
คุณมีฉันที่It seems great. However, I feel the documentation could be better.
user9074332

7
ใช่เอกสารน่าจะดีขึ้นมาก ฉันค้นหาเอกสาร pytest ทั้งหมดconftest.pyและแม้ว่ามีการอ้างอิงจำนวนมากในการทำสิ่งนี้หรือทำสิ่งนั้นด้วยไฟล์ conftest แต่ในเอกสารนั้นไม่ได้ระบุว่าเมื่อ pytest ทำการทดสอบการค้นพบ ไฟล์ conftest.py ทั้งหมดที่พบ (ภายใน ไดเรกทอรีโครงสร้างที่การค้นพบการทดสอบกำลังดำเนินการอยู่) จะถูกเรียกใช้ในระหว่างขั้นตอนการรวบรวมการทดสอบ (ก่อนที่จะทำการทดสอบใด ๆ ) ต้องคิดออกเองว่าผ่านการทดลอง
Daniel Goldfarb

คำตอบ:


289

นี่เป็นการใช้งาน conftest.py ที่ถูกต้องหรือไม่?

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

มันมีประโยชน์อื่น ๆ ?

ใช่แล้ว.

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

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

    pytest_plugins = "someapp.someplugin"

  • Hooks : คุณสามารถระบุ hooks เช่นวิธีการตั้งค่าและการฉีกขาดและอีกมากมายเพื่อปรับปรุงการทดสอบของคุณ สำหรับชุดของตะขอใช้ได้อ่านที่นี่ ตัวอย่าง:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
    
  • ทดสอบเส้นทางหลัก : นี่เป็นคุณลักษณะที่ซ่อนอยู่เล็กน้อย โดยการกำหนดconftest.pyในเส้นทางรากของคุณคุณจะต้องตระหนักถึงโมดูลใบสมัครของคุณโดยไม่ได้ระบุpytest PYTHONPATHในพื้นหลัง py.test จะปรับเปลี่ยนของคุณsys.pathด้วยการรวมเอา submodules ทั้งหมดที่พบจากเส้นทางของรูท

ฉันสามารถมีไฟล์ conftest.py มากกว่าหนึ่งไฟล์ได้หรือไม่

ใช่คุณสามารถทำได้และขอแนะนำอย่างยิ่งหากโครงสร้างการทดสอบของคุณค่อนข้างซับซ้อน conftest.pyไฟล์มีขอบเขตไดเรกทอรี ดังนั้นการสร้างการแข่งขันและผู้ช่วยเป้าหมายจึงเป็นวิธีปฏิบัติที่ดี

เมื่อไหร่ที่ฉันจะทำเช่นนั้น? ตัวอย่างจะได้รับการชื่นชม

หลายกรณีสามารถใส่ได้:

การสร้างชุดเครื่องมือหรือขอสำหรับกลุ่มการทดสอบที่เฉพาะเจาะจง

ราก / mod / conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff


test root/mod2/test.py will NOT produce "I am mod"

กำลังโหลดชุดการแข่งขันสำหรับการทดสอบบางอย่าง แต่ไม่ใช่สำหรับการทดสอบอื่น ๆ

ราก / mod / conftest.py

@pytest.fixture()
def fixture():
    return "some stuff"

ราก / mod2 / conftest.py

@pytest.fixture()
def fixture():
    return "some other stuff"

ราก / mod2 / test.py

def test(fixture):
    print(fixture)

จะพิมพ์ "สิ่งอื่น ๆ "

การแทนที่ hooks ที่สืบทอดมาจากรูconftest.py

ราก / mod / conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff

ราก / conftest.py

def pytest_runtest_setup(item):
    print("I am root")
    #do some stuff

เมื่อทำการทดสอบภายในroot/modจะมีการพิมพ์เฉพาะ "I am mod"

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับที่นี่conftest.py

แก้ไข:

จะทำอย่างไรถ้าฉันต้องการฟังก์ชั่นตัวช่วยธรรมดาแบบเก่าที่จะเรียกจากการทดสอบจำนวนมากในโมดูลที่แตกต่างกัน - พวกเขาจะสามารถใช้งานได้หรือไม่หากฉันวางไว้ใน conftest.py หรือฉันควรวางไว้ในโมดูล helpers.py แล้วนำเข้าและใช้ในโมดูลทดสอบของฉัน

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

ราก / ผู้ช่วย / Redis / redis.py

@pytest.fixture
def mock_redis():
    return MockRedis()

ราก / ทดสอบ / สิ่ง / conftest.py

pytest_plugin="helper.redis.redis"

ราก / ทดสอบ / สิ่ง / test.py

def test(mock_redis):
    print(mock_redis.get('stuff'))

นี่จะเป็นโมดูลทดสอบที่คุณสามารถนำเข้าได้อย่างอิสระในการทดสอบของคุณ โปรดทราบว่าคุณอาจตั้งชื่อredis.pyราวกับconftest.pyว่าโมดูลของคุณredisมีการทดสอบเพิ่มเติม อย่างไรก็ตามการฝึกฝนนั้นไม่ได้เกิดขึ้นเพราะความกำกวม

หากคุณต้องการใช้conftest.pyคุณสามารถใส่ผู้ช่วยนั้นลงในรูทconftest.pyแล้วฉีดเข้าไปเมื่อจำเป็น

ราก / ทดสอบ / conftest.py

@pytest.fixture
def mock_redis():
    return MockRedis()

ราก / ทดสอบ / สิ่ง / test.py

def test(mock_redis):
    print(mock_redis.get(stuff))

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

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

ราก / ทดสอบ / ผู้ช่วย / redis.py

class MockRedis():
    # stuff

ราก / ทดสอบ / สิ่ง / test.py

from helper.redis import MockRedis

def test():
    print(MockRedis().get(stuff))

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

ราก / ทดสอบ / ผู้ช่วย / __ init__.py

from .redis import MockRedis

PYTHONPATHหรือเพียงแค่การเพิ่มโมดูลผู้ช่วยของคุณ


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

หากไม่มี conftest.py พา ธ การทดสอบของคุณจะไม่ถูกเพิ่มไปยัง sys.path และคุณจะเห็นข้อผิดพลาดเช่น "ModuleNotFoundError: ไม่มีโมดูลชื่อ 'foobar'"
Cale Sweeney

11

ในความหมายกว้าง conftest.py เป็นปลั๊กอินท้องถิ่นต่อไดเรกทอรี ที่นี่คุณกำหนด hooks และฟิกซ์เจอร์เฉพาะไดเร็กทอรี ในกรณีของฉันมีไดเรกทอรีรากที่มีไดเรกทอรีการทดสอบเฉพาะโครงการ เวทมนตร์ทั่วไปบางอย่างถูกส่งไปประจำการใน 'root' conftest.py โครงการที่เฉพาะเจาะจง - ในตัวของพวกเขาเอง ไม่เห็นสิ่งที่ไม่ดีในการจัดเก็บการติดตั้งใน conftest.py เว้นแต่ว่าพวกเขาจะไม่ได้ใช้กันอย่างแพร่หลาย (ในกรณีนี้ฉันต้องการกำหนดพวกเขาในไฟล์ทดสอบโดยตรง)


10

ฉันใช้conftest.pyไฟล์เพื่อกำหนดการแข่งขันที่ฉันฉีดเข้าไปในการทดสอบของฉันนี่เป็นการใช้งานที่ถูกต้องconftest.pyหรือไม่?

ใช่โดยปกติฟิกซ์เจอร์จะถูกใช้เพื่อเตรียมข้อมูลให้พร้อมสำหรับการทดสอบหลายครั้ง

มันมีประโยชน์อื่น ๆ ?

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

ฉันสามารถมีมากกว่าหนึ่งconftest.pyไฟล์ได้หรือไม่ เมื่อไหร่ที่ฉันจะทำเช่นนั้น?

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

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

ในที่สุดการวางฟิกซ์เจอร์ลงในconftest.pyไฟล์ที่รูทการทดสอบจะทำให้มันพร้อมใช้งานในไฟล์ทดสอบทั้งหมด

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