Python 单元测试文件写入
我正在为Python中的ConfigParser
写一个封装器,目的是提供一个简单的接口来存储和获取应用程序的设置。
这个封装器有两个方法,分别是read
和write
,还有一组属性用来处理不同的应用设置。
其中,write
方法其实就是对ConfigParser
的write
方法的封装,额外的功能是创建ConfigParser
所需的文件对象。它的代码大致是这样的:
def write(self):
f = open(self.path, "w")
try:
self.config_parser.write(f)
finally:
f.close()
我想写一个单元测试,来验证这个方法在无法写入文件时会抛出IOError,同时在其他情况下,确认配置解析器的写入方法被调用了。
第二个测试相对简单,可以用一个模拟对象来处理。但是open
这个调用就有点麻烦了。最终我需要创建一个文件对象来传递给配置解析器。实际上在运行这段代码时会创建一个文件,这让它在单元测试中不太实用。有没有什么策略可以模拟文件的创建?这段代码能以某种方式进行测试吗?还是说它太简单了,不值得测试?
3 个回答
记住,你不需要测试 open() 或 ConfigParser 这些功能,因为它们不是你自己写的代码。你只需要确保你正确地使用了它们。你可以用自己的 open() 来替换这个模块,就像替换实例属性一样,这样你就可以返回一个模拟的结果,帮助你进行测试。
不过,单元测试并不是我唯一的工具,这个函数足够简单,可以直接分析和“证明”它是有效的。
虽然这种证明方式可能没有数学家们想要的那么严格,但对我来说已经足够了。
其实,只有打开文件的那部分代码可能会出错。关于写入(write())的文档没有提到会有异常。可能只有在文件指针不对的时候会出现一个ValueError(这通常是因为打开文件失败,但在这里不可能出现这种情况)。
让打开文件时出现IOError其实很简单。你可以在其他地方创建这个文件,然后在那里打开它进行写入。或者你可以更改文件的权限,让你没有访问权限。
不过你可能想在这里使用with
语句,这样它会自动处理文件的关闭。
在Python 2.5中,你需要第一行代码。在后来的版本中就不需要了。
from __future__ import with_statement # python 2.5 only
def write(self):
with open(self.path, 'w') as f:
self.config_parser.write(f)
如果open
成功,写入方法一定会被调用;如果open
抛出一个IOError
,那么写入方法就不会被调用。我不知道你为什么需要测试写入是否被调用。代码已经说明它会被调用。别过于测试了。;)
首先,其实你并不需要对 open()
进行单元测试,因为我们可以合理地认为标准库是正确的。
接下来,你也不想通过操作文件系统来让 open()
产生你想要的错误,因为那样你就不是在做单元测试,而是在做功能测试或集成测试,因为你涉及到了文件系统。
所以,你可以考虑在全局范围内用一个替代品替换 open()
,这个替代品只会抛出一个 IOError
。不过,执行完后可能需要确保把东西恢复回来。
但最终,这个测试有什么价值呢?在那个代码片段中,几乎没有你自己系统的东西。即使替换了 open()
,其实也只是测试“Python中的 try
和 finally
语句是否有效?”
我的建议是?在文档字符串中加一句记录你的期望。“如果文件无法写入,则抛出一个 IOError。”然后就可以继续了。如果这个方法后面变得复杂(并且值得测试),你可以再添加单元测试。