Trong pytest, việc sử dụng các tập tin conftest.py là gì?


216

Tôi mới phát hiện ra pytest. Nó có vẻ tuyệt vời. Tuy nhiên, tôi cảm thấy các tài liệu có thể tốt hơn.

Tôi đang cố gắng hiểu những gì conftest.pytập tin được sử dụng cho.

Trong bộ thử nghiệm (hiện tại nhỏ) của tôi, tôi có một conftest.pytệp ở gốc dự án. Tôi sử dụng nó để xác định đồ đạc mà tôi tiêm vào các bài kiểm tra của mình.

Tôi có hai câu hỏi:

  1. Đây có phải là cách sử dụng đúng conftest.py? Nó có công dụng khác không?
  2. Tôi có thể có nhiều hơn một conftest.pytập tin không? Khi nào tôi muốn làm điều đó? Ví dụ sẽ được đánh giá cao.

Tổng quát hơn, làm thế nào bạn sẽ xác định mục đích và việc sử dụng đúng conftest.py(các) tệp trong bộ kiểm tra py.test?


8
Bạn đã có tôi tạiIt seems great. However, I feel the documentation could be better.
user9074332

6
Vâng, tài liệu có thể tốt hơn nhiều. Tôi đã tìm kiếm toàn bộ tài liệu về pytest conftest.pyvà mặc dù có nhiều tài liệu tham khảo để thực hiện điều này hoặc thực hiện điều đó với một tệp conftest, nhưng không có tài liệu nào chứng minh rằng khi pytest thực hiện kiểm tra khám phá, tất cả các tệp conftest.py được tìm thấy (trong thư mục strucutre về việc khám phá thử nghiệm đang được thực hiện) sẽ được chạy trong giai đoạn thu thập thử nghiệm (trước khi bất kỳ thử nghiệm nào được chạy). Phải tự mình tìm ra điều đó thông qua thử nghiệm.
Daniel Goldfarb

Câu trả lời:


287

Đây có phải là cách sử dụng chính xác của conftest.py?

Vâng, đúng vậy. Lịch thi đấu là một tiềm năng và sử dụng phổ biến conftest.py. Các đồ đạc mà bạn sẽ xác định sẽ được chia sẻ giữa tất cả các bài kiểm tra trong bộ kiểm tra của bạn. Tuy nhiên, việc xác định đồ đạc trong thư mục gốc conftest.pycó thể là vô ích và nó sẽ làm chậm quá trình kiểm tra nếu tất cả các bài kiểm tra đó không được sử dụng.

Nó có công dụng khác không?

Có nó làm.

  • Lịch thi đấu : Xác định đồ đạc cho dữ liệu tĩnh được sử dụng bởi các bài kiểm tra. Dữ liệu này có thể được truy cập bởi tất cả các thử nghiệm trong bộ trừ khi được quy định khác. Đây có thể là dữ liệu cũng như người trợ giúp của các mô-đun sẽ được chuyển đến tất cả các thử nghiệm.

  • Tải plugin bên ngoài : conftest.pyđược sử dụng để nhập các plugin hoặc mô-đun bên ngoài. Bằng cách xác định biến toàn cục sau, pytest sẽ tải mô-đun và làm cho nó có sẵn để thử nghiệm. Plugin thường là các tệp được xác định trong dự án của bạn hoặc các mô-đun khác có thể cần thiết trong các thử nghiệm của bạn. Bạn cũng có thể tải một tập các plugin được xác định trước như được giải thích ở đây .

    pytest_plugins = "someapp.someplugin"

  • Móc : Bạn có thể chỉ định các móc như phương pháp thiết lập và phá bỏ và nhiều hơn nữa để cải thiện các thử nghiệm của bạn. Đối với một bộ móc có sẵn, đọc ở đây . Thí dụ:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
    
  • Kiểm tra đường dẫn gốc : Đây là một chút tính năng ẩn. Bằng cách xác định conftest.pytrong đường dẫn gốc của bạn, bạn sẽ pytestnhận ra các mô-đun ứng dụng của mình mà không chỉ định PYTHONPATH. Trong nền, py.test sửa đổi của bạn sys.pathbằng cách bao gồm tất cả các mô hình con được tìm thấy từ đường dẫn gốc.

Tôi có thể có nhiều hơn một tập tin conftest.py không?

Có, bạn có thể và rất khuyến khích nếu cấu trúc kiểm tra của bạn hơi phức tạp. conftest.pytập tin có phạm vi thư mục. Do đó, tạo đồ đạc mục tiêu và người trợ giúp là thực hành tốt.

Khi nào tôi muốn làm điều đó? Ví dụ sẽ được đánh giá cao.

Một số trường hợp có thể phù hợp:

Tạo một bộ công cụ hoặc móc cho một nhóm thử nghiệm cụ thể.

root / 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"

Đang tải một bộ đồ đạc cho một số bài kiểm tra nhưng không cho các bài kiểm tra khác.

root / mod / conftest.py

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

root / mod2 / conftest.py

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

root / mod2 / test.py

def test(fixture):
    print(fixture)

Sẽ in "một số thứ khác".

Móc ghi đè thừa kế từ gốc conftest.py.

root / mod / conftest.py

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

root / conftest.py

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

Bằng cách chạy bất kỳ thử nghiệm nào bên trong root/mod, chỉ có "Tôi là mod" được in.

Bạn có thể đọc thêm về conftest.py đây .

BIÊN TẬP:

Điều gì sẽ xảy ra nếu tôi cần các hàm trợ giúp cũ đơn giản được gọi từ một số thử nghiệm trong các mô-đun khác nhau - chúng có sẵn cho tôi nếu tôi đặt chúng trong một conftest.py không? Hoặc tôi chỉ nên đặt chúng trong một mô-đun trợ giúp và nhập và sử dụng nó trong các mô-đun thử nghiệm của mình?

Bạn có thể sử dụng conftest.pyđể xác định người trợ giúp của bạn. Tuy nhiên, bạn nên làm theo thông lệ. Người trợ giúp có thể được sử dụng như đồ đạc ít nhất trong pytest. Ví dụ, trong các thử nghiệm của tôi, tôi có một người trợ giúp giả mà tôi tiêm vào các thử nghiệm của mình theo cách này.

root / helper / redis / redis.py

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

root / tests / Stuff / conftest.py

pytest_plugin="helper.redis.redis"

root / tests / Stuff / test.py

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

Đây sẽ là một mô-đun thử nghiệm mà bạn có thể tự do nhập vào các thử nghiệm của mình. LƯU Ý rằng bạn có khả năng có thể đặt tên redis.pynhư conftest.pythể mô-đun của bạn redischứa nhiều bài kiểm tra hơn. Tuy nhiên, thực tế đó không được khuyến khích vì sự mơ hồ.

Nếu bạn muốn sử dụng conftest.py, bạn chỉ cần đặt người trợ giúp đó vào thư mục gốc của mình conftest.pyvà tiêm nó khi cần.

root / tests / conftest.py

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

root / tests / Stuff / test.py

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

Một điều khác bạn có thể làm là viết một plugin có thể cài đặt. Trong trường hợp đó, người trợ giúp của bạn có thể được viết ở bất cứ đâu nhưng nó cần xác định một điểm vào sẽ được cài đặt trong các khung kiểm tra tiềm năng khác của bạn. Xem này .

Nếu bạn không muốn sử dụng đồ đạc, tất nhiên bạn có thể xác định một người trợ giúp đơn giản và chỉ cần sử dụng nhập cũ đơn giản bất cứ nơi nào cần thiết.

root / tests / helper / redis.py

class MockRedis():
    # stuff

root / tests / Stuff / test.py

from helper.redis import MockRedis

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

Tuy nhiên, ở đây bạn có thể gặp vấn đề với đường dẫn vì mô-đun không nằm trong thư mục con của bài kiểm tra. Bạn sẽ có thể khắc phục điều này (không được kiểm tra) bằng cách thêm một __init__.pyngười trợ giúp của bạn

root / tests / helper / __ init__.py

from .redis import MockRedis

Hoặc đơn giản là thêm mô-đun trợ giúp vào PYTHONPATH.


tôi đang gặp một tình huống trong đó mô-đun thử nghiệm đơn vị đầu tiên của tôi, test_aaaaa.pythực sự đang cố chạy trước khi thiết lập lịch thi đấu hoàn tất conftest.py. Bất kỳ suy nghĩ về lý do tại sao điều này có thể xảy ra?
dùng907432

Nếu không có conftest.py, đường dẫn gốc kiểm tra của bạn sẽ không được thêm vào sys.path và bạn sẽ thấy các lỗi như "ModuleNotFoundError: Không có mô-đun nào có tên 'foobar'".
Cale Sweeney

10

Theo nghĩa rộng, conftest.py là một plugin cho mỗi thư mục cục bộ. Ở đây bạn xác định móc và đồ đạc cụ thể thư mục. Trong trường hợp của tôi, có một thư mục gốc chứa các thư mục kiểm tra cụ thể của dự án. Một số phép thuật phổ biến được đặt trong 'root' conftest.py. Dự án cụ thể - trong những cái riêng của họ. Không thể thấy bất cứ điều gì xấu khi lưu trữ đồ đạc trong conftest.py trừ khi chúng không được sử dụng rộng rãi (Trong trường hợp đó tôi muốn xác định chúng trực tiếp trong các tệp thử nghiệm)


10

Tôi sử dụng conftest.pytệp để xác định đồ đạc mà tôi tiêm vào các bài kiểm tra của mình, đây có phải là cách sử dụng đúng conftest.pykhông?

, một vật cố thường được sử dụng để có được dữ liệu sẵn sàng cho nhiều thử nghiệm.

Nó có công dụng khác không?

, một vật cố là một chức năng được chạy pytesttrước và đôi khi sau, các chức năng kiểm tra thực tế. Mã trong vật cố có thể làm bất cứ điều gì bạn muốn. Ví dụ, một vật cố có thể được sử dụng để có được một bộ dữ liệu cho các thử nghiệm hoạt động hoặc một vật cố cũng có thể được sử dụng để đưa một hệ thống vào trạng thái đã biết trước khi chạy thử nghiệm.

Tôi có thể có nhiều hơn một conftest.pytập tin không? Khi nào tôi muốn làm điều đó?

Đầu tiên, có thể đặt đồ đạc vào các tệp thử nghiệm riêng lẻ. Tuy nhiên, để chia sẻ đồ đạc giữa nhiều tệp thử nghiệm, bạn cần sử dụng một conftest.pytệp ở đâu đó nằm ở trung tâm cho tất cả các thử nghiệm. Lịch thi đấu có thể được chia sẻ bởi bất kỳ thử nghiệm. Chúng có thể được đặt trong các tệp thử nghiệm riêng lẻ nếu bạn muốn vật cố định chỉ được sử dụng bởi các thử nghiệm trong tệp đó.

Thứ hai, vâng , bạn có thể có các conftest.pytệp khác trong thư mục con của thư mục kiểm tra hàng đầu. Nếu bạn làm như vậy, đồ đạc được xác định trong các conftest.pytệp cấp thấp hơn này sẽ có sẵn để kiểm tra trong thư mục và thư mục con đó.

Cuối cùng, đặt đồ đạc trong conftest.pytệp ở gốc kiểm tra sẽ làm cho chúng có sẵn trong tất cả các tệp kiểm tra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.