python对函数进⾏单元测试_如何使⽤pythonunittest对函数进
⾏单元测试
我有⼀个python函数,它将输出⽂件写⼊磁盘。
我想使⽤python unit test模块为它编写⼀个单元测试。
我应该如何断⾔⽂件的相等性?如果⽂件内容与预期的⼀+差异列表不同,我希望得到⼀个错误。在unix diff命令的输出中。
是否有任何官⽅/推荐的⽅法?
我更喜欢让输出函数显式地接受⽂件句柄(或类似⽂件的对象),⽽不是接受⽂件名并⾃⼰打开⽂件。这样,我可以在单元测试中将⼀个StringIO对象传递给输出函数,然后将该StringIO对象(在.seek(0)调⽤之后)的内容返回到该StringIO对象,并与预期的输出进⾏⽐较。
例如,我们将像这样转换代码
##File:lamb.py
import sys
def write_lamb(outfile_path):
with open(outfile_path, 'w') as outfile:
outfile.write("Mary had a little lamb.
")
if __name__ == '__main__':
write_lamb(sys.argv[1])
##File test_lamb.py
import unittest
python怎么读取py文件
import tempfile
import lamb
class LambTests(unittest.TestCase):
def test_lamb_output(self):
outfile_path = tempfile.mkstemp()[1]
try:
lamb.write_lamb(outfile_path)
contents = open(tempfile_path).read()
finally:
# NOTE: To retain the tempfile if the test fails, remove
# the try-finally clauses
self.assertEqual(result,"Mary had a little lamb.
")
这样编码
##File:lamb.py
import sys
def write_lamb(outfile):
outfile.write("Mary had a little lamb.
")
if __name__ == '__main__':
with open(sys.argv[1], 'w') as outfile:
write_lamb(outfile)
##File test_lamb.py
import unittest
from io import StringIO
import lamb
class LambTests(unittest.TestCase):
def test_lamb_output(self):
outfile = StringIO()
# NOTE: Alternatively, for Python 2.6+, you can use
# tempfile.SpooledTemporaryFile, e.g.,
#outfile = tempfile.SpooledTemporaryFile(10 ** 9)
lamb.write_lamb(outfile)
outfile.seek(0)
content = ad()
self.assertEqual(content,"Mary had a little lamb.
")
这种⽅法还有⼀个额外的好处,那就是,如果您决定不想写⼊⽂件,⽽是使⽤其他缓冲区,那么您的输出函数就更加灵活,因为它将接受所有类似⽂件的对象。
注意,使⽤StringIO假设测试输出的内容可以装⼊主内存。对于⾮常⼤的输出,可以使⽤临时⽂件⽅法(例如
tempfile.spooledtemporaryfile)。
这⽐将⽂件写⼊磁盘要好。如果您正在运⾏⼤量的单元测试,IO到磁盘会导致各种各样的问题,特别是试图清理它们。我有写磁盘的测试,拆卸删除写的⽂件。测试⼀次只能运⾏⼀个,然后在全部运⾏时失败。⾄少在Win机器上使⽤Visual Studio和pytools。此外,速度。
虽然这是⼀个测试单独函数的好解决⽅案,但是在测试程序提供的实际接⼝(例如cli⼯具)时,仍然很⿇烦。
你可以⽤getvalue()代替seek()和read()。
我得到了错误:类型错误:需要unicode参数,得到了'str'
我来这⾥是因为我正试图编写单元测试来遍历和逐个⽂件读取分区的拼花数据集。这需要分析⽂件路径以获取键/值对,以便将分区的适当值分配给(最终)结果熊猫数据帧。写⼊缓冲区虽然很好,但⽆法解析分区值。
@pmende听起来您正在使⽤⼀个需要与实际⽂件系统交互的API。单元测试并不总是适当的测试级别。不在单元测试级别测试代码的所有部分是可以的;在适当的情况下,也应该使⽤集成或系统测试。但是,尝试包含这些部分,并尽可能在边界之间传递简单的值。看到youtube/watch了吗?V= EyAlAl8ELNZK
最后,我使⽤python的tempfile模块随机⽣成临时分区数据集。但你提出了⼀些好的想法。感谢您的输⼊!
最简单的⽅法是编写输出⽂件,然后读取其内容,读取黄⾦(预期)⽂件的内容,并将其与简单字符串相等进⾏⽐较。如果它们相同,请删除输出⽂件。如果他们不同,提出⼀个主张。
这样,当测试完成时,每⼀个失败的测试都将⽤⼀个输出⽂件表⽰,并且您可以使⽤第三⽅⼯具将它
们与黄⾦⽂件进⾏⽐较(Beyond Compare⾮常适合这样做)。
如果您真的想提供⾃⼰的diff输出,请记住python stdlib有difflib模块。python 3.1中新的unittest⽀持包括⼀个assertMultiLineEqual ⽅法,该⽅法使⽤它来显⽰差异,类似于:
def assertMultiLineEqual(self, first, second, msg=None):
"""Assert that two multi-line strings are equal.
If they aren't, show a nice diff.
"""
self.assertTrue(isinstance(first, str),
'First argument is not a string')
self.assertTrue(isinstance(second, str),
'Second argument is not a string')
if first != second:
message = ''.join(difflib.ndiff(first.splitlines(True),
second.splitlines(True)))
if msg:
message +=" :" + msg
self.fail("Multi-line strings are unequal:
" + message)
import filecmp
然后
self.p(path1, path2))
您可以将内容⽣成与⽂件处理分开。这样,您就可以测试内容是否正确,⽽不必乱弄临时⽂件,然后再清理它们。
如果编写⼀个⽣成每⾏内容的⽣成器⽅法,那么您可以有⼀个⽂件处理⽅法,它打开⼀个⽂件并按⾏的顺序调⽤file.writelines()。这两个⽅法甚⾄可以在同⼀个类上:测试代码将调⽤⽣成器,⽣产代码将调⽤⽂件处理程序。
下⾯是⼀个例⼦,展⽰了所有三种测试⽅法。通常,您只需要选择⼀个⽅法,这取决于要测试的类中可⽤的⽅法。
import os
from io import StringIO
from unittest.case import TestCase
class Foo(object):
def save_content(self, filename):
with open(filename, 'w') as f:
self.write_content(f)
def write_content(self, f):
f.ate_content())
def generate_content(self):
for i in range(3):
yield u"line {}
".format(i)
class FooTest(TestCase):
def test_generate(self):
expected_lines = ['line 0
', 'line 1
', 'line 2
']
foo = Foo()
lines = ate_content())
self.assertEqual(expected_lines, lines)
def test_write(self):
expected_text = u"""\
line 0
line 1
line 2
"""
f = StringIO()
foo = Foo()
foo.write_content(f)
self.assertEqual(expected_text, f.getvalue()) def test_save(self):
expected_text = u"""\
line 0
line 1
line 2
"""
foo = Foo()
filename = ''
try:
foo.save_content(filename)
with open(filename, 'rU') as f:
text = f.read()
finally:
self.assertEqual(expected_text, text)
你能提供这个例⼦代码吗?听起来很有趣。
我为这三种⽅法添加了⼀个例⼦,@buhtz。
我总是尽量避免将⽂件写⼊磁盘,即使它是专门⽤于测试的临时⽂件夹:不实际接触磁盘会使测试更快,尤其是在代码中与⽂件进⾏⼤量交互时。
假设您在⼀个名为main.py的⽂件中有⼀个"惊⼈"的软件:
"""
main.py
"""
def write_to_file(text):
with open("","w") as h:
h.write(text)
if __name__ =="__main__":
write_to_file("Every great dream begins with a dreamer.")
要测试write_to_file⽅法,您可以在名为test_main.py的同⼀⽂件夹中编写类似的⽂件:
"""
test_main.py
"""
k import patch, mock_open
import main
def test_do_stuff_with_file():
open_mock = mock_open()
with patch("main.open", open_mock, create=True):
main.write_to_file("test-data")
open_mock.assert_called_with("","w")
urn_value.write.assert_called_once_with("test-data")

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。