正如引言中提到的,doctest已經(jīng)發(fā)展到三個(gè)主要用途:
這些用途具有不同的要求,區(qū)分它們很重要。特別是,用不明確的測(cè)試用例填充文檔字符串會(huì)導(dǎo)致錯(cuò)誤的文檔。
在編寫(xiě)文檔字符串時(shí),請(qǐng)小心選擇文檔字符串示例。有一個(gè)學(xué)問(wèn)需要學(xué)習(xí) - 起初可能并不自然。示例應(yīng)該為文檔增加真正的價(jià)值。一個(gè)很好的例子往往可以說(shuō)很多話。如果謹(jǐn)慎處理,這些示例對(duì)您的用戶來(lái)說(shuō)將是非常寶貴的,并且會(huì)隨著時(shí)間的推移和事情的變化而回報(bào)多次收集它們所需的時(shí)間。我仍然驚訝于我的一個(gè)doctest示例在“無(wú)害”更改后停止工作的頻率。
Doctest也是回歸測(cè)試的絕佳工具,特別是如果你不吝嗇解釋性文本。通過(guò)插入散文和例子,跟蹤實(shí)際正在測(cè)試的內(nèi)容以及為什么更容易。當(dāng)一個(gè)測(cè)試失敗時(shí),好的散文可以使得更容易找出問(wèn)題所在,以及應(yīng)該如何解決問(wèn)題。的確,您可以在基于代碼的測(cè)試中編寫(xiě)大量的評(píng)論,但很少有程序員會(huì)這樣做。許多人已經(jīng)發(fā)現(xiàn)使用doctest方法會(huì)導(dǎo)致更清晰的測(cè)試。也許這只是因?yàn)閐octest使編寫(xiě)散文比編寫(xiě)代碼容易一些,而在代碼中編寫(xiě)注釋有點(diǎn)困難。我認(rèn)為它比以上更深刻:編寫(xiě)基于doctest的測(cè)試時(shí)的自然態(tài)度是您想解釋軟件的優(yōu)點(diǎn),并用示例來(lái)說(shuō)明它們。這反過(guò)來(lái)自然會(huì)導(dǎo)致以最簡(jiǎn)單的功能開(kāi)始的測(cè)試文件,并在邏輯上進(jìn)展到復(fù)雜性和邊緣情況。一個(gè)連貫的敘述是結(jié)果,而不是一組孤立的函數(shù),它們似乎隨機(jī)地測(cè)試孤立的功能位。這是一種不同的態(tài)度,產(chǎn)生不同的結(jié)果,模糊了測(cè)試和解釋之間的區(qū)別。
回歸測(cè)試最好局限于專用對(duì)象或文件。有幾種組織測(cè)試的選項(xiàng):
當(dāng)您將測(cè)試放入模塊中時(shí),模塊本身可以成為測(cè)試運(yùn)行者。當(dāng)測(cè)試失敗時(shí),您可以安排測(cè)試運(yùn)行者在調(diào)試問(wèn)題時(shí)僅重新運(yùn)行失敗的doctest。這是一個(gè)這樣的測(cè)試運(yùn)行者的最小例子:
if __name__ == '__main__':
import doctest
flags = doctest.REPORT_NDIFF|doctest.REPORT_ONLY_FIRST_FAILURE
if len(sys.argv) > 1:
name = sys.argv[1]
if name in globals():
obj = globals()[name]
else:
obj = __test__[name]
doctest.run_docstring_examples(obj, globals(), name=name,
optionflags=flags)
else:
fail, total = doctest.testmod(optionflags=flags)
print("{} failures out of {} tests".format(fail, total))
不支持包含預(yù)期輸出和異常的示例。試圖猜測(cè)一個(gè)結(jié)束和另一個(gè)開(kāi)始的地方太容易出錯(cuò),這也會(huì)導(dǎo)致一個(gè)令人困惑的測(cè)試。
更多建議: