Here's the thing:
I have an Array2D class that receives parameters 'shape' and 'val'. The constructor is as follows:
class Array2D:
def __init__(self, shape: tuple, val):
self.shape = shape
self.size = self.shape[0] * self.shape[1]
self.data = [val] * self.size
I want, for learning reasons, to perform tests in this function. To do this I have declared a variable ARRAY_CONFIG, which lists parameters for different two-dimensional arrays. Here is an example:
ARRAY_CONFIG = [
[(2, 3), 3],
[(2, 3), 1.7]
]
I have also defined other lists that store the expected values for future tests. Take a look:
SIZE = [6, 6]
DATA = [
[3, 3, 3, 3, 3, 3],
[1.7, 1.7, 1.7, 1.7, 1.7, 1.7]
]
Now, I want to build a test function that by the parameterization decorator, makes comparison between these lists. Here is an example without the decorators from the PyTest library:
def test_size_and_data():
for i in range(len(ARRAY_CONFIG)):
array_config = ARRAY_CONFIG[i]
size = SIZE[i]
data = DATA[i]
array = Array2D(*array_config)
assert array.size == size
assert array.data == data
I managed to develop something, but it seems somewhat repetitive to me. Here it is:
def combine(list1, list2):
return [(list1[i], list2[i]) for i in range(len(list1))]
@pytest.fixture
def array(request):
return Array2D(*request.param)
@pytest.mark.parametrize('array, expected', combine(ARRAY_CONFIG, SIZE), indirect=['array'])
def test_size(array, expected):
assert array.size == expected
@pytest.mark.parametrize('array, expected', combine(ARRAY_CONFIG, DATA), indirect=['array'])
def test_data(array, expected):
assert array.data == expected
What is the best way to perform this kind of test where there is a list of "expected values"? I've tried performing two parameterizations, for example, but I end up performing combinations between the values, rather than one-to-one comparisons. As done here:
# Other tests --> generate 4 tests instead of 2
@pytest.fixture(params=ARRAY_CONFIG)
def array(request):
return Array2D(*request.param)
@pytest.fixture
def array_size(array):
return array.size
@pytest.mark.parametrize('expected', SIZE)
def test_size(array_size, expected):
assert array_size == expected
Thanks in advance.
CodePudding user response:
It's much simpler if you use the combine
function as the parameter in parametrize
. You can yield
every set of values
def combine():
for arr, size, data in zip(ARRAY_CONFIG, SIZE, DATA):
yield Array2D(*arr), size, data
@pytest.mark.parametrize('expected', combine())
def test_size_and_data(expected):
array, size, data = expected
print(array.size, size)
print(array.data, data)
Or more explicit parameters
@pytest.mark.parametrize('array, size, data', combine())
def test_size_and_data(array, size, data):
print(array.size, size)
print(array.data, data)
Output
example_test.py::test_size_and_data[expected0] PASSED [ 50%]
6 6
[3, 3, 3, 3, 3, 3] [3, 3, 3, 3, 3, 3]
example_test.py::test_size_and_data[expected1] PASSED [100%]
6 6
[1.7, 1.7, 1.7, 1.7, 1.7, 1.7] [1.7, 1.7, 1.7, 1.7, 1.7, 1.7]
--------------------------------------------------------------
example_test.py::test_size_and_data[array0-6-data0] PASSED [ 50%]
6 6
[3, 3, 3, 3, 3, 3] [3, 3, 3, 3, 3, 3]
example_test.py::test_size_and_data[array1-6-data1] PASSED [100%]
6 6
[1.7, 1.7, 1.7, 1.7, 1.7, 1.7] [1.7, 1.7, 1.7, 1.7, 1.7, 1.7]