Faced such complexity to generate test data in pytest. I read the key-value pair from a text file (json), and with the help of yield I pass it to the pytest fixture as follows:

def read_list(): with open(config.testfile) as f: data = json.load(f) dct = {line['fullname']: line['val'] for line in data} for res in dct: yield res, dct[res] @pytest.mark.parametrize('name, val', read_list()) def test_task_waiting(driver, name, val): assert create_task(driver, name, val) 

The problem is that when you restart, the test is run by the parameters in the same order in which they are in the original json file. How can I apply a random element from the dct dictionary to the input of the test function? I tried random.choice, but it returns a random value only once, the task failed with the fly.

  • Generally speaking, tests should not operate on random data. For example, the RNG may not produce a single even number for several tests (which would break the code). And when it does, you will have to break your head once more, why did the tests pass before. - Kromster

2 answers 2

It is possible to randomly select one element at each iteration using the choice , and remove it from the dictionary - for example, in this case it is convenient to do this using pop :

 import random def read_list(): dct = {'a': 1, 'b': 2, 'c': 3, 'd': 4} while dct: key = random.choice(list(dct.keys())) value = dct.pop(key) yield key, value print([item for item in read_list()]) 

Or you can simply mix the elements of the dictionary:

 import random def read_list(): dct = {'a': 1, 'b': 2, 'c': 3, 'd': 4} items = list(dct.items()) random.shuffle(items) for (key, value) in items: yield key, value print([item for item in read_list()]) 
  • Thanks, helped! Interestingly, under unix, the problem was irrelevant - each time I started, my initial version gave a random parameter each time, and the poppy required the proposed update. - Alexander Svezhentcev
  • Yes, it may depend on the interpreter. In general, the dictionary is not guaranteed to preserve the order of the elements. But some interpreters implement the internal mechanics of the dictionary in such a way that order is preserved. However, you need to understand that even if order is not maintained in the dictionary, it will not be complete random mixing. Therefore, if you really want a random order, then in any case it is better to mix yourself. - Xander

It seems to me that the dictionary data structure is not suitable for "accidental" removal. Put variables into lists, for example:

 arg = {"a": [1, 2, 3], "b": [4, 5, 6]} 

Assign in the code values ​​for the variables from those specified in json before the test:

 import random a = arg["a"][random.randint(0, len(arg["a"]) - 1)] b = arg["b"][random.randint(0, len(arg["b"]) - 1)] print a, b # 1, 5