[英]Save a pandas df into a file-like object with gzip compression
[英]Create a gzip file like object for unit testing
我想測試一個 Python 函數,它讀取一個 gzip 文件並從文件中提取一些東西(使用 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
我可以創建一個 gzip 文件,比如我可以傳遞給my_function
對象嗎? 該對象應已定義內容並應與gzip.open()
我知道我可以在夾具中創建一個臨時 gzip 文件,但這取決於文件系統和環境的其他屬性。 從代碼創建類似文件的對象會更便攜。
您永遠不應該嘗試在單元測試中測試外部代碼。 只測試你寫的代碼。 如果您正在測試gzip
,則gzip
做錯了(他們應該編寫自己的單元測試)。 相反,請執行以下操作:
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>'
這就是你的整個單元測試。 您只想知道gzip.open()
已被調用(並且您假設它有效,否則gzip
失敗了,這就是他們的問題)並且您從被測試的方法中得到了您期望的結果。 您可以根據期望返回的內容指定gzip
返回的內容,但實際上並未在測試中調用該函數。
這有點冗長,但我會做這樣的事情(我假設您將 my_function 保存到名為 patch_one.py 的文件中):
import patch_one # this is the file with my_function in it
from unittest.mock import patch
from unittest import TestCase
class MyTestCase(TestCase):
def test_my_function(self):
# because you used "with open(...) as f", we need a mock context
class MyContext:
def __enter__(self, *args, **kwargs):
return [1, 2] # note the two items
def __exit__(self, *args, **kwargs):
return None
# in case we want to know the arguments to open()
open_args = None
def f(*args, **kwargs):
def my_open(*args, **kwargs):
nonlocal open_args
open_args = args
return MyContext()
return my_open
# patch the gzip.open in our file under test
with patch('patch_one.gzip.open', new_callable=f):
# finally, we can call the function we want to test
ret_val = patch_one.my_function('not a real file path')
# note the two items, corresponding to the list in __enter__()
self.assertListEqual(['something from line', 'something from line'], ret_val)
# check the arguments, just for fun
self.assertEqual('rt', open_args[1])
如果你想嘗試更復雜的東西,我建議你閱讀 unittest 模擬文檔,因為你如何導入“patch_one”文件和你傳遞給 patch() 的字符串一樣重要。
肯定有辦法用 Mock 或 MagicMock 做到這一點,但我發現它們有點難以調試,所以我走了很長一段路。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.