Python doctest模組:檔案測試(超級詳細)

2020-07-16 10:05:19
前面章節不止一次講到,Python 支援給函數、類以及類方法新增說明性文件,並提供 help() 函數和 __doc__ 屬性獲取指定成員的說明文件。例如:
def display(add):
    '''
    這是一個函數

    '''
    print(add)
   
class my_cla:
    '''
    這是一個類

    '''
    def say(self,add):
        '''
        這是一個類實體方法
        '''
        print(add)
help(display)
程式輸出結果為:

Help on function display in module __main__:

display(add)
    這是一個函數

但是,說明性文件的功能還遠不止此,它還可以用來包含一些測試程式碼,以測試該成員(函數、類、類方法)的功能是否正確。值得一提的是,說明性文件中測試該成員的程式碼和實際呼叫該成員時使用的程式碼是一樣的,只不過作為測試程式碼,它有特定的編寫格式。

在函數、類或類方法的說明性文件中,以>>>作為開始的內容就表示一行測試程式碼,並且接下來的一行則明確該測試程式碼的輸出結果,以上面程式為例,為 display() 函數新增測試程式碼如下:

'''
這是一個函數

>>> display("http://c.biancheng.net/python/")
http://c.biancheng.net/python/
>>> display("http://c.biancheng.net/java/")
http://c.biancheng.net/java/
'''

可以看到,我們為 display() 函數新增了 2 個測試程式碼,並且指定了該函數應該輸出的正確結果。在此基礎上,如果想執行測試程式碼,還需借助 doctest 模組中的 testmod() 函數。例如,修改上面程式如下所示:
import doctest

def display(add):
    '''
    這是一個函數
    >>> display("http://c.biancheng.net/python/")
    http://c.biancheng.net/python/
    >>> display("http://c.biancheng.net/java/")
    http://c.biancheng.net/java/
    '''
    print(add)
   
class my_cla:
    '''
    這是一個類
    >>> myClass = my_cla()
    >>> myClass.say("http://c.biancheng.net/shell/")
    http://c.biancheng.net/shell/
    >>> myClass.say("http://c.biancheng.net")
    abc
    '''
    def say(self,add):
        '''
        這是一個類實體方法
        '''
        print(add)
doctest.testmod()
可以看到,我們為 display() 函數以及 my_cla 類都新增了測試程式碼,同時還呼叫 doctest 模組中的 testmod() 函數。執行該程式,輸出結果為:

**********************************************************************
File "C:UsersmengmaDesktopdemo.py", line 20, in __main__.my_cla
Failed example:
    myClass.say("http://c.biancheng.net")
Expected:
    abc
Got:
    http://c.biancheng.net
**********************************************************************
1 items had failures:
   1 of   3 in __main__.my_cla
***Test Failed*** 1 failures.

該輸出結果中,僅顯示了執行錯誤的測試程式碼,所謂執行錯誤,指的是規定的測試程式碼的輸出結果和執行該測試程式碼時的輸出結果不一致。顯然,對於上面所有的測試程式碼中,當呼叫 my_cls.say("http://c.bianchegn.net") 時,正常就應該輸出 “http://c.biancheng.net”這個字串,而不應該輸出“abc”,這裡僅是為了讓讀者看到使用 doctest.testmod() 函數的效果。

因此,在執行 doctest.testmod() 函數時,它會執行該模組中各成員說明性文件包含的測試程式碼,並將執行結果和指定的結果做比對,如果一致,則什麼也不輸出;反之,則輸出以下提示資訊:
  1. 顯示在哪個原始檔的哪一行。
  2. Failed example,顯示是哪個測試用例出錯了。
  3. Expected,顯示程式期望的輸出結果。也就是在“>>>命令”的下一行給出的執行結果,它就是期望結果。
  4. Got,顯示程式實際執行產生的輸出結果。只有當實際執行產生的輸出結果與期望結果一致時,才表明該測試用例通過。