Оновлення: Оскільки це прийнята відповідь на це питання і все ще іноді отримує надмірну оцінку, я повинен додати оновлення. Хоча мій початковий відповідь (нижче) був єдиним способом зробити це в більш старих версіях pytest , як інші вже зазначив pytest тепер підтримує непряму параметризацію світильників. Наприклад, ви можете зробити щось подібне (через @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
Однак, хоча ця форма непрямої параметризації є явною, як зазначає @Yukihiko Shinoda , вона тепер підтримує форму неявної непрямої параметризації (хоча я не могла знайти жодних очевидних посилань на це в офіційних документах):
# 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
Я точно не знаю, що таке семантика цієї форми, але, схоже, pytest.mark.parametrize
визнається, що, хоча test_tc1
метод не бере аргумент, названий tester_arg
, tester
арматура, яку він використовує, робить, тому він передає параметризований аргумент через tester
кріплення.
У мене була подібна проблема - у мене викликається кріплення test_package
, і пізніше я хотів мати можливість передавати необов'язковий аргумент цьому кріпленню під час його запуску в конкретних тестах. Наприклад:
@pytest.fixture()
def test_package(request, version='1.0'):
...
request.addfinalizer(fin)
...
return package
(Для цих цілей не має значення, чим займається кріплення або який об’єкт повертається package
).
Тоді було б бажано якось використовувати це кріплення в тестовій функції таким чином, щоб я міг також вказати version
аргумент до цього кріплення для використання з цим тестом. Наразі це неможливо, хоча це може зробити приємну функцію.
Тим часом було досить просто зробити так, щоб мій кріплення просто повернув функцію, яка виконує всю роботу, яку раніше виконував кріплення, але дозволяє мені вказати version
аргумент:
@pytest.fixture()
def test_package(request):
def make_test_package(version='1.0'):
...
request.addfinalizer(fin)
...
return test_package
return make_test_package
Тепер я можу використовувати це у своїй тестовій функції, наприклад:
def test_install_package(test_package):
package = test_package(version='1.1')
...
assert ...
і так далі.
Спроба рішення ОП була спрямована в правильному напрямку, і як підказує відповідь @ hpk42 , MyTester.__init__
може просто зберегти посилання на запит, наприклад:
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"
Потім використовуйте це для реалізації кріплення на зразок:
@pytest.fixture()
def tester(request):
""" create tester object """
# how to use the list below for arg?
_tester = MyTester(request)
return _tester
За бажанням MyTester
клас можна трохи переструктурувати, щоб його .args
атрибут можна було оновити після його створення, щоб змінити поведінку для окремих тестів.