我正在尝试对采用文件路径并返回一些文件内容的解析函数进行单元测试。我希望能够将这些函数字符串传递给测试目的。
据我所知,我可以将csv.reader()传递给StringIO或file_handle(例如csv.reader(StringIO(“my,data”)或csv.reader(open(file))),但我不能看到一种方法,我可以传递一个StringIO对象代替文件路径,因为open(StringIO(“my,data”))失败。同样我希望在这些解析中有文件打开/关闭逻辑方法而不是我的代码的主要部分,因为这会混乱我的主要代码,也意味着我必须重新编写所有文件IO接口!
似乎我的选择是:
import csv
def parse_file(input):
with open(input, 'r') as f:
reader = csv.reader(f)
output = []
for row in reader:
#Do something complicated
output.append(row)
return output
import unittest
class TestImport(unittest.TestCase):
def test_read_string(self):
string_input = u"a,b\nc,d\n"
output = read_file(string_input)
self.assertEqual([['a', 'b'], ['c', 'd']], output)
def test_read_file(self):
filename = "sample_data.csv"
output = read_file(filename)
self.assertEqual([['a', 'b'],['c', 'd']], output)
答案 0 :(得分:3)
您可以使用temporary files。
如果您真的不想使用硬盘,可以使用StringIO替换文件,并重新定义内置open
函数,如下所示:
import StringIO
import csv
#this function is all you need to make your code work with StringIO objects
def replaceOpen():
#the next line redefines the open function
oldopen, __builtins__.open = __builtins__.open, lambda *args, **kwargs: args[0] if isinstance(args[0], StringIO.StringIO) else oldopen(*args, **kwargs)
#these methods below have to be added to the StringIO class
#in order for the with statement to work
StringIO.StringIO.__enter__ = lambda self: self
StringIO.StringIO.__exit__ = lambda self, a, b, c: None
replaceOpen()
#after the re-definition of open, it still works with normal paths
with open(__file__, 'rb') as f:
print f.read(16)
#and it also works with StringIO objects
sio = StringIO.StringIO('1,2\n3,4')
with open(sio, 'rb') as f:
reader = csv.reader(f)
output = []
for row in reader:
output.append(row)
print output
输出:
import StringIO
[['1', '2'], ['3', '4']]
答案 1 :(得分:1)
如果您不想更改接口以接受#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int main(string name)
{
cout << "What is your name?" << endl;
cin >> name;
cout << endl << "Your name is " << name << "." << endl;
return 0;
}
等开放文件对象,请查看testfixtures module。我已经用它来管理单元测试的文件和目录,虽然我通常更喜欢传入StringIO
个对象。
如果您不喜欢这样,那么修补StringIO
听起来像是一个合理的策略。我自己还没有尝试过。
答案 2 :(得分:0)
对于将来寻找此事的其他人,我能够使用Mock非常有效地完成这项工作。
---- module: import_data.py -----
import csv
def read_file(input):
with open(input, 'r') as f:
reader = csv.reader(f)
output = []
for row in reader:
#Do something complicated
output.append(row)
return output
---- Unittests ----
import unittest
from io import StringIO
from mock import patch
from import_data import read_file
class TestImport(unittest.TestCase):
@patch('import_data.open')
def test_read_string(self, mock_file):
mock_file.return_value = StringIO(u"a,b\nc,d")
output = read_file(None)
self.assertEqual([['a', 'b'], ['c', 'd']], output)
def test_read_file(self):
filename = "sample_data.csv"
output = read_file(filename)
self.assertEqual([['a', 'b', 'c'],['d', 'e', 'f']], output)