Cập nhật: Vì đây là câu trả lời được chấp nhận cho câu hỏi này và đôi khi vẫn được ủng hộ, tôi nên thêm một bản cập nhật. Mặc dù câu trả lời ban đầu của tôi (bên dưới) là cách duy nhất để thực hiện điều này trong các phiên bản pytest cũ hơn vì những người khác đã lưu ý rằng pytest hiện hỗ trợ tham số gián tiếp của đồ đạc. Ví dụ: bạn có thể làm điều gì đó như thế này (thông qua @imiric):
# test_parameterized_fixture.py
import pytest
class MyTester:
def __init__(self, x):
self.x = x
def dothis(self):
assert self.x
@pytest.fixture
def tester(request):
"""Create tester object"""
return MyTester(request.param)
class TestIt:
@pytest.mark.parametrize('tester', [True, False], indirect=['tester'])
def test_tc1(self, tester):
tester.dothis()
assert 1
$ pytest -v test_parameterized_fixture.py
================================================================================= test session starts =================================================================================
platform cygwin -- Python 3.6.8, pytest-5.3.1, py-1.8.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: .
collected 2 items
test_parameterized_fixture.py::TestIt::test_tc1[True] PASSED [ 50%]
test_parameterized_fixture.py::TestIt::test_tc1[False] FAILED
Tuy nhiên, mặc dù hình thức tham số gián tiếp này là rõ ràng, như @Yukihiko Shinoda chỉ ra rằng nó hiện hỗ trợ hình thức tham số gián tiếp ngầm (mặc dù tôi không tìm thấy bất kỳ tham chiếu rõ ràng nào về điều này trong tài liệu chính thức):
# test_parameterized_fixture2.py
import pytest
class MyTester:
def __init__(self, x):
self.x = x
def dothis(self):
assert self.x
@pytest.fixture
def tester(tester_arg):
"""Create tester object"""
return MyTester(tester_arg)
class TestIt:
@pytest.mark.parametrize('tester_arg', [True, False])
def test_tc1(self, tester):
tester.dothis()
assert 1
$ pytest -v test_parameterized_fixture2.py
================================================================================= test session starts =================================================================================
platform cygwin -- Python 3.6.8, pytest-5.3.1, py-1.8.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: .
collected 2 items
test_parameterized_fixture2.py::TestIt::test_tc1[True] PASSED [ 50%]
test_parameterized_fixture2.py::TestIt::test_tc1[False] FAILED
Tôi không biết chính xác ngữ nghĩa của biểu mẫu này là gì, nhưng có vẻ như nó pytest.mark.parametrize
nhận ra rằng mặc dù test_tc1
phương thức không có đối số được đặt tên tester_arg
, nhưng tester
vật cố định mà nó đang sử dụng thì có, vì vậy nó truyền đối số được tham số hóa qua tester
vật thể.
Tôi đã gặp vấn đề tương tự - tôi có một bộ cố định được gọi test_package
và sau đó tôi muốn có thể chuyển một đối số tùy chọn cho bộ cố định đó 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
(Đối với những mục đích này, vật cố định làm gì hoặc loại đối tượng nào được trả về không quan trọng package
).
Sau đó, tôi mong muốn bằng cách nào đó sử dụng vật cố định này trong một hàm thử nghiệm theo cách mà tôi cũng có thể chỉ định version
đối số cho vật cố định đó để sử dụng với thử nghiệm đó. Điều này hiện không thể thực hiện được, mặc dù có thể tạo ra một tính năng tốt.
Trong thời gian chờ đợi, thật dễ dàng để làm cho vật cố định của tôi chỉ cần trả lại một hàm thực hiện tất cả công việc mà vật cố định đã làm trước đó, nhưng cho phép tôi chỉ định version
đối số:
@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 điều này trong chức năng thử nghiệm của mình như:
def test_install_package(test_package):
package = test_package(version='1.1')
...
assert ...
và như thế.
Giải pháp cố gắng của OP đã đi đúng hướng và như câu trả lời của @ hpk42 cho thấy, giải pháp MyTester.__init__
có thể chỉ lưu trữ tham chiếu đến 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 điều này để triển khai các vật cố định 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, MyTester
lớp có thể được cấu trúc lại một chút để .args
thuộc tính của nó có thể được cập nhật sau khi nó được tạo, để điều chỉnh hành vi cho các bài kiểm tra riêng lẻ.