'Finding inputs of every possible test case [duplicate]

Let's say I have a Python program that takes in ~40 user inputs and returns a prediction on their lifespan. The user inputs are mainly categorical or finite such as sex, smoking status, and birth year.

I want to maximize my test cases by testing all the acceptable values for each field, such as sex:['Male', 'Female', None]. Is there a good way to do this without using dozens of nested for loops? For example, an itertools function. I'm thinking of something like scikit-learn's grid search where you list the acceptable values and it initiates a hyperparameter optimization by checking all possible combinations

I want to avoid:

for sex in ['male', 'female', None]:
    for smoking_status in ['smoker', 'non-smoker', None]:
        for birth_year in [1900, ..., 2022, None]:
           assert(myfunc(sex, smoking_status, birth_year) == trueOutput)

Assume trueOutput is dynamic and always gives the correct value (I plan to cross-reference Python output to an Excel spreadsheet and rewrite the Excel inputs for every test case to get the updated output). I also plan to write every possible test case to JSON files that would represent a specific user's data so I can test the cases that failed



Solution 1:[1]

You want to use itertools.product like so:

sex = ['m', 'f', None]
smoking = ['smoker', 'non-smoker', None]
birth = [1999, 2000, 2001, None]

for item in itertools.product(sex, smoking, birth):
    print(item)

to pass the arguments to your function, use the spreading operator:

sex = ['m', 'f', None]
smoking = ['smoker', 'non-smoker', None]
birth = [1999, 2000, 2001, None]

for item in itertools.product(sex, smoking, birth):
     assert myfunc(*item) == trueOutput
# or
for se, sm, b in itertools.product(sex, smoking, birth):
     assert myfunc(se, sm, b) == trueOutput

Solution 2:[2]

itertools.product() is exactly what you want, but for additional functionality, collect each choice into a dict

category_inputs_mapping = {
    "gender":     ("male", "female", ..., None),
    "birth_year": sorted(2022 - x for x in range(150)),
    ...
}

Then create a function which generates each possibility for you

def gen_inputs_mapper(d: Dict):
    # opportunity to inspect dict
    for values in itertools.product(*d.values()):
        # opportunity to assert/inspect values
        yield {k: v for k, v in zip(d.keys(), values)}

and finally, get each possibility in turn along with its index

for index, possibility in enumerate(gen_inputs_mapper(category_inputs_mapping)):
    result = myfunc(**possibility)      # unpack dict to args
    assert result = true_output[index]  # nth index from computed sheet

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Schottky
Solution 2 ti7