Pembaruan: Karena ini adalah jawaban yang diterima untuk pertanyaan ini dan kadang-kadang masih mendapat suara positif, saya harus menambahkan pembaruan. Meskipun jawaban asli saya (di bawah) adalah satu-satunya cara untuk melakukan ini di versi pytest yang lebih lama karena yang lain telah mencatat pytest sekarang mendukung parametriisasi perlengkapan tidak langsung. Misalnya Anda dapat melakukan sesuatu seperti ini (melalui @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
Namun, meskipun bentuk parametrization tidak langsung adalah eksplisit, seperti @Yukihiko Shinoda menunjukkan sekarang mendukung bentuk parametrization tidak langsung implisit (meskipun saya tidak bisa menemukan referensi yang jelas untuk ini di dokumentasi resmi):
# 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
Saya tidak tahu persis apa semantik dari formulir ini, tetapi tampaknya pytest.mark.parametrize
mengakui bahwa meskipun test_tc1
metode tidak mengambil argumen bernama tester_arg
, tester
fixture yang digunakan tidak, sehingga meneruskan argumen parametrized melalui tester
fixture.
Saya memiliki masalah yang sama - saya memiliki fixture yang dipanggil test_package
, dan saya kemudian ingin memberikan argumen opsional ke fixture tersebut saat menjalankannya dalam tes tertentu. Sebagai contoh:
@pytest.fixture()
def test_package(request, version='1.0'):
...
request.addfinalizer(fin)
...
return package
(Tidak masalah untuk tujuan ini apa yang dilakukan fixture atau jenis objek yang dikembalikan package
).
Maka akan diinginkan untuk entah bagaimana menggunakan perlengkapan ini dalam fungsi uji sedemikian rupa sehingga saya juga dapat menentukan version
argumen ke perlengkapan itu untuk digunakan dengan tes itu. Ini saat ini tidak memungkinkan, meskipun mungkin merupakan fitur yang bagus.
Sementara itu, cukup mudah untuk membuat perlengkapan saya mengembalikan fungsi yang melakukan semua pekerjaan fixture sebelumnya, tetapi memungkinkan saya untuk menentukan version
argumen:
@pytest.fixture()
def test_package(request):
def make_test_package(version='1.0'):
...
request.addfinalizer(fin)
...
return test_package
return make_test_package
Sekarang saya dapat menggunakan ini dalam fungsi pengujian saya seperti:
def test_install_package(test_package):
package = test_package(version='1.1')
...
assert ...
dan seterusnya.
Solusi yang dicoba OP sedang menuju ke arah yang benar, dan seperti yang disarankan oleh jawaban @ hpk42 , MyTester.__init__
itu hanya dapat menyimpan referensi ke permintaan seperti:
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"
Kemudian gunakan ini untuk mengimplementasikan perlengkapan seperti:
@pytest.fixture()
def tester(request):
""" create tester object """
# how to use the list below for arg?
_tester = MyTester(request)
return _tester
Jika diinginkan, MyTester
kelas dapat direstrukturisasi sedikit sehingga .args
atributnya dapat diperbarui setelah dibuat, untuk menyesuaikan perilaku pengujian individual.