2013-08-02 45 views
43

Tôi đang sử dụng py.test để kiểm tra một số mã DLL được bao bọc trong một lớp python MyTester. Để xác thực mục đích, tôi cần đăng nhập một số dữ liệu thử nghiệm trong quá trình thử nghiệm và thực hiện nhiều thao tác sau đó. Vì tôi có nhiều tệp thử nghiệm _... tôi muốn sử dụng lại việc tạo đối tượng thử nghiệm (ví dụ của MyTester) cho hầu hết các thử nghiệm của tôi.py.test: Chuyển một tham số đến hàm cố định

Khi đối tượng thử nghiệm là đối tượng có tham chiếu đến các biến và hàm của DLL, tôi cần chuyển danh sách các biến của DLL cho đối tượng thử nghiệm cho từng tệp kiểm tra (các biến được ghi là giống nhau cho một tập tin thử nghiệm _...). Nội dung của danh sách sẽ được sử dụng để ghi dữ liệu được chỉ định.

Ý tưởng của tôi là để làm điều đó bằng cách nào đó như thế này:

import pytest 

class MyTester(): 
    def __init__(self, arg = ["var0", "var1"]): 
     self.arg = arg 
     # self.use_arg_to_init_logging_part() 

    def dothis(self): 
     print "this" 

    def dothat(self): 
     print "that" 

# located in conftest.py (because other test will reuse it) 

@pytest.fixture() 
def tester(request): 
    """ create tester object """ 
    # how to use the list below for arg? 
    _tester = MyTester() 
    return _tester 

# located in test_...py 

# @pytest.mark.usefixtures("tester") 
class TestIt(): 

    # def __init__(self): 
    #  self.args_for_tester = ["var1", "var2"] 
    #  # how to pass this list to the tester fixture? 

    def test_tc1(self, tester): 
     tester.dothis() 
     assert 0 # for demo purpose 

    def test_tc2(self, tester): 
     tester.dothat() 
     assert 0 # for demo purpose 

Có thể đạt được nó như thế này hoặc là có ngay cả một cách thanh lịch hơn?

Thông thường tôi có thể làm điều đó cho mỗi phương pháp thử nghiệm với một số loại chức năng thiết lập (xUnit-style). Nhưng tôi muốn đạt được một số loại tái sử dụng. Có ai biết nếu điều này là có thể với đồ đạc ở tất cả?

Tôi biết tôi có thể làm điều gì đó như thế này: (từ các tài liệu)

@pytest.fixture(scope="module", params=["merlinux.eu", "mail.python.org"]) 

Nhưng tôi cần đến parametrization trực tiếp trong các mô-đun thử nghiệm. Có thể truy cập thuộc tính params của vật cố từ mô-đun thử nghiệm không?

Trả lời

45

Tôi gặp vấn đề tương tự - Tôi có một vật cố gọi là test_package và sau đó tôi muốn có thể chuyển đối số tùy chọn cho vật cố đó khi chạy nó trong các thử nghiệm cụ thể. Ví dụ:

@pytest.fixture() 
def test_package(request, version='1.0'): 
    ... 
    request.addfinalizer(fin) 
    ... 
    return package 

(Nó không quan trọng cho những mục đích này hoặc loại đối tượng trả lại package) là gì. Sau đó, nó sẽ được mong muốn bằng cách nào đó sử dụng vật cố định này trong một chức năng thử nghiệm theo cách mà tôi cũng có thể chỉ định đối số version cho vật cố đó để sử dụng với thử nghiệm đó. Hiện tại, điều này là không thể, mặc dù có thể tạo ra một tính năng tuyệt vời.

Trong khi đó nó đã được dễ dàng, đủ để làm cho trận đấu của tôi chỉ đơn giản là trả lại một chức năng mà làm tất cả các công việc cố định đã làm trước đó, nhưng cho phép tôi để xác định version luận:

@pytest.fixture() 
def test_package(request): 
    def make_test_package(version='1.0'): 
     ... 
     request.addfinalizer(fin) 
     ... 
     return test_package 

    return make_test_package 

Bây giờ tôi có thể sử dụng chức năng này trong hàm thử nghiệm của tôi như:

def test_install_package(test_package): 
    package = test_package(version='1.1') 
    ... 
    assert ... 

v.v.

giải pháp cố gắng OP của đội đầu đi đúng hướng, và như @ của answer gợi ý hpk42, các MyTester.__init__ chỉ có thể lưu trữ ra khỏi một tham chiếu đến các yêu cầu như:

class MyTester(object): 
    def __init__(self, request, arg=["var0", "var1"]): 
     self.request = request 
     self.arg = arg 
     # self.use_arg_to_init_logging_part() 

    def dothis(self): 
     print "this" 

    def dothat(self): 
     print "that" 

Sau đó sử dụng để thực hiện các vật cố như :

@pytest.fixture() 
def tester(request): 
    """ create tester object """ 
    # how to use the list below for arg? 
    _tester = MyTester(request) 
    return _tester 

Nếu muốn lớp MyTester có thể được sắp xếp lại một chút để thuộc tính .args của nó có thể được cập nhật sau khi nó đã được tạo ra, để tinh chỉnh các hành vi cho individ kiểm tra ual.

+0

Cảm ơn gợi ý với hàm bên trong lịch thi đấu. Đã mất một thời gian cho đến khi tôi có thể làm việc trên này một lần nữa nhưng điều này là khá hữu ích! – maggie

10

Bạn có thể truy cập mô-đun/lớp/chức năng yêu cầu từ chức năng lịch thi đấu (và từ lớp Tester), xem interacting with requesting test context from a fixture function. Vì vậy, bạn có thể khai báo một số tham số trên một lớp hoặc mô-đun và thử nghiệm vật cố có thể nhặt nó lên.

+3

Tôi biết tôi có thể làm một cái gì đó như thế này: (từ các tài liệu) @ pytest.fixture (phạm vi = "module", params = [ "merlinux. eu "," mail.python.org "]) Nhưng tôi cần làm điều đó trong mô-đun thử nghiệm. Làm thế nào tôi có thể tự động thêm thông số vào đồ đạc? – maggie

+1

Điểm không nhất thiết phải * tương tác với yêu cầu ngữ cảnh thử nghiệm * từ một hàm cố định nhưng để có một cách được xác định rõ ràng để chuyển các đối số đến một hàm cố định. Chức năng Lịch thi đấu không cần phải biết về một loại ngữ cảnh thử nghiệm yêu cầu chỉ để có thể nhận các đối số với các tên đã được đồng ý. Ví dụ, người ta muốn có thể viết '@fixture def my_fixture (yêu cầu)' và sau đó '@pass_args (arg1 = ..., arg2 = ...) def test (my_fixture)' và nhận các arg này trong 'my_fixture() 'như thế này' arg1 = request.arg1, arg2 = request.arg2'. Là một cái gì đó như thế này có thể trong py.test bây giờ? –

61

Điều này thực sự được hỗ trợ nguyên bản trong py.test thông qua indirect parametrization.

Trong trường hợp của bạn, bạn sẽ phải:

@pytest.fixture 
def tester(request): 
    """Create tester object""" 
    return MyTester(request.param) 


class TestIt: 
    @pytest.mark.parametrize('tester', [['var1', 'var2']], indirect=True) 
    def test_tc1(self, tester): 
     tester.dothis() 
     assert 1 
+0

Ah, điều này là khá tốt đẹp (tôi nghĩ rằng ví dụ của bạn có thể là một chút lỗi thời mặc dù - nó khác với các ví dụ trong các tài liệu chính thức). Đây có phải là một tính năng tương đối mới không? Tôi chưa bao giờ gặp nó trước đây. Đây là một giải pháp tốt cho vấn đề này - theo một số cách tốt hơn câu trả lời của tôi. – Iguananaut

+0

Tôi đã thử sử dụng giải pháp này nhưng gặp sự cố khi truyền nhiều thông số hoặc sử dụng tên biến khác ngoài yêu cầu. Tôi đã kết thúc bằng cách sử dụng giải pháp của @Iguananaut. –

+14

** Đây phải là câu trả lời được chấp nhận. ** [Tài liệu chính thức] (http://docs.pytest.org/en/latest/example/parametrize.html#deferring-the-setup-of-parametrized-resources) đối số từ khóa 'gián tiếp 'được thừa nhận là thưa thớt và không thân thiện, có lẽ là tài khoản cho sự tối nghĩa của kỹ thuật thiết yếu này. Tôi đã lùng sục trang web py.test nhiều lần cho tính năng này rất nhiều - chỉ để trống rỗng, lớn tuổi hơn và lúng túng. Sự đắng đắng là một nơi được gọi là tích hợp liên tục. _Cảm ơn Odin cho Stackoverflow._ –