Câu hỏi Nhiều bản sao của một vật cố py.test


Hãy nói rằng tôi có một trận đấu đơn giản như sau (bằng cách sử dụng pytest-django, nhưng tôi nghĩ rằng nó nên áp dụng cho pytest là tốt):

@pytest.fixture
def my_thing(request, db):
    thing = MyModel.objects.create()
    request.addfinalizer(lambda: thing.delete())
    return thing

Điều này làm việc tuyệt vời khi các bài kiểm tra của tôi cần một cá thể đơn của MyModel. Nhưng nếu tôi cần hai (hoặc ba hoặc bốn) thì sao? Tôi muốn mỗi cá thể là khác biệt, nhưng phải được thiết lập theo cùng một cách.

Tôi có thể sao chép / dán mã và đổi tên chức năng lịch thi đấu, nhưng điều đó có vẻ không phù hợp.

Tương tự, tôi đã thử:

@pytest.fixture
def my_thing_1(my_thing):
    return my_thing

@pytest.fixture
def my_thing_2(my_thing):
    return my_thing

Tuy nhiên, mỗi trong số này xuất hiện để trả về cùng một thể hiện MyModel.

Có cách nào để làm những gì tôi muốn bằng cách sử dụng chức năng tích hợp của pytest? Cách khác, tôi có thể di chuyển các thiết lập / teardown của vật cố của tôi ra thành các chức năng trợ giúp vì vậy tôi không nhân bản quá nhiều mã.

Hoặc tôi đang đi về toàn bộ điều này một cách sai lầm?


13
2018-02-05 17:09


gốc




Các câu trả lời:


Cách tiếp cận của tôi có lẽ sẽ tạo ra một vật cố định có thể tạo ra các đối tượng của bạn:

@pytest.fixture
def thing(request, db):
    class ThingFactory(object):
        def get(self):
            thing = MyModel.objects.create()
            request.addfinalizer(thing.delete)
            return thing
    return ThingFactory()

def test_thing(thing):
    thing1 = thing.get()
    thing2 = thing.get()

Rõ ràng bạn có thể làm .get() lấy một đối số, v.v.

(PS: Cũng lưu ý không cần lambda trong finalizer)


17
2018-02-05 22:39



1) Tốt cuộc gọi trên không cần lambda trong finalizer. 2) Tôi thích cách tiếp cận của bạn. Tôi đang thực sự sử dụng Factory Boy để tạo ra những mô hình này, vì vậy tôi nghĩ rằng lý tưởng tôi thậm chí sẽ không cần phải tạo ra đồ đạc nhà máy cho từng mô hình. Nhưng tôi đang gặp khó khăn khi phân lớp ModelFactory để đệ quy thêm finalizers cho SubFactories, vì vậy tôi nghĩ rằng tôi sẽ sử dụng cách tiếp cận của bạn như là một khoảng cách dừng lại. Cảm ơn! - Frank T
Để tham khảo trong tương lai, lý do duy nhất tôi đã sử dụng finalizers là bởi vì pytest-django đã không làm sạch cơ sở dữ liệu giữa các bài kiểm tra vì nó không hỗ trợ nhiều cơ sở dữ liệu (xem thêm github.com/pelme/pytest_django/issues/76). Đối với các loại vấn đề tôi mô tả ở trên, tôi hết lòng khuyên bạn nên sử dụng FactoryBoy với pytest-django. - Frank T


Tôi đến câu hỏi này rất muộn ... nhưng, bằng cách sử dụng một vật cố định và chỉ đơn giản là trả lại các vật cố bạn muốn sao chép dường như làm việc quá.

import pytest
import random

@pytest.fixture
def name():
    return random.randint(0, 10)


@pytest.fixture(params=[0, 1])
def parametrized_name(request, name):
    return name


def test_something(parametrized_name):
    print "Testing with name: " + str(parametrized_name)

Nếu bạn chạy thử nghiệm ở trên, bạn sẽ nhận được 2 đồ đạc "tên" khác nhau

$ pytest -s blah.py
============================================= test session starts ==============================================
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /home/bsquizza/repos/blah/tests, inifile:
collected 2 items                                                                                              

blah.py Testing with name: 7
.Testing with name: 10
.                                                                                               [100%]

=========================================== 2 passed in 0.01 seconds ===========================================

0
2018-01-30 20:14