doctest — это модуль, включенный в стандартную библиотеку языка программирования Python , который позволяет легко генерировать тесты на основе выходных данных стандартной оболочки интерпретатора Python, скопированных и вставленных в строки документации .
Doctest инновационно [1] использует следующие возможности Python: [2]
При использовании оболочки Python за основным приглашением: >>> следуют новые команды. Вторичное приглашение: ... используется при продолжении команд на нескольких строках; и результат выполнения команды ожидается на следующих строках. Пустая строка или другая строка, начинающаяся с основного приглашения, рассматривается как конец вывода команды.
Модуль doctest ищет такие последовательности подсказок в строке документации, повторно выполняет извлеченную команду и сравнивает вывод с выводом команды, приведенным в тестовом примере docstrings.
Действие по умолчанию при запуске doctests — не показывать никаких выходных данных при прохождении тестов. Это можно изменить с помощью параметров для doctest runner. Кроме того, doctest был интегрирован с модулем юнит-тестов Python, что позволяет запускать doctests как стандартные тестовые случаи unittest. Runners для тестовых случаев unittest предоставляют больше возможностей при запуске тестов, таких как отчетность по статистике тестов, например, пройденные и не пройденные тесты.
Хотя doctest не позволяет встраивать программу Python в повествовательный текст, он позволяет встраивать проверяемые примеры в docstrings, где docstrings могут содержать другой текст. Docstrings, в свою очередь, можно извлечь из программных файлов для создания документации в других форматах, таких как HTML или PDF. Можно создать программный файл, содержащий документацию, тесты, а также код и тесты, легко проверяемые по коду. Это позволяет коду, тестам и документации развиваться вместе.
Doctests хорошо подходят для знакомства с библиотекой, демонстрируя, как используется API.
На основе выходных данных интерактивного интерпретатора Python текст можно смешивать с тестами, которые проверяют работу библиотеки и показывают ожидаемые результаты.
Пример 1 показывает, как повествовательный текст может быть перемежен с тестируемыми примерами в docstring. Во втором примере показаны дополнительные возможности doctest вместе с их объяснением. Пример 3 настроен на запуск всех doctest в файле при запуске файла, но при импорте в качестве модуля тесты не будут запущены.
def list_to_0_index ( lst ): """Решение проблемы приведено в: https://rgrig.blogspot.com/2005/11/writing-readable-code.html «Дав список lst, скажем, для каждого элемента 0-индекс, где он появляется в первый раз. Таким образом, список x = [0, 1, 4, 2, 4, 1, 0, 2] преобразуется в y = [0, 1, 2, 3, 2, 1, 0, 3]. Обратите внимание, что для всех i мы имеем x[y[i]] = x[i]. Используйте любой язык программирования и любое представление данных, которое вам нужно.» >>> x = [0, 1, 4, 2, 4, 1, 0, 2] >>> list_to_0_index(x) [0, 1, 2, 3, 2, 1, 0, 3] >>> """ вернуть [ lst.index ( i ) for i in lst ]
===================== Демонстрационные доктесты =====================Это всего лишь пример того, как выглядит текст README, который можно использовать с функцией doctest.DocFileSuite() из модуля doctest Python.Обычно файл README описывает API модуля следующим образом:>>> а = 1 >>> б = 2 >>> а + б 3Обратите внимание, что мы только что продемонстрировали, как сложить два числа в Python и как будет выглядеть результат.Специальная опция позволяет вам быть несколько нечеткими в своих примерах:>>> o = object () >>> o # doctest: +ELLIPSIS <object object at 0x...>Исключения также можно очень хорошо протестировать:>>> x Traceback (последний вызов был последним): ... NameError : имя 'x' не определено
В этом примере также имитируется ввод данных в функцию из файла с использованием модуля Python StringIO.
def unique_words ( page ): """Возвращает набор уникальных слов в списке строк текста. Пример: >>> from StringIO import StringIO >>> fileText = '''кот сидел на коврике ... коврик был надурен котом ... одна рыба две рыбы красная рыба ... синяя рыба ... У этой рыбы желтая машина ... У этой рыбы желтая звезда''' >>> file = StringIO(fileText) >>> page = file.readlines() >>> words = unique_words(page) >>> print sorted(list(words)) ["This", "a", "blue", "car", "cat", "fish", "has", "mat", "on", "ondur", "one", "red", "sat", "star", "the", "two", "was", "yellow"] >>> """ return set ( word for line in page for word in line . split ())def _test (): импорт doctest doctest . testmod ()если __name__ == "__main__" : _test ()
Как формат EpyText Epydoc , так и формат reStructuredText Docutils поддерживают разметку разделов doctest внутри строк документации.
В C++ фреймворк doctest является наиболее близкой возможной реализацией этой концепции — тесты можно писать непосредственно в производственном коде с минимальными накладными расходами и возможностью извлечения их из двоичного файла. [3]
Библиотека ExUnit.DocTest Elixir реализует функциональность, похожую на Doctest. [4]
Реализация Doctest для Haskell . [5]
Написание тестов документации в Elm . [6]
Написание тестов документации на Rust . [7]
Написание тестов документации в Elixir . [8]
byexample
[9] поддерживает написание doctest-ов для нескольких популярных языков программирования (например, Python, Ruby, Shell, JavaScript, C/C++, Java, Go, Rust) внутри Markdown , reStructuredText и других текстовых документов.