以可模拟/可测试的方式连接文件

时间:2013-11-08 03:28:27

标签: python unit-testing io mocking

我有一个用例,我有一堆文件,我需要顺序连接,删除每个文件后连接到输出。代码看起来像这样:

def compile(self):
    with open("output.file", "wb") as outfile:
        for part in sorted(self.parts):
            with open(part, "rb") as infile:
                for line in infile:
                    outfile.write(line)

            os.remove(part)

    # do other logic ...

我很难想出一种正确测试此代码的方法。我想确定:

  1. 按顺序对零件进行排序和循环。
  2. 逐行读取每个输入文件并将其写入输出文件。
  3. 用尽后,每个输入文件都会被删除。
  4. 我的主要困难是模拟文件对象。我正在使用Python的mock库,但我不确定在哪里修补以及如何实现它。如何修补文件对象以确保所有内容都正确写入?

1 个答案:

答案 0 :(得分:1)

你真的不想测试'open','os.remove','sorted'实际上正在工作,可以安全地假设因为它们是python标准库的一部分,所以它们已经很重在别处测试过你真正想要的只是测试它们实际上是否被调用,所以你可以简单地在你的测试代码中模拟这些调用,并测试它们实际上是用你期望的args调用的。

测试可能类似于

@mock.patch.object(os, 'remove')
@mock.patch('%s.sorted' % __name__, create=True)
@mock.patch('%s.open' % __name__, create=True)
def test_compile(mock_open, mock_sort, mock_os_remove):
    mock_sort.return_value = ['parts']
    compile()
    mock_open.assert_any_call('output.file', 'wb')
    mock_sorted.assert_called_with(['parts'])
    mock_os_remove.assert_called_with('parts','rb')

显然这需要稍微调整一下,因为compile()似乎是一个方法而不是一个独立的函数,但补丁和函数的一般方法应该是相同的。