Использование pytest на диапазонах многих параметров
Допустим, у меня есть Simulation
объект, основной атрибут которого представляет собой словарь параметров, который принимает что-то вроде следующей формы:
@pytest.fixture
def param_base():
'''Dict of parameter defaults'''
return {
"fs" : 2e4,
"sweep_length" : 1,
"num_trials" : 300,
...
"pool_tau" : 1.00,
"quantal_size" : -10,
"a_tau" : (0.001,0.005)
}
Я хотел бы написать функцию pytest, которая просто запускает это моделирование с диапазоном значений для каждого из этих параметров. Несколько иначе структурированный словарь может заключить эту идею:
@pytest.fixture
def param_ranges():
'''Dict of parameter ranges'''
p_name = [
"cav_p_open",
"num_trials",
"num_stim",
"num_cav",
"cav_i",
"num_cav_ratio",
"vesicle_prox",
]
p_sets = [
[0,0.01,0.99,1], #cav_p_open
[1,10,300], #num_trials
[1,2,5], #num_stim
[1,3,10], #num_cav
[0,1,5,10], #cav_i
[1,2], #num_cav_ratio
[0,0.01,0.25,1], #vesicle_prox
]
return dict(zip(p_name,p_sets))
Важно отметить, что я НЕ хочу запускать все комбинации всех этих параметров, поскольку число симуляций растет слишком быстро. Я хочу изменять только один параметр за раз, оставляя другие параметры по умолчанию.
Мое текущее решение заключается в следующем (продолжение после кода выше):
parameter_names = [
"cav_p_open",
"num_trials",
"num_stim",
"num_cav",
"cav_i",
"num_cav_ratio",
"vesicle_prox",
]
@pytest.mark.parametrize("p_name", parameter_names)
def test_runModel_range_params(p_name,param_ranges,param_base):
alt_params = copy.deepcopy(param_base)
p_range = param_ranges[p_name]
for i in range(len(p_range)):
alt_params[p_name] = p_range[i]
SIM = utils.Simulation(params = alt_params)
Это работает довольно хорошо, но поскольку я перебираю все диапазоны параметров, я могу видеть только сбой кода, потому что utils.Simulation
потерпел неудачу при некотором значении определенного параметра, не зная, на каком именно он произошел.
Поэтому я думаю, что я ищу что-то вроде вложенной версии pytest.mark.parameterize
где я могу бежать test_runModel_range_params
на каждом из значений диапазона для каждого параметра.
Есть идеи? Дополнительные очки за элегантность!
1 ответ
Я думаю, что вы ищете, это сложенная параметризация. Из документов:
Чтобы получить все комбинации нескольких параметризованных аргументов, вы можете сложить параметризованные декораторы:
import pytest
@pytest.mark.parametrize("control_var1, control_var2", [(0, 1), ('b','a')])
@pytest.mark.parametrize("default_var1, default_var2", [(2, 3), ('b','a')])
def test_foo(control_var1, control_var2, default_var1, default_var2):
pass