Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a gzip file like object for unit testing

Tags:

python

pytest

I want to test a Python function that reads a gzip file and extracts something from the file (using pytest).

import gzip

def my_function(file_path):
    output = []

    with gzip.open(file_path, 'rt') as f:
        for line in f:
            output.append('something from line')

    return output

Can I create a gzip file like object that I can pass to my_function? The object should have defined content and should work with gzip.open()

I know that I can create a temporary gzip file in a fixture but this depends on the filesystem and other properties of the environment. Creating a file-like object from code would be more portable.

like image 841
Martin Preusse Avatar asked Feb 27 '20 15:02

Martin Preusse


People also ask

How do I create a gzip in Python?

When mode parameter is given as 'w' or 'wb' or 'wt', the GipFile object will provide write() method to compress the given data and write to a gzip file. This will create a testnew. txt. gz file.

How does Python gzip work?

The gzip module provides the GzipFile class, as well as the open() , compress() and decompress() convenience functions. The GzipFile class reads and writes gzip-format files, automatically compressing or decompressing the data so that it looks like an ordinary file object.

Is gzip a standard Python library?

This module provides us with high-level functions such as open() , compress() and decompress() , for quickly dealing with these file extensions. Essentially, this will be simply opening a file! There is no need to pip install this module since it is a part of the standard library!


Video Answer


2 Answers

You can use the io and gzip libraries to create in-memory file objects. Example:

import io, gzip

def inmem():
    stream = io.BytesIO()
    with gzip.open(stream, 'wb') as f:
        f.write(b'spam\neggs\n')
    stream.seek(0)
    return stream
like image 144
hoefling Avatar answered Nov 10 '22 05:11

hoefling


You should never try to test outside code in a unit test. Only test the code you wrote. If you're testing gzip, then gzip is doing something wrong (they should be writing their own unit tests). Instead, do something like this:

from unittest import mock

@mock.Mock('gzip', return_value=b'<whatever you expect to be returned from gzip>')
def test_my_function(mock_gzip):
    file_path = 'testpath'
    output = my_function(file_path=file_path)
    mock_gzip.open.assert_called_with(file_path)
    assert output == b'<whatever you expect to be returned from your method>'

That's your whole unit test. All you want to know is that gzip.open() was called (and you assume it works or else gzip is failing and that's their problem) and that you got back what you expected from the method being tested. You specify what gzip returns based on what you expect it to return, but you don't actually call the function in your test.

like image 37
Blairg23 Avatar answered Nov 10 '22 05:11

Blairg23