如何使用像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