1

I have written a function that loads a pickled list of dictionaries and optionally filters the result:

def load_pickled_list(path_to_file, filter_key=None):
    with open(path_to_file, "rb") as file:
        loaded_list = pickle.load(file)

    if filter_key is not None:
        loaded_list = [entry for entry in loaded_list if loaded_list[filter_key] == filter_key]

    return loaded_list

How do I test this with pytest by providing two different lists of dictionaries in code? Especially, how do I implement a test double of pickle? I do not want to provide a file such as test_list.pkl so that the test would have to perform real disk IO operations.

LuGeNat
  • 179
  • 1
  • 2
  • 13

1 Answers1

0

If you have a sequence of bytes in mind, you can hard-code it directly into your program using io.BytesIO. The example in the module docs may be what you need, or at least provide a good starting point:

f = io.BytesIO(b"your pickle file here ")
loaded_list = pickle.load(f)

Better than hard-coding the data, have some part of your setup or a fixture generate it:

# make some objects
data = ...
f = io.BytesIO()
pickle.dump(data, f)
f.seek(0)

# now load `f`

You could also avoid the file interface entirely by using dumps/loads to work with bytes directly instead of doing I/O with dump/load.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • Thank you. But now I can't pass `f` into a call of `load_pickled_list` within my test because the function expects a string and not a BytesIO object. – LuGeNat Jun 24 '22 at 15:03
  • @LuGeNat. That's because your function can't handle file objects. I would recommend that you allow it to do that. – Mad Physicist Jun 24 '22 at 15:36
  • @LuGeNat. I'm not aware of any way to pass in an in-memory file without passing either bytes or file-like objects. The only other thing I can think of is adding a prefix to your data to let your function know that it's not really a string it's dealing with: – Mad Physicist Jun 24 '22 at 15:42