如何使用像doctest,unittest,nose等测试框架测试Python脚本的STDOUT输出?例如,说运行我的脚本“todo.py --list”应该返回“取出垃圾”。我读过一些人,他将脚本的STDOUT打印部分从生成要打印的输出的部分中分离出来。我习惯在我的shell脚本周围喷洒打印语句。这是否仅仅是TDD不友好的习惯,我应该打破,还是有办法轻松测试正确的打印输出吗?测试Python脚本
回答
这是我写了一个晚上测试脚本运行的东西。请注意,该测试涵盖了基本情况,但它本身并不够彻底。考虑一下初稿。
import sys
import subprocess
if sys.platform == "win32":
cmd = "zs.py"
else:
cmd = "./zs.py"
def testrun(cmdline):
try:
retcode = subprocess.call(cmdline, shell=True)
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
return retcode
except OSError, e:
return e
tests = []
tests.append((0, " string pattern 4"))
tests.append((1, " string pattern"))
tests.append((3, " string pattern notanumber"))
passed = 0
for t in tests:
r = testrun(cmd + t[1])
if r == t[0]:
res = "passed"
passed += 1
else:
res = "FAILED"
print res, r, t[1]
print
if passed != len(tests):
print "only",passed,"tests passed"
else:
print "all tests passed"
这里是正在测试,zs.py脚本,这确实模式搜索类似生物化学搜索在DNA数据或蛋白质链数据模式的方式的字符串。
#!/usr/bin/env python
# zs - some example Python code to demonstrate to Z??s
# interviewers that the writer really does know Python
import sys
from itertools import *
usage = '''
Usage: zs <string> <pattern> <n>"
print top n matches of pattern in substring"
'''
if sys.hexversion > 0x03000000:
print "This script is only intended to run on Python version 2"
sys.exit(2)
if len(sys.argv) != 4:
print usage
sys.exit(1)
A = sys.argv[1] # string to be searched
B = sys.argv[2] # pattern being searched for
N = sys.argv[3] # number of matches to report
if not N.isdigit():
print "<n> must be a number"
print usage
sys.exit(3)
def matchscore(s1, s2):
''' a helper function to calculate the match score
'''
matches = 0
for i in xrange(len(s1)):
if s1[i] == s2[i]:
matches += 1
return (matches + 0.0)/len(s1) # added 0.0 to force floating point div
def slices(s, n):
''' this is a generator that returns the sequence of slices of
the input string s that are n characters long '''
slen = len(s)
for i in xrange(slen - n + 1):
yield s[i:i+n]
matchlen = len(B)
allscores = ((matchscore(x,B),x,i) for i,x in enumerate(slices(A,matchlen)))
nonzeros = [ y for y in allscores if y[0] != 0 ]
for elem in sorted(nonzeros,key=lambda e: e[0],reverse=True):
nprinted = 0 # We will count them; in case num elements > N
print elem[1], str(round(elem[0],4)), elem[2]
nprinted += 1
if nprinted >= N:
break
我看到有两种方式:
重定向的单元测试过程中标准输出:
class YourTest(TestCase): def setUp(self): self.output = StringIO() self.saved_stdout = sys.stdout sys.stdout = self.output def tearDown(self): self.output.close() sys.stdout = self.saved_stdout def testYourScript(self): yourscriptmodule.main() assert self.output.getvalue() == "My expected ouput"
使用记录你的输出和听它在您的测试。
当您使用py.test进行测试时。您可以使用“capsys”或“capfd”测试功能参数运行断言对STDOUT和STDIN
def test_myoutput(capsys): # or use "capfd" for fd-level
print ("hello")
sys.stderr.write("world\n")
out, err = capsys.readouterr()
assert out == "hello\n"
assert err == "world\n"
print "next"
out, err = capsys.readouterr()
assert out == "next\n"
更多细节可以发现in the py.test docs
我可能也想看看TextTest测试框架。它更侧重于功能/验收测试(因此不太适合单元测试)并且严重依赖于程序的文本输出。这样你的习惯就变成了一个好习惯:-)。
Python的测试套件做到这一点相当多,我们用两种主要的方法:
重定向标准输出(如其他人所说)。我们使用的上下文经理这样的:
import io import sys import contextlib @contextlib.contextmanager def captured_output(stream_name): """Run the 'with' statement body using a StringIO object in place of a specific attribute on the sys module. Example use (with 'stream_name=stdout'): with captured_stdout() as s: print("hello") assert s.getvalue() == "hello" """ orig_stdout = getattr(sys, stream_name) setattr(sys, stream_name, io.StringIO()) try: yield getattr(sys, stream_name) finally: setattr(sys, stream_name, orig_stdout) def captured_stdout(): return captured_output("stdout") def captured_stderr(): return captured_output("stderr") def captured_stdin(): return captured_output("stdin")
使用
subprocess
模块。当我们特别想测试命令行参数的处理时,我们使用它。几个例子见http://hg.python.org/cpython/file/default/Lib/test/test_cmd_line_script.py。
此代码不能在Python 2.7上运行。请参阅http://stackoverflow.com/questions/3423601/python-2-7-exec-what-is-wrong。我使用__module__ StringIO中的StringIO类来处理它。 – 2013-04-02 14:03:10
- 1. Python测试整个脚本
- 2. Python版本的PHP测试脚本
- 3. 网站负载测试Python脚本
- 4. c#,vb,java,python脚本测试环境?
- 5. Python脚本加载测试网页
- 6. 在Python 3中测试学生脚本
- 7. 安装后,python测试脚本失败
- 8. 使用Python脚本测试服务器
- 9. 测试游戏的Python脚本
- 10. 用于Python的IDE:测试脚本
- 11. 测试ruby脚本
- 12. Shell脚本测试
- 13. 如何从另一个测试脚本调用测试脚本?
- 14. Selenium IDE:将测试脚本包含到新测试脚本中
- 15. 试图运行Selenium IDE Python脚本作为测试套件
- 16. Python的 - 尝试编写一个脚本,测试HTTP接口
- 17. 从在Python Python脚本获取输出测试
- 18. 测试bash shell脚本
- 19. 单元测试PHP脚本
- 20. 测试脚本描述框
- 21. 硒Android的测试脚本
- 22. 自动测试shell脚本
- 23. Shell脚本测试命令
- 24. 什么是测试脚本?
- 25. 在线测试脚本
- 26. 测试幻像JS脚本
- 27. J-Meter - Moodle测试脚本
- 28. 如何测试猪脚本
- 29. 贡献R测试脚本
- 30. Gatling负载测试脚本
doctest已经知道如何处理输出... – 2011-05-12 07:18:09
首先。搜索:http://stackoverflow.com/questions/3481561/python-using-doctest-on-the-mainline。第二。搜索:doctest文档(http://docs.python.org/library/doctest.html#how-are-docstring-examples-recognized)说“输出到标准输出被捕获,但不输出到标准错误”。 – 2011-05-12 09:57:28