2014-08-28 22 views
6

Tôi muốn có thể trả về một giá trị từ một vật cố định cho nhiều bài kiểm tra/các lớp thử nghiệm, nhưng giá trị được chuyển qua là một hàm.fixture pytest luôn luôn trả về một chức năng

Dưới đây là mã của tôi:

import pytest 

@pytest.fixture() 
def user_setup(): 
    user = { 
     'name': 'chad', 
     'id': 1 
    } 
    return user 

@pytest.mark.usefixtures('user_setup') 
class TestThings: 
    def test_user(self): 
     assert user_setup['name'] == 'chad' 

Đầu ra là:

=================================== FAILURES =================================== 
_____________________________ TestThings.test_user _____________________________ 

self = <tests.test_again.TestThings instance at 0x10aed6998> 

    def test_user(self): 
>  assert user_setup['name'] == 'chad' 
E  TypeError: 'function' object has no attribute '__getitem__' 

tests/test_again.py:14: TypeError 
=========================== 1 failed in 0.02 seconds =========================== 

Nhưng nếu tôi viết lại thử nghiệm của tôi để nó không sử dụng usefixtures trang trí, nó hoạt động như mong đợi:

def test_user(user_setup): 
    assert user_setup['name'] == 'chad' 

Bất kỳ ý tưởng nào tại sao nó không hoạt động khi tôi cố gắng sử dụng phương pháp trang trí?

Trả lời

13

Khi bạn sử dụng @pytest.mark.usefixtures marker bạn vẫn cần phải cung cấp một đối số đầu vào có tên tương tự nếu bạn muốn cố định đó được tiêm vào để kiểm tra chức năng của bạn.

Như đã trình bày trong py.test docs for fixtures:

Tên của hàm cố định sau này có thể được tham chiếu để gây gọi của nó trước chạy thử nghiệm ... chức năng kiểm tra có thể trực tiếp sử dụng tên cố định như các đối số đầu vào trong trong trường hợp đó, bản sửa lỗi được trả về từ chức năng cố định sẽ được bơm.

Vì vậy, chỉ cần sử dụng trang trí @pytest.mark.usefixtures sẽ chỉ gọi hàm. Cung cấp một đối số đầu vào sẽ cho bạn kết quả của hàm đó.

Bạn chỉ thực sự cần sử dụng @pytest.mark.usefixtures khi bạn muốn gọi một lịch thi đấu nhưng không muốn có nó làm đối số đầu vào cho bài kiểm tra của mình. Như được mô tả trong py.test docs.

Lý do bạn nhận được ngoại lệ nói về user_setup là một hàm do bên trong hàm test_user của bạn tên user_setup thực sự đề cập đến hàm bạn đã xác định trước đó trong tệp. Để có được mã của bạn để làm việc như bạn mong đợi bạn sẽ cần phải thêm một tham số cho hàm test_user:

@pytest.mark.usefixtures('user_setup') 
class TestThings: 
    def test_user(self, user_setup): 
     assert user_setup['name'] == 'chad' 

Bây giờ từ quan điểm của hàm test_user tên user_setup sẽ tham khảo các luận cứ chức năng mà sẽ được trả về giá trị của vật cố định được tiêm bởi py.test.

Nhưng thực sự bạn chỉ không cần sử dụng trang trí @pytest.mark.usefixtures.

+2

Cảm ơn bạn đã giải thích rõ về cách hoạt động của nó. Tôi đã nghĩ rằng tôi có thể thực hiện điều này mà không cần phải thêm đối số cho mỗi hàm thử nghiệm nằm trong lớp thử nghiệm của tôi. – Cass

+0

Tôi chỉ đang tìm kiếm sự khác biệt và/hoặc trường hợp sử dụng cho hai biến thể này và khi nào sử dụng, nhờ lời giải thích này. – Zelphir

+0

Theo các tài liệu chính thức, bạn không nên * có * để thêm 'user_setup' vào mỗi chức năng kiểm tra khi chúng được nhóm lại trong một lớp được trang trí bằng' @ pytest.mark.usefixtures': “Do điểm đánh dấu usefixtures, Cleandir fixture sẽ được yêu cầu cho việc thực hiện của mỗi phương pháp thử nghiệm, giống như khi bạn đã chỉ định một đối số hàm “cleandir” cho mỗi đối tượng. ”(Nguồn: http://pytest.org/latest/fixture.html#using-fixtures -from-classes-modules-or-projects) Sau khi tất cả, toàn bộ các điểm kiểm tra nhóm như thế này là để thao tác chúng như là một lô.) ... Có lẽ đây là một lỗi pytest? – Zearin

-1

Trong cả hai trường hợp, trong phạm vi toàn cầuuser_setup là hàm. Sự khác biệt là, trong phiên bản nonfixture của bạn, bạn đang tạo một tham số có cùng tên, đó là một công thức cổ điển cho sự nhầm lẫn.

Trong phiên bản nonfixture đó, trong phạm vi test_user, số nhận dạng user_setup của bạn đề cập đến bất kỳ điều gì bạn đang truyền, không phải là hàm trong phạm vi toàn cầu.

Tôi nghĩ rằng bạn có thể có nghĩa là để được gọi user_setup và subscripting kết quả như

assert user_setup()['name'] == 'chad' 
Các vấn đề liên quan