單元測試框架 - Doctest



Python 的標準發行版包含 'Doctest' 模組。該模組的功能使搜尋看起來像互動式 Python 會話的文字片段成為可能,並執行這些會話以檢視它們是否完全按顯示的那樣工作。

Doctest 在以下場景中非常有用:

  • 透過驗證所有互動式示例是否仍按文件記錄的那樣工作,來檢查模組的文件字串是否是最新的。

  • 透過驗證來自測試檔案或測試物件的互動式示例是否按預期工作來執行迴歸測試。

  • 為軟體包編寫教程文件,並用輸入-輸出示例進行大量說明

在 Python 中,“文件字串”是一個字串文字,它出現在類、函式或模組中的第一個表示式中。在執行套件時,它會被忽略,但編譯器會識別它並將其放入封閉類、函式或模組的 **__doc__** 屬性中。由於它可以透過內省獲得,因此它是物件文件的規範位置。

通常的做法是在文件字串中放入 Python 程式碼不同部分的示例用法。doctest 模組允許驗證這些文件字串是否與程式碼的間歇性修訂保持最新。

在以下程式碼中,定義了一個階乘函式,並穿插了示例用法。為了驗證示例用法是否正確,請在 doctest 模組中呼叫 testmod() 函式。

"""
This is the "example" module.

The example module supplies one function, factorial(). For example,

>>> factorial(5)
120
"""

def factorial(x):
   """Return the factorial of n, an exact integer >= 0.
   >>> factorial(-1)
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
   """
   
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testmod()

輸入並儲存上述指令碼為 FactDocTest.py,並嘗試從命令列執行此指令碼。

Python FactDocTest.py

除非示例失敗,否則不會顯示任何輸出。現在,將命令列更改為以下內容:

Python FactDocTest.py –v

控制檯現在將顯示以下輸出:

C:\Python27>python FactDocTest.py -v
Trying:
   factorial(5)
Expecting:
   120
ok
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

另一方面,如果 factorial() 函式的程式碼沒有在文件字串中給出預期的結果,則將顯示失敗結果。例如,在上述指令碼中,將 f = 1 替換為 f = 2,然後再次執行 doctest。結果如下:

Trying:
   factorial(5)
Expecting:
   120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
   120
Got:
   240
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
1 items passed all tests:
   1 tests in __main__.factorial
**********************************************************************
1 items had failures:
   1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.

Doctest:檢查文字檔案中的示例

doctest 的另一個簡單應用是在文字檔案中測試互動式示例。這可以透過 testfile() 函式來完成。

以下文字儲存在一個名為“example.txt”的文字檔案中。

Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
   >>> from example import factorial
Now use it:
   >>> factorial(5)
   120

檔案內容被視為文件字串。為了驗證文字檔案中的示例,請使用 doctest 模組的 testfile() 函式。

def factorial(x):
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testfile("example.txt")
  • 與 testmod() 一樣,除非示例失敗,否則 testfile() 不會顯示任何內容。如果某個示例確實失敗了,則使用與 testmod() 相同的格式將失敗的示例和失敗的原因列印到控制檯。

  • 在大多數情況下,互動式控制檯會話的複製貼上可以正常工作,但 doctest 並沒有嘗試對任何特定的 Python shell 進行精確模擬。

  • 任何預期的輸出都必須緊跟包含程式碼的最後一個“>>>”或“...”行之後,並且預期的輸出(如果有)擴充套件到下一個“>>>”或全空格行。

  • 預期輸出不能包含全空格行,因為此類行被視為表示預期輸出的結束。如果預期輸出確實包含空行,請在您的 doctest 示例中放置 <BLANKLINE> 在預期空行的每個位置。

廣告