python - 单元测试 - 用 StringIO 对象替换文件路径

标签 python unit-testing csv stream stringio

我正在尝试对采用文件路径并返回一些文件内容的解析函数进行单元测试。我希望能够将这些函数数据字符串传递给测试目的。

我知道我可以传递 csv.reader() StringIO 或 file_handle(例如 csv.reader(StringIO("my,data") 或 csv.reader(open(file))),但我不能看到一种方法,我可以传递一个 StringIO 对象来代替 filepath,因为 open(StringIO("my, data")) 失败了。同样,我想在这些解析中有文件打开/关闭逻辑方法,而不是在我的主要代码中,因为那样会使我的主要代码困惑,也意味着我必须重写所有文件 IO 接口(interface)!

看来我的选择是:

  1. 重写所有现有代码,以便将文件句柄传递给解析函数 - 这真的很痛苦!
  2. 使用 mock.patch() 替换 open() 方法 - 这应该可行,但似乎比此任务所需的复杂得多!
  3. 做一些我尚未想到但确信一定存在的事情!

    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)

最佳答案

您可以使用 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']]

关于python - 单元测试 - 用 StringIO 对象替换文件路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40963128/

相关文章:

python - Selenium Threads : How to open the same browser in multiple threads? 为每个浏览器使用唯一的代理

python - python格式日期时间的问题

python - 是否可以在 Django/South 中设置 SQL Server 查询超时?

javascript - 让 YUI TestLogger 仅显示失败的测试?

java - 解析单个 CSV 行

python - MySql FetchMany 内存问题

asp.net - 代码覆盖率工具

java - 当方法位于基类内部并且测试方法类扩展它时,如何在 JUnit 中模拟方法调用?

r - 将数组写入 CSV,col.names = F 的意外行为

java - 在java中创建.CSV文件的最佳方法