Фреймворк UnitTest - Доктест

Стандартный дистрибутив Python содержит модуль Doctest. Функциональные возможности этого модуля позволяют искать фрагменты текста, похожие на интерактивные сеансы Python, и выполнять эти сеансы, чтобы проверить, работают ли они в точности так, как показано.

Доктест может быть очень полезен в следующих сценариях -

  • Чтобы проверить актуальность документации модуля, убедившись, что все интерактивные примеры по-прежнему работают, как задокументировано.

  • Выполнить регрессионное тестирование, убедившись, что интерактивные примеры из тестового файла или тестового объекта работают должным образом.

  • Написать учебную документацию для пакета, обильно иллюстрированную примерами ввода-вывода

В Python «docstring» - это строковый литерал, который появляется как первое выражение в классе, функции или модуле. Он игнорируется при выполнении набора, но распознается компилятором и помещается в__doc__атрибут включающего класса, функции или модуля. Поскольку он доступен через интроспекцию, это каноническое место для документации объекта.

Это обычная практика - помещать примеры использования различных частей кода Python внутри строки документации. Модуль doctest позволяет проверить актуальность этих строк документации с периодическими изменениями кода.

В следующем коде функция факториала определяется вкраплениями с примером использования. Чтобы проверить правильность использования примера, вызовите функцию testmod () в модуле doctest.

"""
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 = 2 вместо f = 1 в приведенном выше сценарии и снова запустите 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 - тестирование интерактивных примеров в текстовом файле. Это можно сделать с помощью функции 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

Содержимое файла рассматривается как строка документации. Чтобы проверить примеры в текстовом файле, используйте функцию testfile () модуля doctest.

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.

  • Любой ожидаемый вывод должен сразу следовать за последней строкой '>>>' или '...', содержащей код, а ожидаемый вывод (если таковой имеется) распространяется на следующую строку '>>>' или полностью пробелами.

  • Ожидаемый вывод не может содержать строку, состоящую только из пробелов, поскольку такая строка используется для обозначения конца ожидаемого вывода. Если ожидаемый вывод действительно содержит пустую строку, вставьте <BLANKLINE> в ваш пример doctest каждый раз, когда ожидается пустая строка.