doctest.md
1> **Источник:** https://python-all.ru/2.7/library/doctest.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 25.2. [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) – тестирование интерактивных примеров Python89Модуль [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) ищет фрагменты текста, которые выглядят как интерактивные сеансы Python, а затем выполняет эти сеансы, чтобы убедиться, что они работают в точности как показано. Есть несколько распространённых способов использования doctest:1011- Чтобы проверить, что докстринги модуля актуальны, убедившись, что все интерактивные примеры по-прежнему работают как описано.12- Чтобы выполнить регрессионное тестирование, проверяя, что интерактивные примеры из тестового файла или тестового объекта работают как ожидается.13- Чтобы написать учебную документацию для пакета, обильно иллюстрированную примерами ввода-вывода. В зависимости от того, на чём делается акцент – на примерах или на пояснительном тексте, это напоминает «грамотное тестирование» (literate testing) или «исполняемую документацию» (executable documentation).1415Вот полный, но небольшой пример модуля:1617```python18"""19Это модуль "example".2021Модуль example предоставляет одну функцию, factorial(). Например,2223>>> factorial(5)2412025"""2627def factorial(n):28 """Возвращает факториал n – целое число >= 0.2930 Если результат достаточно мал, чтобы поместиться в int, вернуть int.31 Иначе вернуть long.3233 >>> [factorial(n) for n in range(6)]34 [1, 1, 2, 6, 24, 120]35 >>> [factorial(long(n)) for n in range(6)]36 [1, 1, 2, 6, 24, 120]37 >>> factorial(30)38 265252859812191058636308480000000L39 >>> factorial(30L)40 265252859812191058636308480000000L41 >>> factorial(-1)42 Traceback (самый последний вызов последним):43 ...44 ValueError: n должно быть >= 04546 Факториалы чисел с плавающей точкой допустимы, но число должно быть точным целым:47 >>> factorial(30.1)48 Traceback (самый последний вызов последним):49 ...50 ValueError: n должно быть целым числом51 >>> factorial(30.0)52 265252859812191058636308480000000L5354 Оно также не должно быть нелепо большим:55 >>> factorial(1e100)56 Traceback (самый последний вызов последним):57 ...58 OverflowError: n слишком велико59 """6061 import math62 if not n >= 0:63 raise ValueError("n must be >= 0")64 if math.floor(n) != n:65 raise ValueError("n must be exact integer")66 if n+1 == n: # перехватить значение, например 1e30067 raise OverflowError("n too large")68 result = 169 factor = 270 while factor <= n:71 result *= factor72 factor += 173 return result7475if __name__ == "__main__":76 import doctest77 doctest.testmod()78```7980Если запустить `example.py` напрямую из командной строки, [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) творит своё волшебство:8182```console83$ python example.py84$85```8687Нет вывода! Это нормально и означает, что все примеры сработали. Передайте скрипту `-v`, и [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) выведет подробный журнал того, что он пытается сделать, а в конце – сводку:8889```console90$ python example.py -v91Trying:92 factorial(5)93Expecting:94 12095ok96Trying:97 [factorial(n) for n in range(6)]98Expecting:99 [1, 1, 2, 6, 24, 120]100ok101Trying:102 [factorial(long(n)) for n in range(6)]103Expecting:104 [1, 1, 2, 6, 24, 120]105ok106```107108И так далее, в конечном итоге завершаясь:109110```text111Trying:112 factorial(1e100)113Expecting:114 Traceback (most recent call last):115 ...116 OverflowError: n too large117ok1182 items passed all tests:119 1 tests in __main__120 8 tests in __main__.factorial1219 tests in 2 items.1229 passed and 0 failed.123Test passed.124$125```126127Это всё, что нужно знать, чтобы начать продуктивно использовать [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest)! Погружайтесь. В следующих разделах приводятся полные подробности. Обратите внимание, что в стандартном наборе тестов и библиотеках Python есть много примеров doctest. Особенно полезные примеры можно найти в стандартном тестовом файле `Lib/test/test_doctest.py`.128129## 25.2.1. Простое использование: проверка примеров в докстрингах130131Самый простой способ начать использовать doctest (но не обязательно тот, которым вы будете продолжать пользоваться) – это завершить каждый модуль `M` следующим образом:132133```python134if __name__ == "__main__":135 import doctest136 doctest.testmod()137```138139[`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) затем проверяет докстринги в модуле `M`.140141Запуск модуля как скрипта приводит к тому, что примеры в докстрингах выполняются и проверяются:142143```python144python M.py145```146147Это не отобразит ничего, если только какой-либо пример не завершится ошибкой – в этом случае ошибочный пример(ы) и причина(ы) ошибки(ок) выводятся в stdout, и последняя строка вывода будет `***Test Failed*** N failures.`, где *N* – это количество примеров, которые не прошли проверку.148149Запустите его с флагом `-v` вместо этого:150151```python152python M.py -v153```154155и подробный отчёт обо всех проверенных примерах выводится в стандартный вывод, а в конце – различные сводки.156157Можно принудительно включить подробный режим, передав `verbose=True` в [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod), или запретить его, передав `verbose=False`. В любом из этих случаев `sys.argv` не проверяется [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod) (поэтому передача `-v` или её отсутствие не имеет эффекта).158159Начиная с Python 2.6, появился также ярлык командной строки для запуска [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod). Можно указать интерпретатору Python запустить модуль doctest напрямую из стандартной библиотеки и передать имя (имена) модулей в командной строке:160161```python162python -m doctest -v example.py163```164165Это импортирует `example.py` как отдельный модуль и запустит для него [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod). Обратите внимание, что это может работать некорректно, если файл является частью пакета и импортирует другие подмодули из этого пакета.166167Для получения дополнительной информации о [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod) см. раздел [Базовый API](https://python-all.ru/2.7/library/doctest.html#doctest-basic-api).168169## 25.2.2. Простое использование: проверка примеров в текстовом файле170171Ещё одно простое применение doctest – тестирование интерактивных примеров в текстовом файле. Это можно сделать с помощью функции [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile):172173```python174import doctest175doctest.testfile("example.txt")176```177178Этот короткий скрипт выполняет и проверяет любые интерактивные примеры Python, содержащиеся в файле `example.txt`. Содержимое файла рассматривается как один гигантский докстринг; файл не обязан содержать программу на Python! Например, предположим, `example.txt` содержит следующее:179180```text181The ``example`` module182======================183184Using ``factorial``185-------------------186187This is an example text file in reStructuredText format. First import188``factorial`` from the ``example`` module:189190 >>> from example import factorial191192Now use it:193194 >>> factorial(6)195 120196```197198Запуск `doctest.testfile("example.txt")` затем находит ошибку в этой документации:199200```python201File "./example.txt", line 14, in example.txt202Failed example:203 factorial(6)204Expected:205 120206Got:207 720208```209210Как и в случае с [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod), [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) не будет выводить ничего, пока какой-либо пример не завершится ошибкой. Если пример завершается ошибкой, то ошибочный пример(ы) и причина(ы) ошибки(ок) выводятся в stdout, в том же формате, что и [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod).211212По умолчанию [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) ищет файлы в каталоге вызывающего модуля. См. раздел [Базовый API](https://python-all.ru/2.7/library/doctest.html#doctest-basic-api) с описанием необязательных аргументов, которые можно использовать, чтобы указать ему искать файлы в других местах.213214Как и у [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod), степень подробности вывода [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) можно задать с помощью флага командной строки `-v` или необязательного именованного аргумента *verbose*.215216Начиная с Python 2.6, появился также ярлык командной строки для запуска [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile). Можно указать интерпретатору Python запустить модуль doctest напрямую из стандартной библиотеки и передать имя (имена) файлов в командной строке:217218```python219python -m doctest -v example.txt220```221222Поскольку имя файла не заканчивается на `.py`, [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) делает вывод, что его нужно запускать с [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile), а не с [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod).223224Для получения дополнительной информации о [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) см. раздел [Базовый API](https://python-all.ru/2.7/library/doctest.html#doctest-basic-api).225226## 25.2.3. Как это работает227228В этом разделе подробно рассматривается, как работает doctest: какие docstrings он просматривает, как находит интерактивные примеры, какой контекст выполнения использует, как обрабатывает исключения и как опции могут управлять его поведением. Это информация, которую нужно знать для написания примеров doctest; сведения о непосредственном запуске doctest на этих примерах приведены в следующих разделах.229230### 25.2.3.1. Какие докстринги проверяются?231232Проверяются docstring модуля, а также docstrings всех функций, классов и методов. Объекты, импортированные в модуль, не проверяются.233234Кроме того, если `M.__test__` существует и имеет значение «истина», это должен быть словарь, и каждая запись сопоставляет строковое имя с объектом функции, объектом класса или строкой. Докстринги объектов функций и классов, найденные из `M.__test__`, ищутся, а строки обрабатываются так, как если бы они были докстрингами. В выводе ключ `K` в `M.__test__` отображается с именем235236```python237<name of M>.__test__.K238```239240Любые найденные классы аналогично рекурсивно проверяются на наличие docstrings в содержащихся в них методах и вложенных классах.241242Изменено в версии 2.4: Концепция «частного имени» (private name) объявлена устаревшей и больше не документируется.243244### 25.2.3.2. Как распознаются примеры в докстрингах?245246В большинстве случаев копирование и вставка сессии интерактивной консоли работает нормально, но doctest не пытается точно эмулировать какой-либо конкретный Python shell.247248```python249>>> # комментарии игнорируются250>>> x = 12251>>> x25212253>>> if x == 13:254... print "yes"255... else:256... print "no"257... print "NO"258... print "NO!!!"259...260no261NO262NO!!!263>>>264```265266Любой ожидаемый вывод должен сразу следовать за последней строкой `'>>> '` или `'... '`, содержащей код, и ожидаемый вывод (если есть) простирается до следующей строки `'>>> '` или строки, состоящей только из пробелов.267268Мелкий шрифт:269270- Ожидаемый вывод не может содержать строку только из пробелов, так как такая строка считается сигналом конца ожидаемого вывода. Если ожидаемый вывод содержит пустую строку, поместите `<BLANKLINE>` в ваш пример doctest в каждом месте, где ожидается пустая строка.271272 Новое в версии 2.4: Был добавлен `<BLANKLINE>`; в предыдущих версиях не было возможности использовать ожидаемый вывод, содержащий пустые строки.273- Все символы жёсткой табуляции заменяются пробелами с использованием 8-колонных позиций табуляции. Табуляции в выводе тестируемого кода не изменяются. Поскольку любые жёсткие табуляции в образцовом выводе *заменяются*, это означает, что если вывод кода содержит жёсткие табуляции, doctest может пройти, только если действует опция [`NORMALIZE_WHITESPACE`](https://python-all.ru/2.7/library/doctest.html#doctest.NORMALIZE_WHITESPACE) или [директива](https://python-all.ru/2.7/library/doctest.html#doctest-directives). В качестве альтернативы тест можно переписать так, чтобы захватывать вывод и сравнивать его с ожидаемым значением как часть теста. Этот способ обработки табуляций в исходном коде был найден методом проб и ошибок и оказался наименее подверженным ошибкам. Можно использовать другой алгоритм для обработки табуляций, написав собственный класс [`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser).274275 Изменено в версии 2.4: Раскрытие табуляции в пробелы – новое поведение; предыдущие версии пытались сохранить жесткие табуляции, что приводило к путанице.276- Вывод в stdout перехватывается, но не вывод в stderr (трассировки исключений перехватываются другим способом).277- Если вы продолжаете строку обратной косой чертой в интерактивной сессии или по любой другой причине используете обратную косую черту, следует использовать сырой docstring, который сохранит обратные косые черты точно в том виде, как вы их ввели:278279 ```python280 >>> def f(x):281 ... r'''Обратная косая черта в сырой докстринге: m\n'''282 >>> print f.__doc__283 Backslashes in a raw docstring: m\n284 ```285286 В противном случае обратная косая черта будет интерпретироваться как часть строки. Например, `\n` выше будет интерпретироваться как символ новой строки. В качестве альтернативы можно удвоить каждую обратную косую черту в версии для doctest (и не использовать сырую строку):287288 ```python289 >>> def f(x):290 ... '''Обратная косая черта в сырой докстринге: m\\n'''291 >>> print f.__doc__292 Backslashes in a raw docstring: m\n293 ```294- Начальный столбец не имеет значения:295296 ```python297 >>> assert "Easy!"298 >>> import math299 >>> math.floor(1.9)300 1.0301 ```302303 а также из ожидаемого вывода удаляется столько начальных пробельных символов, сколько их было в исходной строке `'>>> '`, с которой начинался пример.304305### 25.2.3.3. Каков контекст выполнения?306307По умолчанию каждый раз, когда [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) находит документирующую строку для тестирования, он использует *поверхностную копию* глобальных переменных `M`, чтобы выполнение тестов не изменяло реальные глобальные переменные модуля и чтобы один тест в `M` не мог оставить следов, случайно позволяющих работать другому тесту. Это означает, что примеры могут свободно использовать любые имена, определённые на верхнем уровне в `M`, а также имена, определённые ранее в выполняемой документирующей строке. Примеры не видят имена, определённые в других документирующих строках.308309Можно принудительно использовать собственный словарь в качестве контекста выполнения, передав `globs=your_dict` в [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod) или [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile).310311### 25.2.3.4. Что насчёт исключений?312313Никаких проблем, при условии, что трассировка – единственный вывод, выдаваемый примером: просто вставьте трассировку. [1](https://python-all.ru/2.7/library/doctest.html#id2) Поскольку трассировки содержат детали, которые могут быстро меняться (например, точные пути к файлам и номера строк), это тот случай, когда doctest старается быть гибким в том, что он принимает.314315Простой пример:316317```python318>>> [1, 2, 3].remove(42)319Traceback (most recent call last):320 File "<stdin>", line 1, in <module>321ValueError: list.remove(x): x not in list322```323324Этот doctest считается успешным, если возбуждается [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError) с деталями `list.remove(x): x not in list`, как показано.325326Ожидаемый вывод для исключения должен начинаться с заголовка трассировки, которым может быть одна из следующих двух строк, с отступом, совпадающим с первой строкой примера:327328```python329Traceback (most recent call last):330Traceback (innermost last):331```332333За заголовком трассировки следует необязательный стек трассировки, содержимое которого игнорируется doctest. Стек трассировки обычно опускается или копируется дословно из интерактивного сеанса.334335За стеком трассировки следует самая интересная часть: строка(и), содержащие тип исключения и его описание. Обычно это последняя строка трассировки, но может занимать несколько строк, если у исключения многострочное описание:336337```python338>>> raise ValueError('multi\n line\ndetail')339Traceback (most recent call last):340 File "<stdin>", line 1, in <module>341ValueError: multi342 line343detail344```345346Последние три строки (начиная с [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError)) сравниваются с типом и описанием исключения, а остальные игнорируются.347348Изменено в версии 2.4: Предыдущие версии не могли обрабатывать многострочные детали исключений.349350Лучшая практика – опускать стек трассировки, если он не добавляет существенной документационной ценности примеру. Так что последний пример, вероятно, лучше оформить так:351352```python353>>> raise ValueError('multi\n line\ndetail')354Traceback (most recent call last):355 ...356ValueError: multi357 line358detail359```360361Обратите внимание, что трассировки обрабатываются особым образом. В частности, в переписанном примере использование `...` не зависит от опции [`ELLIPSIS`](https://python-all.ru/2.7/library/doctest.html#doctest.ELLIPSIS) doctest. Многоточие в этом примере можно было бы опустить или заменить тремя (или тремястами) запятыми, цифрами или отступной стенограммой скетча Монти Пайтона.362363Некоторые детали, которые стоит прочитать один раз, но запоминать не обязательно:364365- Doctest не может угадать, получен ли ваш ожидаемый вывод из трассировки исключения или из обычной печати. Поэтому, например, пример, ожидающий `ValueError: 42 is prime`, будет пройден независимо от того, действительно ли возбуждено [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError) или же пример просто выводит этот текст трассировки. На практике обычный вывод редко начинается со строки заголовка трассировки, так что это не создаёт реальных проблем.366- Каждая строка стека трассировки (если присутствует) должна иметь отступ больше, чем первая строка примера, *или* начинаться с небуквенно-цифрового символа. Первая строка после заголовка трассировки с таким же отступом и начинающаяся с буквенно-цифрового символа считается началом описания исключения. Конечно, это корректно работает для настоящих трассировок.367- Когда указана опция doctest [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/2.7/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL), всё, что находится после самого левого двоеточия и любой информации о модуле в имени исключения, игнорируется.368- Интерактивная оболочка опускает строку заголовка трассировки для некоторых [`SyntaxError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.SyntaxError). Но doctest использует строку заголовка трассировки, чтобы отличать исключения от не-исключений. Поэтому в редком случае, когда нужно протестировать [`SyntaxError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.SyntaxError), который опускает заголовок трассировки, придётся вручную добавить строку заголовка трассировки в тестовый пример.369- Для некоторых [`SyntaxError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.SyntaxError) Python отображает позицию символа синтаксической ошибки с помощью маркера `^`:370371 ```python372 >>> 1 1373 File "<stdin>", line 1374 1 1375 ^376 SyntaxError: invalid syntax377 ```378379 Поскольку строки, показывающие положение ошибки, идут до типа и описания исключения, они не проверяются doctest. Например, следующий тест будет пройден, даже если `^`-маркер поставлен в неверное место:380381 ```python382 >>> 1 1383 File "<stdin>", line 1384 1 1385 ^386 SyntaxError: invalid syntax387 ```388389### 25.2.3.5. Флаги опций390391Ряд опциональных флагов управляют различными аспектами поведения doctest. Символические имена флагов предоставляются как константы модуля, которые можно [объединять побитовым ИЛИ](https://python-all.ru/2.7/reference/expressions.html#bitwise) и передавать различным функциям. Эти имена также можно использовать в [директивах doctest](https://python-all.ru/2.7/library/doctest.html#doctest-directives).392393Первая группа опций определяет семантику тестов, управляя аспектами того, как doctest решает, соответствует ли фактический вывод ожидаемому выводу примера:394395#### `doctest.DONT_ACCEPT_TRUE_FOR_1`396397По умолчанию, если блок ожидаемого вывода содержит просто `1`, то фактический вывод, содержащий просто `1` или просто `True`, считается совпадением; аналогично для `0` и `False`. Когда указано [`DONT_ACCEPT_TRUE_FOR_1`](https://python-all.ru/2.7/library/doctest.html#doctest.DONT_ACCEPT_TRUE_FOR_1), ни одна из подстановок не разрешена. Поведение по умолчанию учитывает, что Python изменил тип возвращаемого значения многих функций с целого числа на логическое; тесты из модуля doctest, ожидающие «маленькое целое», всё ещё работают в таких случаях. Эта опция, вероятно, будет удалена, но не в ближайшие годы.398399#### `doctest.DONT_ACCEPT_BLANKLINE`400401По умолчанию, если блок ожидаемого вывода содержит строку, состоящую только из `<BLANKLINE>`, то эта строка будет соответствовать пустой строке в фактическом вызове. Поскольку действительно пустая строка разделяет ожидаемый вывод, это единственный способ указать, что ожидается пустая строка. Когда указано [`DONT_ACCEPT_BLANKLINE`](https://python-all.ru/2.7/library/doctest.html#doctest.DONT_ACCEPT_BLANKLINE), такая подстановка не разрешена.402403#### `doctest.NORMALIZE_WHITESPACE`404405Когда указано, все последовательности пробельных символов (пробелы и переводы строк) считаются равными. Любая последовательность пробелов в ожидаемом выводе будет соответствовать любой последовательности пробелов в фактическом выводе. По умолчанию пробельные символы должны совпадать точно. [`NORMALIZE_WHITESPACE`](https://python-all.ru/2.7/library/doctest.html#doctest.NORMALIZE_WHITESPACE) особенно полезна, когда строка ожидаемого вывода очень длинная, и её хочется перенести на несколько строк в исходном коде.406407#### `doctest.ELLIPSIS`408409Когда указано, маркер многоточия (`...`) в ожидаемом выводе может соответствовать любой подстроке в фактическом выводе. Это включает подстроки, выходящие за границы строк, и пустые подстроки, поэтому лучше использовать эту возможность просто. Сложное использование может привести к тем же сюрпризам «ой, совпало слишком много!», к которым склонен `.*` в регулярных выражениях.410411#### `doctest.IGNORE_EXCEPTION_DETAIL`412413Если этот флаг указан, пример, ожидающий исключение, считается успешным, если возбуждено исключение ожидаемого типа, даже если описание исключения не совпадает. Например, пример, ожидающий `ValueError: 42`, будет пройден, если фактически возбуждено исключение `ValueError: 3*14`, но не пройден, если возбуждено, скажем, [`TypeError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.TypeError).414415Этот флаг также игнорирует имя модуля, которое используется в отчётах doctest в Python 3. Поэтому оба следующих варианта будут работать с указанным флагом независимо от того, выполняется ли тест под Python 2.7 или Python 3.2 (или более поздними версиями):416417```python418>>> raise CustomError('message')419Traceback (most recent call last):420CustomError: message421422>>> raise CustomError('message')423Traceback (most recent call last):424my_module.CustomError: message425```426427Обратите внимание, что [`ELLIPSIS`](https://python-all.ru/2.7/library/doctest.html#doctest.ELLIPSIS) можно также использовать для игнорирования деталей сообщения об исключении, но такой тест всё равно может не пройти из-за того, выводятся ли сведения о модуле как часть имени исключения. Использование [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/2.7/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL) и деталей из Python 2.3 – единственный понятный способ написать доктест, которому безразличны детали исключения и который продолжает работать в Python 2.3 и более ранних версиях (эти версии не поддерживают [директивы doctest](https://python-all.ru/2.7/library/doctest.html#doctest-directives) и игнорируют их как незначащие комментарии). Например:428429```python430>>> (1, 2)[3] = 'moo'431Traceback (most recent call last):432 File "<stdin>", line 1, in <module>433TypeError: object doesn't support item assignment434```435436проходит в Python 2.3 и более поздних версиях Python с указанным флагом, хотя в Python 2.4 описание изменилось c «doesn’t» на «does not».437438Изменено в версии 2.7: [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/2.7/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL) теперь также игнорирует любую информацию, относящуюся к модулю, содержащему тестируемое исключение439440#### `doctest.SKIP`441442Если этот флаг указан, пример не выполняется вообще. Это может быть полезно в ситуациях,\\nкогда доктесты служат одновременно документацией и тестовыми примерами, и пример\\nдолжен быть включён для документации, но не должен проверяться. Например, вывод\\nпримера может быть случайным, или пример может зависеть от ресурсов,\\nнедоступных для тестового драйвера.443444Флаг SKIP также можно использовать для временного «закомментирования» примеров.445446Новое в версии 2.5.447448#### `doctest.COMPARISON_FLAGS`449450Битовая маска, объединяющая все перечисленные выше флаги сравнения.451452Вторая группа опций управляет тем, как сообщается о неудачных тестах:453454#### `doctest.REPORT_UDIFF`455456Если указан, ошибки, включающие многострочные ожидаемый и фактический вывод, отображаются в виде unified diff.457458#### `doctest.REPORT_CDIFF`459460Если указан, ошибки, включающие многострочные ожидаемый и фактический вывод, отображаются в виде context diff.461462#### `doctest.REPORT_NDIFF`463464Если указан, различия вычисляются с помощью `difflib.Differ`, используя тот же алгоритм, что и популярная утилита `ndiff.py`. Это единственный метод, который помечает различия как внутри строк, так и между строками. Например, если строка ожидаемого вывода содержит цифру `1`, а фактический вывод – букву `l`, вставляется строка с символом '^', отмечающим позиции несовпадающих столбцов.465466#### `doctest.REPORT_ONLY_FIRST_FAILURE`467468Если указан, отображается первый упавший пример в каждом доктесте, но вывод\\nдля всех остальных примеров подавляется. Это предотвращает сообщение доктестом\\nо корректных примерах, которые «ломаются» из-за предыдущих ошибок; но оно также может\\nскрыть некорректные примеры, которые падают независимо от первой ошибки. Когда\\n[`REPORT_ONLY_FIRST_FAILURE`](https://python-all.ru/2.7/library/doctest.html#doctest.REPORT_ONLY_FIRST_FAILURE) указан, остальные примеры всё равно выполняются\\nи учитываются в общем количестве сообщённых ошибок; только\\nвывод подавляется.469470#### `doctest.REPORTING_FLAGS`471472Битовая маска, объединяющая все перечисленные выше флаги отчёта.473474Новое в версии 2.4: Константы [`DONT_ACCEPT_BLANKLINE`](https://python-all.ru/2.7/library/doctest.html#doctest.DONT_ACCEPT_BLANKLINE), [`NORMALIZE_WHITESPACE`](https://python-all.ru/2.7/library/doctest.html#doctest.NORMALIZE_WHITESPACE), [`ELLIPSIS`](https://python-all.ru/2.7/library/doctest.html#doctest.ELLIPSIS), [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/2.7/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL), [`REPORT_UDIFF`](https://python-all.ru/2.7/library/doctest.html#doctest.REPORT_UDIFF), [`REPORT_CDIFF`](https://python-all.ru/2.7/library/doctest.html#doctest.REPORT_CDIFF), [`REPORT_NDIFF`](https://python-all.ru/2.7/library/doctest.html#doctest.REPORT_NDIFF), [`REPORT_ONLY_FIRST_FAILURE`](https://python-all.ru/2.7/library/doctest.html#doctest.REPORT_ONLY_FIRST_FAILURE), [`COMPARISON_FLAGS`](https://python-all.ru/2.7/library/doctest.html#doctest.COMPARISON_FLAGS) и [`REPORTING_FLAGS`](https://python-all.ru/2.7/library/doctest.html#doctest.REPORTING_FLAGS) были добавлены.475476Существует также способ регистрации новых имен опциональных флагов, хотя это не имеет смысла, если не предполагается расширять внутренности [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) через наследование:477478#### `doctest.register_optionflag(name)`479480Создаёт новый флаг опции с заданным именем и возвращает целочисленное\\nзначение нового флага. [`register_optionflag()`](https://python-all.ru/2.7/library/doctest.html#doctest.register_optionflag) можно использовать при создании подклассов\\n[`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker) или [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner) для создания новых опций, которые\\nподдерживаются вашими подклассами. [`register_optionflag()`](https://python-all.ru/2.7/library/doctest.html#doctest.register_optionflag) всегда следует вызывать,\\nиспользуя следующий идиоматический приём:481482```python483MY_FLAG = register_optionflag('MY_FLAG')484```485486Новое в версии 2.4.487488### 25.2.3.6. Директивы489490Директивы доктестов могут использоваться для изменения [флагов опций](https://python-all.ru/2.7/library/doctest.html#doctest-options) для отдельного примера. Директивы доктестов – это\\nспециальные комментарии Python, следующие за исходным кодом примера:491492```493494directive ::= "#" "doctest:" directive_options495directive_options ::= directive_option ("," directive_option)\*496directive_option ::= on_or_off directive_option_name497on_or_off ::= "+" \| "-"498directive_option_name ::= "DONT_ACCEPT_BLANKLINE" \| "NORMALIZE_WHITESPACE" \| ...499```500501Пробелы не допускаются между `+` или `-` и именем опции\\nдирективы. Имя опции директивы может быть любым из имён флагов опций,\\nописанных выше.502503Директивы доктестов примера изменяют поведение doctest только для этого\\nодного примера. Используйте `+` для включения указанного поведения или\\n`-` для его отключения.504505Например, этот тест проходит:506507```python508>>> print range(20) 509[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,51010, 11, 12, 13, 14, 15, 16, 17, 18, 19]511```512513Без директивы он бы не прошёл, и потому что в фактическом выводе нет\\nдвух пробелов перед элементами списка из одной цифры, и потому что фактический вывод\\nнаходится на одной строке. Этот тест тоже проходит и тоже требует директивы\\nдля этого:514515```python516>>> print range(20) 517[0, 1, ..., 18, 19]518```519520На одной физической строке можно использовать несколько директив, разделённых запятыми:521522```python523>>> print range(20) 524[0, 1, ..., 18, 19]525```526527Если для одного примера используется несколько директив-комментариев, то они объединяются:528529```python530>>> print range(20) 531... 532[0, 1, ..., 18, 19]533```534535Как показано в предыдущем примере, можно добавлять строки `...` в пример, содержащие только директивы. Это может быть полезно, когда пример слишком длинный, чтобы директива удобно поместилась на той же строке:536537```python538>>> print range(5) + range(10,20) + range(30,40) + range(50,60)539... 540[0, ..., 4, 10, ..., 19, 30, ..., 39, 50, ..., 59]541```542543Обратите внимание: поскольку все опции по умолчанию отключены, а директивы применяются только к тому примеру, в котором они находятся, включение опций (через `+` в директиве) обычно является единственным осмысленным выбором. Однако флаги опций также могут передаваться функциям, запускающим доктесты, устанавливая другие значения по умолчанию. В таких случаях отключение опции через `-` в директиве может быть полезным.544545Новое в версии 2.4: Добавлена поддержка директив doctest.546547### 25.2.3.7. Предупреждения548549[`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) серьёзно относится к требованию точного совпадения ожидаемого вывода. Если не совпадёт хотя бы один символ, тест считается проваленным. Это, вероятно, несколько раз вас удивит, пока вы не узнаете, что именно Python гарантирует, а что нет в отношении вывода. Например, при выводе словаря Python не гарантирует, что пары ключ-значение будут выведены в каком-либо определённом порядке, поэтому тест вроде550551```python552>>> foo()553{"Hermione": "hippogryph", "Harry": "broomstick"}554```555556является уязвимым! Один из способов обойти это – сделать557558```python559>>> foo() == {"Hermione": "hippogryph", "Harry": "broomstick"}560True561```562563вместо этого. Другой способ – сделать564565```python566>>> d = foo().items()567>>> d.sort()568>>> d569[('Harry', 'broomstick'), ('Hermione', 'hippogryph')]570```571572Есть и другие, но идея понятна.573574Ещё одна плохая идея – печатать то, что содержит адрес объекта, например575576```python577>>> id(1.0) # обязательно иногда будет ошибаться5787948648579>>> class C: pass580>>> C() # стандартный repr() для экземпляров содержит адрес581<__main__.C instance at 0x00AC18F0>582```583584Директива [`ELLIPSIS`](https://python-all.ru/2.7/library/doctest.html#doctest.ELLIPSIS) даёт хороший подход для последнего примера:585586```python587>>> C() 588<__main__.C instance at 0x...>589```590591Числа с плавающей запятой также подвержены небольшим различиям в выводе на разных платформах, поскольку Python полагается на системную библиотеку C для форматирования чисел с плавающей запятой, а качество библиотек C сильно различается.592593```python594>>> 1./7 # рискованно5950.14285714285714285596>>> print 1./7 # безопаснее5970.142857142857598>>> print round(1./7, 6) # гораздо безопаснее5990.142857600```601602Числа вида `I/2.**J` безопасны на всех платформах, и я часто подбираю примеры для doctest так, чтобы они давали числа такого вида:603604```python605>>> 3./4 # абсолютно безопасно6060.75607```608609Простые дроби также легче понимаются людьми, что улучшает документацию.610611## 25.2.4. Базовый API612613Функции [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod) и [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) предоставляют простой интерфейс к doctest, которого должно быть достаточно для большинства простых случаев использования. Для менее формального введения в эти две функции см. разделы [Простое использование: проверка примеров в строке документации](https://python-all.ru/2.7/library/doctest.html#doctest-simple-testmod) и [Простое использование: проверка примеров в текстовом файле](https://python-all.ru/2.7/library/doctest.html#doctest-simple-testfile).614615#### `doctest.testfile(filename[, module_relative][, name][, package][, globs][, verbose][, report][, optionflags][, extraglobs][, raise_on_error][, parser][, encoding])`616617Все аргументы, кроме *filename*, являются необязательными и должны указываться в форме ключевых слов.618619Проверяет примеры в файле с именем *filename*. Возвращает `(failure_count, test_count)`.620621Необязательный аргумент *module\_relative* определяет, как следует интерпретировать имя файла:622623- Если *module\_relative* равно `True` (значение по умолчанию), то *filename* задаёт независимый от ОС путь относительно модуля. По умолчанию этот путь указывается относительно каталога вызывающего модуля; но если указан аргумент *package*, то путь задаётся относительно этого пакета. Чтобы обеспечить независимость от ОС, *filename* должен использовать символы `/` для разделения сегментов пути и не должен быть абсолютным (т.е. не может начинаться с `/`).624- Если *module\_relative* равно `False`, то *filename* задаёт путь, зависящий от ОС. Путь может быть абсолютным или относительным; относительные пути разрешаются относительно текущего рабочего каталога.625626Необязательный аргумент *name* задаёт имя теста; по умолчанию, или если `None`, используется `os.path.basename(filename)`.627628Необязательный аргумент *package* – это пакет Python или имя пакета Python, каталог которого должен использоваться в качестве базового для имени файла относительно модуля. Если пакет не указан, то в качестве базового каталога для имён файлов относительно модуля используется каталог вызывающего модуля. Указывать *package*, если *module\_relative* равно `False`, является ошибкой.629630Необязательный аргумент *globs* задаёт словарь, который будет использоваться как пространство глобальных имён при выполнении примеров. Для doctest создаётся новая поверхностная копия этого словаря, чтобы примеры начинали с чистого листа. По умолчанию, или если `None`, используется новый пустой словарь.631632Необязательный аргумент *extraglobs* задаёт словарь, который сливается с глобальными переменными, используемыми для выполнения примеров. Это работает как [`dict.update()`](https://python-all.ru/2.7/library/stdtypes.html#dict.update): если *globs* и *extraglobs* имеют общий ключ, то в объединённом словаре отображается значение из *extraglobs*. По умолчанию, или если `None`, дополнительные глобальные переменные не используются. Это расширенная возможность, позволяющая параметризовать доктесты. Например, доктест можно написать для базового класса, используя обобщённое имя класса, а затем повторно использовать для тестирования любого количества подклассов, передавая словарь *extraglobs*, отображающий обобщённое имя на тестируемый подкласс.633634Необязательный аргумент *verbose*: если истина, выводит много информации, если ложь – только ошибки; по умолчанию, или если `None`, он истинен тогда и только тогда, когда `'-v'` присутствует в `sys.argv`.635636Необязательный аргумент *report*: если истина, выводит сводку в конце, иначе ничего не выводит. В подробном режиме сводка подробная, в противном случае – очень краткая (фактически пустая, если все тесты пройдены).637638Необязательный аргумент *optionflags* объединяет опциональные флаги с помощью OR. Смотрите раздел [Опциональные флаги](https://python-all.ru/2.7/library/doctest.html#doctest-options).639640Необязательный аргумент *raise\_on\_error* по умолчанию равен false. Если true, при первой ошибке или неожиданном исключении в примере выбрасывается исключение. Это позволяет выполнять посмертную отладку ошибок. Поведение по умолчанию – продолжать выполнение примеров.641642Необязательный аргумент *parser* задаёт объект [`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser) (или его подкласс), который следует использовать для извлечения тестов из файлов. По умолчанию используется обычный анализатор (т.е. `DocTestParser()`).643644Необязательный аргумент *encoding* задаёт кодировку, которая должна использоваться для преобразования файла в Unicode.645646Новое в версии 2.4.647648Изменено в версии 2.5: Параметр *encoding* был добавлен.649650#### `doctest.testmod([m][, name][, globs][, verbose][, report][, optionflags][, extraglobs][, raise_on_error][, exclude_empty])`651652Все аргументы необязательны, и все, кроме *m*, должны передаваться как именованные.653654Тестирует примеры в строках документации функций и классов, доступных из модуля *m* (или модуля [`__main__`](https://python-all.ru/2.7/library/__main__.html#module-__main__), если *m* не указан или равен `None`), начиная с `m.__doc__`.655656Также проверяет примеры, доступные из словаря `m.__test__`, если он существует и не равен `None`. `m.__test__` сопоставляет имена (строки) с функциями, классами и строками; докстринги функций и классов ищутся на наличие примеров; строки ищутся напрямую, как если бы они были докстрингами.657658Проверяются только строки документации, прикреплённые к объектам, принадлежащим модулю *m*.659660Вернуть `(failure_count, test_count)`.661662Необязательный аргумент *name* задаёт имя модуля; по умолчанию, или если `None`, используется `m.__name__`.663664Необязательный аргумент *exclude\_empty* по умолчанию равен false. Если true, объекты, для которых не найдено ни одного доктеста, исключаются из рассмотрения. Значение по умолчанию – это хак для обратной совместимости, чтобы код, всё ещё использующий `doctest.master.summarize()` в сочетании с [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod), продолжал получать вывод для объектов без тестов. Аргумент *exclude\_empty* у более нового конструктора [`DocTestFinder`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder) по умолчанию равен true.665666Необязательные аргументы *extraglobs*, *verbose*, *report*, *optionflags*, *raise\_on\_error* и *globs* такие же, как у функции [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) выше, за исключением того, что *globs* по умолчанию равен `m.__dict__`.667668Изменено в версии 2.3: Параметр *optionflags* был добавлен.669670Изменено в версии 2.4: Параметры *extraglobs*, *raise\_on\_error* и *exclude\_empty* были добавлены.671672Изменено в версии 2.5: Необязательный аргумент *isprivate*, объявленный устаревшим в 2.4, был удален.673674#### `doctest.run_docstring_examples(f, globs[, verbose][, name][, compileflags][, optionflags])`675676Тестирует примеры, связанные с объектом *f*; например, *f* может быть строкой, модулем, функцией или объектом класса.677678Для контекста выполнения используется поверхностная копия словаря *globs*.679680Необязательный аргумент *name* используется в сообщениях об ошибках и по умолчанию равен `"NoName"`.681682Если необязательный аргумент *verbose* равен true, вывод создаётся, даже если нет ошибок. По умолчанию вывод создаётся только в случае ошибки в примере.683684Необязательный аргумент *compileflags* задаёт набор флагов, которые должны использоваться компилятором Python при запуске примеров. По умолчанию или если `None`, флаги выводятся из набора будущих возможностей, найденных в *globs*.685686Необязательный аргумент *optionflags* работает так же, как у функции [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) выше.687688## 25.2.5. API Unittest689690По мере роста коллекции модулей с doctest понадобится способ систематически запускать все их doctest. До Python 2.4 у [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) был едва документированный класс `Tester`, предоставлявший примитивный способ объединения doctest из нескольких модулей. `Tester` был слабым, и на практике большинство серьезных фреймворков для тестирования Python основывались на модуле [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), который предоставляет множество гибких способов объединения тестов из разных источников. Поэтому в Python 2.4 класс `Tester` из [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) объявлен устаревшим, а [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) предоставляет две функции, которые можно использовать для создания тестовых наборов [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) из модулей и текстовых файлов, содержащих doctest. Для интеграции с обнаружением тестов [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) включите функцию `load_tests()` в свой тестовый модуль:691692```python693import unittest694import doctest695import my_module_with_doctests696697def load_tests(loader, tests, ignore):698 tests.addTests(doctest.DocTestSuite(my_module_with_doctests))699 return tests700```701702Существует две основные функции для создания экземпляров [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) из текстовых файлов и модулей с доктестами:703704#### `doctest.DocFileSuite(*paths, [module_relative][, package][, setUp][, tearDown][, globs][, optionflags][, parser][, encoding])`705706Преобразует доктесты из одного или нескольких текстовых файлов в [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite).707708Возвращаемый [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) предназначен для запуска через unittest framework и выполняет интерактивные примеры из каждого файла. Если пример в любом файле завершается неудачей, то созданный модульный тест также завершается неудачей, и вызывается исключение `failureException`, которое показывает имя файла с тестом и (иногда приблизительный) номер строки.709710Передаётся один или несколько путей (в виде строк) к текстовым файлам для проверки.711712Параметры могут быть указаны в виде именованных аргументов:713714Необязательный аргумент *module\_relative* определяет, как должны интерпретироваться имена файлов в *paths*:715716- Если *module\_relative* равен `True` (по умолчанию), то каждое имя файла в *paths* задаёт независимый от ОС путь относительно модуля. По умолчанию этот путь относителен каталога вызывающего модуля; но если указан аргумент *package*, то он относителен этого пакета. Для обеспечения независимости от ОС каждое имя файла должно использовать символы `/` для разделения сегментов пути и не может быть абсолютным путём (т.е. не должно начинаться с `/`).717- Если *module\_relative* равен `False`, то каждое имя файла в *paths* задаёт путь, зависящий от ОС. Путь может быть абсолютным или относительным; относительные пути разрешаются относительно текущего рабочего каталога.718719Необязательный аргумент *package* – это пакет Python или имя пакета Python, каталог которого должен использоваться в качестве базового каталога для имён файлов, относительных модуля, в *paths*. Если пакет не указан, то в качестве базового каталога для относительных имён файлов используется каталог вызывающего модуля. Указывать *package*, если *module\_relative* равен `False`, является ошибкой.720721Необязательный аргумент *setUp* задаёт функцию настройки для набора тестов. Она вызывается перед выполнением тестов в каждом файле. Функция *setUp* получает объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest). Функция setUp может обращаться к глобальным переменным теста через атрибут *globs* переданного теста.722723Необязательный аргумент *tearDown* задаёт функцию завершения для набора тестов. Она вызывается после выполнения тестов в каждом файле. Функция *tearDown* получает объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest). Функция setUp может обращаться к глобальным переменным теста через атрибут *globs* переданного теста.724725Необязательный аргумент *globs* – это словарь, содержащий начальные глобальные переменные для тестов. Для каждого теста создаётся новая копия этого словаря. По умолчанию *globs* – новый пустой словарь.726727Необязательный аргумент *optionflags* задаёт параметры доктеста по умолчанию для тестов, создаваемые путём объединения отдельных флагов параметров (OR). См. раздел [Option Flags](https://python-all.ru/2.7/library/doctest.html#doctest-options). Функцию [`set_unittest_reportflags()`](https://python-all.ru/2.7/library/doctest.html#doctest.set_unittest_reportflags) см. ниже для лучшего способа установки параметров отчёта.728729Необязательный аргумент *parser* задаёт [`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser) (или подкласс), который должен использоваться для извлечения тестов из файлов. По умолчанию используется обычный парсер (т.е. `DocTestParser()`).730731Необязательный аргумент *encoding* задаёт кодировку, которая должна использоваться для преобразования файла в Unicode.732733Новое в версии 2.4.734735Изменено в версии 2.5: Глобальная переменная `__file__` была добавлена в глобальные переменные, предоставляемые доктестам, загруженным из текстового файла с помощью [`DocFileSuite()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocFileSuite).736737Изменено в версии 2.5: Параметр *encoding* был добавлен.738739> **Примечание**740>741> В отличие от [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod) и [`DocTestFinder`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder), эта функция порождает [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError), если *module* не содержит строк документации. Эту ошибку можно предотвратить, передав экземпляр [`DocTestFinder`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder) в качестве аргумента *test\_finder* с ключевым аргументом *exclude\_empty*, установленным в `False`:742>743> ```python744> >>> finder = doctest.DocTestFinder(exclude_empty=False)745> >>> suite = doctest.DocTestSuite(test_finder=finder)746> ```747748#### `doctest.DocTestSuite([module][, globs][, extraglobs][, test_finder][, setUp][, tearDown][, checker])`749750Преобразует доктесты для модуля в [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite).751752Возвращаемый [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) предназначен для запуска через unittest framework и выполняет каждый doctest в модуле. Если какой-либо из doctest'ов завершается неудачей, то созданный модульный тест завершается неудачей, и вызывается исключение `failureException`, которое показывает имя файла с тестом и (иногда приблизительный) номер строки.753754Необязательный аргумент *module* задаёт тестируемый модуль. Это может быть объект модуля или (возможно, с точками) имя модуля. Если он не указан, используется модуль, из которого вызывается эта функция.755756Необязательный аргумент *globs* – это словарь, содержащий начальные глобальные переменные для тестов. Для каждого теста создаётся новая копия этого словаря. По умолчанию *globs* – новый пустой словарь.757758Необязательный аргумент *extraglobs* задаёт дополнительный набор глобальных переменных, который объединяется с *globs*. По умолчанию дополнительные глобальные переменные не используются.759760Необязательный аргумент *test\_finder* – это объект [`DocTestFinder`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder) (или его замена, совместимая по интерфейсу), который используется для извлечения доктестов из модуля.761762Необязательные аргументы *setUp*, *tearDown* и *optionflags* такие же, как для функции [`DocFileSuite()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocFileSuite) выше.763764Новое в версии 2.3.765766Изменено в версии 2.4: Параметры *globs*, *extraglobs*, *test\_finder*, *setUp*, *tearDown* и *optionflags* были добавлены; теперь эта функция использует тот же метод поиска, что и [`testmod()`](https://python-all.ru/2.7/library/doctest.html#doctest.testmod).767768Под капотом [`DocTestSuite()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestSuite) создаёт [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) из экземпляров `doctest.DocTestCase`, а `DocTestCase` является подклассом [`unittest.TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase). `DocTestCase` здесь не документирован (это внутренняя деталь), но изучение его кода может ответить на вопросы о точных деталях интеграции [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest).769770Аналогично, [`DocFileSuite()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocFileSuite) создаёт [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) из экземпляров `doctest.DocFileCase`, а `DocFileCase` является подклассом `DocTestCase`.771772Таким образом, оба способа создания [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) запускают экземпляры `DocTestCase`. Это важно по тонкой причине: при непосредственном запуске функций [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) можно напрямую управлять используемыми параметрами [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest), передавая флаги опций функциям [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest). Однако при написании фреймворка [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) именно [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) в конечном счёте управляет тем, когда и как выполняются тесты. Автор фреймворка обычно хочет управлять параметрами отчётности [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) (возможно, заданными через параметры командной строки), но нет способа передать параметры через [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) в средства запуска тестов [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest).773774По этой причине [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) также поддерживает понятие флагов отчётности [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest), специфичных для поддержки [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), с помощью этой функции:775776#### `doctest.set_unittest_reportflags(flags)`777778Устанавливает используемые флаги отчётности [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest).779780Аргумент *flags* объединяет опциональные флаги с помощью OR. Смотрите раздел [Опциональные флаги](https://python-all.ru/2.7/library/doctest.html#doctest-options). Можно использовать только «флаги отчетности».781782Это глобальная настройка модуля, которая влияет на все будущие доктесты, запускаемые модулем [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest): метод `runTest()` объекта `DocTestCase` проверяет флаги опций, указанные для тестового случая при создании экземпляра `DocTestCase`. Если флаги отчётности не были указаны (что является типичным и ожидаемым случаем), флаги отчётности [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) объекта [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) [побитово объединяются с помощью ИЛИ](https://python-all.ru/2.7/reference/expressions.html#bitwise) с флагами опций, и расширенные таким образом флаги опций передаются экземпляру [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner), созданному для запуска доктеста. Если какие-либо флаги отчётности были указаны при создании экземпляра `DocTestCase`, флаги отчётности [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) объекта [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) игнорируются.783784Функция возвращает значение флагов отчётности [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), действовавших до её вызова.785786Новое в версии 2.4.787788## 25.2.6. Расширенный API789790Базовый API – это простая обёртка, предназначенная для упрощения использования doctest. Он достаточно гибок и должен удовлетворять потребности большинства пользователей; однако, если требуется более детальный контроль над тестированием или расширение возможностей doctest, следует использовать расширенный API.791792Расширенный API строится вокруг двух классов-контейнеров, которые используются для хранения интерактивных примеров, извлечённых из тестовых сценариев doctest:793794- [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example): Одна инструкция ([statement](https://python-all.ru/2.7/glossary.html#term-statement)) Python в паре с ожидаемым выводом.795- [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest): Набор объектов [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example), обычно извлечённых из одной строки документации или текстового файла.796797Для поиска, разбора, выполнения и проверки примеров doctest определены дополнительные классы обработки:798799- [`DocTestFinder`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder): Находит все строки документации в заданном модуле и использует [`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser) для создания [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) из каждой строки документации, содержащей интерактивные примеры.800- [`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser): Создаёт объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) из строки (например, из строки документации объекта).801- [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner): Выполняет примеры в [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) и использует [`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker) для проверки их вывода.802- [`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker): Сравнивает фактический вывод примера doctest с ожидаемым выводом и определяет, совпадают ли они.803804Взаимосвязи между этими классами обработки показаны на следующей диаграмме.805806```python807 list of:808+------+ +---------+809|module| --DocTestFinder-> | DocTest | --DocTestRunner-> results810+------+ | ^ +---------+ | ^ (printed)811 | | | Example | | |812 v | | ... | v |813 DocTestParser | Example | OutputChecker814 +---------+815```816817### 25.2.6.1. Объекты DocTest818819#### `class doctest.DocTest(examples, globs, name, filename, lineno, docstring)`820821Набор примеров doctest, которые должны выполняться в одном пространстве имён. Аргументы конструктора инициализируют одноимённые атрибуты.822823Новое в версии 2.4.824825[`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) определяет следующие атрибуты. Они инициализируются конструктором и не должны изменяться напрямую.826827#### `examples`828829Список объектов [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example), представляющих отдельные интерактивные примеры Python, которые должны быть выполнены этим тестом.830831#### `globs`832833Пространство имён (также известное как globals), в котором должны выполняться примеры. Это словарь, отображающий имена в значения. Любые изменения пространства имён, сделанные примерами (например, связывание новых переменных), будут отражены в [`globs`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest.globs) после выполнения теста.834835#### `name`836837Строковое имя, идентифицирующее [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest). Обычно это имя объекта или файла, из которого был извлечён тест.838839#### `filename`840841Имя файла, из которого был извлечён этот [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest); или `None`, если имя файла неизвестно, или [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) не был извлечён из файла.842843#### `lineno`844845Номер строки внутри [`filename`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest.filename), с которой начинается данный [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest), или `None`, если номер строки недоступен. Этот номер строки отсчитывается от нуля относительно начала файла.846847#### `docstring`848849Строка, из которой был извлечён тест, или `None`, если строка недоступна, или если тест не был извлечён из строки.850851### 25.2.6.2. Объекты Example852853#### `class doctest.Example(source, want[, exc_msg][, lineno][, indent][, options])`854855Один интерактивный пример, состоящий из оператора Python и его ожидаемого вывода. Аргументы конструктора используются для инициализации атрибутов с теми же именами.856857Новое в версии 2.4.858859[`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example) определяет следующие атрибуты. Они инициализируются конструктором и не должны изменяться напрямую.860861#### `source`862863Строка, содержащая исходный код примера. Этот исходный код состоит из одного оператора Python и всегда заканчивается символом новой строки; конструктор добавляет символ новой строки при необходимости.864865#### `want`866867Ожидаемый результат выполнения исходного кода примера (либо из stdout, либо трассировка в случае исключения). [`want`](https://python-all.ru/2.7/library/doctest.html#doctest.Example.want) заканчивается символом новой строки, если только результат не ожидается; в этом случае это пустая строка. Конструктор добавляет символ новой строки при необходимости.868869#### `exc_msg`870871Сообщение об исключении, сгенерированное примером, если ожидается, что пример вызовет исключение; или `None`, если исключение не ожидается. Это сообщение об исключении сравнивается с возвращаемым значением [`traceback.format_exception_only()`](https://python-all.ru/2.7/library/traceback.html#traceback.format_exception_only). [`exc_msg`](https://python-all.ru/2.7/library/doctest.html#doctest.Example.exc_msg) заканчивается символом новой строки, если только оно не равно `None`. Конструктор добавляет символ новой строки при необходимости.872873#### `lineno`874875Номер строки внутри строки, содержащей этот пример, с которой начинается пример. Этот номер строки отсчитывается от нуля относительно начала содержащей строки.876877#### `indent`878879Отступ примера в содержащей строке, т.е. количество пробелов перед первым приглашением примера.880881#### `options`882883Словарь, отображающий флаги опций в `True` или `False`, который используется для переопределения опций по умолчанию для этого примера. Любые флаги опций, не содержащиеся в этом словаре, остаются в своем значении по умолчанию (как указано в [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner).`optionflags`). По умолчанию никакие опции не установлены.884885### 25.2.6.3. Объекты DocTestFinder886887#### `class doctest.DocTestFinder([verbose][, parser][, recurse][, exclude_empty])`888889Класс обработки, используемый для извлечения [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest), относящихся к заданному объекту, из его строки документации и строк документации содержащихся в нём объектов. [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) в настоящее время могут быть извлечены из следующих типов объектов: модули, функции, классы, методы, статические методы, методы класса и свойства.890891Необязательный аргумент *verbose* используется для отображения объектов, которые ищет поисковик. По умолчанию он равен `False` (вывод отсутствует).892893Необязательный аргумент *parser* задаёт объект [`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser) (или его замену), который используется для извлечения доктестов из строк документации.894895Если необязательный аргумент *recurse* равен false, то [`DocTestFinder.find()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder.find) будет проверять только указанный объект, но не содержащиеся в нём объекты.896897Если необязательный аргумент *exclude\_empty* равен false, то [`DocTestFinder.find()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder.find) будет включать тесты для объектов с пустыми строками документации.898899Новое в версии 2.4.900901[`DocTestFinder`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFinder) определяет следующий метод:902903#### `find(obj[, name][, module][, globs][, extraglobs])`904905Возвращает список [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest), определённых строкой документации *obj* или строками документации любых содержащихся в нём объектов.906907Необязательный аргумент *name* задаёт имя объекта; это имя будет использоваться для формирования имён возвращаемых [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest). Если *name* не указан, то используется `obj.__name__`.908909Необязательный параметр *module* – это модуль, содержащий указанный объект. Если модуль не указан или равен `None`, то поисковик тестов попытается автоматически определить правильный модуль. Модуль объекта используется:910911- В качестве пространства имён по умолчанию, если *globs* не указан.912- Чтобы предотвратить извлечение DocTests объектом DocTestFinder из объектов, импортированных из других модулей. (Содержащиеся объекты, чей модуль отличается от *module*, игнорируются.)913- Для поиска имени файла, содержащего объект.914- Для помощи в определении номера строки объекта в его файле.915916Если *module* равен `False`, попытка найти модуль не предпринимается. Это необычная возможность, используемая в основном при тестировании самого doctest: если *module* равен `False` или `None`, но не может быть найден автоматически, то все объекты считаются принадлежащими (несуществующему) модулю, поэтому все содержащиеся объекты будут (рекурсивно) проверяться на наличие доктестов.917918Глобальные переменные для каждого [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest) формируются объединением *globs* и *extraglobs* (привязки в *extraglobs* переопределяют привязки в *globs*). Создаётся новая поверхностная копия словаря глобальных переменных для каждого [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest). Если *globs* не указано, то по умолчанию используется *\_\_dict\_\_* модуля, если он указан, или `{}` в противном случае. Если *extraglobs* не указано, то по умолчанию используется `{}`.919920### 25.2.6.4. Объекты DocTestParser921922#### `class doctest.DocTestParser`923924Класс обработки, используемый для извлечения интерактивных примеров из строки и создания из них объекта [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest).925926Новое в версии 2.4.927928[`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser) определяет следующие методы:929930#### `get_doctest(string, globs, name, filename, lineno)`931932Извлекает все примеры доктестов из заданной строки и собирает их в объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest).933934*globs*, *name*, *filename* и *lineno* – это атрибуты нового объекта [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest). Дополнительную информацию см. в документации [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest).935936#### `get_examples(string[, name])`937938Извлекает все примеры доктестов из заданной строки и возвращает их в виде списка объектов [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example). Номера строк начинаются с 0. Необязательный аргумент *name* – это имя, идентифицирующее данную строку; используется только для сообщений об ошибках.939940#### `parse(string[, name])`941942Разделяет заданную строку на примеры и промежуточный текст и возвращает их в виде списка, чередующего [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example) и строки. Номера строк для [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example) начинаются с 0. Необязательный аргумент *name* – это имя, идентифицирующее данную строку; используется только для сообщений об ошибках.943944### 25.2.6.5. Объекты DocTestRunner945946#### `class doctest.DocTestRunner([checker][, verbose][, optionflags])`947948Класс обработки, используемый для выполнения и проверки интерактивных примеров в [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest).949950Сравнение ожидаемых и фактических выходных данных выполняется с помощью [`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker). Это сравнение можно настроить с помощью ряда флагов опций; подробнее см. раздел [Флаги опций](https://python-all.ru/2.7/library/doctest.html#doctest-options). Если флагов опций недостаточно, сравнение можно также настроить, передав подкласс [`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker) в конструктор.951952Выводом тестового исполнителя можно управлять двумя способами. Во-первых, можно передать функцию вывода в `TestRunner.run()`; эта функция будет вызываться со строками, которые нужно отобразить. По умолчанию используется `sys.stdout.write`. Если захвата вывода недостаточно, то вывод также можно настроить, создав подкласс DocTestRunner и переопределив методы [`report_start()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.report_start), [`report_success()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.report_success), [`report_unexpected_exception()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.report_unexpected_exception) и [`report_failure()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.report_failure).953954Необязательный именованный аргумент *checker* задаёт [`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker) объект (или замену без изменений), который следует использовать для сравнения ожидаемых выходных данных с фактическими результатами выполнения примеров doctest.955956Необязательный именованный аргумент *verbose* управляет подробностью [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner). Если *verbose* равен `True`, то выводится информация о каждом примере по мере его выполнения. Если *verbose* равен `False`, то выводятся только сбои. Если *verbose* не указан или равен `None`, то подробный вывод используется, только если указан ключ командной строки `-v`.957958Необязательный именованный аргумент *optionflags* позволяет управлять тем, как исполнитель тестов сравнивает ожидаемый вывод с фактическим и как отображает ошибки. Дополнительную информацию см. в разделе [Флаги опций](https://python-all.ru/2.7/library/doctest.html#doctest-options).959960Новое в версии 2.4.961962[`DocTestParser`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestParser) определяет следующие методы:963964#### `report_start(out, test, example)`965966Сообщает, что исполнитель тестов собирается обработать указанный пример. Этот метод предоставляется, чтобы позволить подклассам [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner) настраивать свой вывод; его не следует вызывать напрямую.967968*example* – это пример, который будет обработан. *test* – это тест, *содержащий пример*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.run).969970#### `report_success(out, test, example, got)`971972Сообщает, что указанный пример выполнен успешно. Этот метод предоставляется, чтобы позволить подклассам [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner) настраивать свой вывод; его не следует вызывать напрямую.973974*example* – это пример, который будет обработан. *got* – это фактический вывод из примера. *test* – это тест, содержащий *example*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.run).975976#### `report_failure(out, test, example, got)`977978Сообщает, что указанный пример провален. Этот метод предоставляется, чтобы позволить подклассам [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner) настраивать свой вывод; его не следует вызывать напрямую.979980*example* – это пример, который будет обработан. *got* – это фактический вывод из примера. *test* – это тест, содержащий *example*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.run).981982#### `report_unexpected_exception(out, test, example, exc_info)`983984Сообщает, что указанный пример вызвал неожиданное исключение. Этот метод предоставляется, чтобы позволить подклассам [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner) настраивать свой вывод; его не следует вызывать напрямую.985986*example* – это пример, который будет обработан. *exc\_info* – это кортеж, содержащий информацию о неожиданном исключении (возвращаемый функцией [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info)). *test* – это тест, содержащий *example*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner.run).987988#### `run(test[, compileflags][, out][, clear_globs])`989990Выполняет примеры в *test* (объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest)) и отображает результаты с помощью функции вывода *out*.991992Примеры выполняются в пространстве имён `test.globs`. Если *clear\_globs* имеет значение true (по умолчанию), то это пространство имён будет очищено после выполнения теста для сборки мусора. Если требуется изучить пространство имён после завершения теста, используйте *clear\_globs=False*.993994*compileflags* задаёт набор флагов, которые должен использовать компилятор Python при выполнении примеров. Если не указан, по умолчанию используется набор флагов future-import, действующих для *globs*.995996Вывод каждого примера проверяется с помощью средства проверки вывода [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner), а результаты форматируются методами `DocTestRunner.report_*()`.997998#### `summarize([verbose])`9991000Выводит сводку всех тестовых случаев, выполненных этим DocTestRunner, и возвращает [именованный кортеж](https://python-all.ru/2.7/glossary.html#term-named-tuple) `TestResults(failed, attempted)`.10011002Необязательный аргумент *verbose* управляет степенью детализации сводки. Если степень детализации не указана, то используется [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner).10031004Изменено в версии 2.6: Используйте именованный кортеж.10051006### 25.2.6.6. Объекты OutputChecker10071008#### `class doctest.OutputChecker`10091010Класс, используемый для проверки, совпадает ли фактический вывод примера доктеста с ожидаемым выводом. [`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker) определяет два метода: [`check_output()`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker.check_output), который сравнивает заданную пару выводов и возвращает true, если они совпадают; и [`output_difference()`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker.output_difference), который возвращает строку, описывающую различия между двумя выводами.10111012Новое в версии 2.4.10131014[`OutputChecker`](https://python-all.ru/2.7/library/doctest.html#doctest.OutputChecker) определяет следующие методы:10151016#### `check_output(want, got, optionflags)`10171018Возвращает `True`, если фактический вывод примера (*got*) совпадает с ожидаемым выводом (*want*). Эти строки всегда считаются совпадающими, если они идентичны; но в зависимости от того, какие флаги опций использует test runner, возможны и несколько нестрогих типов совпадений. См. раздел [Option Flags](https://python-all.ru/2.7/library/doctest.html#doctest-options) для получения дополнительной информации о флагах опций.10191020#### `output_difference(example, got, optionflags)`10211022Возвращает строку с описанием различий между ожидаемым выводом для заданного примера (*example*) и фактическим выводом (*got*). *optionflags* – это набор флагов опций, используемых для сравнения *want* и *got*.10231024## 25.2.7. Отладка10251026Doctest предоставляет несколько механизмов для отладки примеров doctest:10271028- Некоторые функции преобразуют doctest в исполняемые программы Python, которые можно запускать под отладчиком Python, [`pdb`](https://python-all.ru/2.7/library/pdb.html#module-pdb).1029- Класс [`DebugRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DebugRunner) является подклассом [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner), который вызывает исключение для первого неудачного примера, содержащее информацию об этом примере. Эту информацию можно использовать для посмертной отладки примера.1030- Случаи [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), сгенерированные [`DocTestSuite()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestSuite), поддерживают метод [`debug()`](https://python-all.ru/2.7/library/doctest.html#doctest.debug), определённый [`unittest.TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase).1031- Можно добавить вызов [`pdb.set_trace()`](https://python-all.ru/2.7/library/pdb.html#pdb.set_trace) в пример doctest, и при выполнении этой строки произойдёт вход в отладчик Python. Затем можно проверять текущие значения переменных и т.д. Например, предположим, что `a.py` содержит только эту строку документации модуля:10321033 ```python1034 """1035 >>> def f(x):1036 ... g(x*2)1037 >>> def g(x):1038 ... print x+31039 ... import pdb; pdb.set_trace()1040 >>> f(3)1041 91042 """1043 ```10441045 Тогда интерактивный сеанс Python может выглядеть так:10461047 ```python1048 >>> import a, doctest1049 >>> doctest.testmod(a)1050 --Return--1051 > <doctest a[1]>(3)g()->None1052 -> import pdb; pdb.set_trace()1053 (Pdb) list1054 1 def g(x):1055 2 print x+31056 3 -> import pdb; pdb.set_trace()1057 [EOF]1058 (Pdb) print x1059 61060 (Pdb) step1061 --Return--1062 > <doctest a[0]>(2)f()->None1063 -> g(x*2)1064 (Pdb) list1065 1 def f(x):1066 2 -> g(x*2)1067 [EOF]1068 (Pdb) print x1069 31070 (Pdb) step1071 --Return--1072 > <doctest a[2]>(1)?()->None1073 -> f(3)1074 (Pdb) cont1075 (0, 3)1076 >>>1077 ```10781079 Изменено в версии 2.4: Добавлена возможность полезно использовать [`pdb.set_trace()`](https://python-all.ru/2.7/library/pdb.html#pdb.set_trace) внутри доктестов.10801081Функции, которые преобразуют doctest в код Python и, возможно, запускают полученный код под отладчиком:10821083#### `doctest.script_from_examples(s)`10841085Преобразует текст с примерами в скрипт.10861087Аргумент *s* – это строка, содержащая примеры doctest. Строка преобразуется в скрипт Python, где примеры doctest из *s* преобразуются в обычный код, а всё остальное – в комментарии Python. Сгенерированный скрипт возвращается в виде строки. Например,10881089```python1090import doctest1091print doctest.script_from_examples(r"""1092 Set x and y to 1 and 2.1093 >>> x, y = 1, 210941095 Print their sum:1096 >>> print x+y1097 31098""")1099```11001101выводит:11021103```python1104# Установите x и y в 1 и 2.1105x, y = 1, 21106#1107# Выведите их сумму:1108print x+y1109# Ожидаемый результат:1110## 31111```11121113Эта функция используется внутренне другими функциями (см. ниже), но также может быть полезна, когда требуется преобразовать интерактивный сеанс Python в скрипт Python.11141115Новое в версии 2.4.11161117#### `doctest.testsource(module, name)`11181119Преобразует доктест объекта в скрипт.11201121Аргумент *module* – это объект модуля или точечное имя модуля, содержащего объект, чьи доктесты интересуют. Аргумент *name* – это имя (внутри модуля) объекта с интересующими доктестами. Результат – строка, содержащая строку документации объекта, преобразованная в скрипт Python, как описано для [`script_from_examples()`](https://python-all.ru/2.7/library/doctest.html#doctest.script_from_examples) выше. Например, если модуль `a.py` содержит функцию верхнего уровня `f()`, то11221123```python1124import a, doctest1125print doctest.testsource(a, "a.f")1126```11271128выводит скриптовую версию строки документации функции `f()`, при этом доктесты преобразуются в код, а остальное помещается в комментарии.11291130Новое в версии 2.3.11311132#### `doctest.debug(module, name[, pm])`11331134Отладка доктестов для объекта.11351136Аргументы *module* и *name* такие же, как и для функции [`testsource()`](https://python-all.ru/2.7/library/doctest.html#doctest.testsource) выше. Синтезированный скрипт Python из строки документации указанного объекта записывается во временный файл, а затем этот файл выполняется под управлением отладчика Python, [`pdb`](https://python-all.ru/2.7/library/pdb.html#module-pdb).11371138Для локального и глобального контекста выполнения используется поверхностная копия `module.__dict__`.11391140Необязательный аргумент *pm* определяет, используется ли посмертная отладка. Если *pm* имеет истинное значение, файл скрипта выполняется напрямую, и отладчик подключается только в случае завершения скрипта из-за необработанного исключения. Если это происходит, то вызывается посмертная отладка через [`pdb.post_mortem()`](https://python-all.ru/2.7/library/pdb.html#pdb.post_mortem) с передачей объекта traceback из необработанного исключения. Если *pm* не указан или равен false, скрипт выполняется под отладчиком с самого начала, путем передачи соответствующего вызова [`execfile()`](https://python-all.ru/2.7/library/functions.html#execfile) в [`pdb.run()`](https://python-all.ru/2.7/library/pdb.html#pdb.run).11411142Новое в версии 2.3.11431144Изменено в версии 2.4: Добавлен аргумент *pm*.11451146#### `doctest.debug_src(src[, pm][, globs])`11471148Отладка доктестов в строке.11491150Эта функция похожа на функцию [`debug()`](https://python-all.ru/2.7/library/doctest.html#doctest.debug) выше, за исключением того, что строка, содержащая примеры доктестов, задается напрямую через аргумент *src*.11511152Необязательный аргумент *pm* имеет тот же смысл, что и в функции [`debug()`](https://python-all.ru/2.7/library/doctest.html#doctest.debug) выше.11531154Необязательный аргумент *globs* задает словарь, используемый как для локального, так и для глобального контекста выполнения. Если он не указан или равен `None`, используется пустой словарь. Если указан, используется поверхностная копия словаря.11551156Новое в версии 2.4.11571158Класс [`DebugRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DebugRunner) и специальные исключения, которые он может вызывать, представляют наибольший интерес для разработчиков тестовых фреймворков и будут лишь кратко описаны здесь. За подробностями обращайтесь к исходному коду и особенно к строке документации [`DebugRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DebugRunner) (которая сама является доктестом!).11591160#### `class doctest.DebugRunner([checker][, verbose][, optionflags])`11611162Подкласс [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner), который вызывает исключение сразу при обнаружении сбоя. Если происходит неожиданное исключение, вызывается исключение [`UnexpectedException`](https://python-all.ru/2.7/library/doctest.html#doctest.UnexpectedException), содержащее тест, пример и исходное исключение. Если вывод не совпадает, вызывается исключение [`DocTestFailure`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFailure), содержащее тест, пример и фактический вывод.11631164Информацию о параметрах конструктора и методах см. в документации для [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner) в разделе [Advanced API](https://python-all.ru/2.7/library/doctest.html#doctest-advanced-api).11651166Экземпляры [`DebugRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DebugRunner) могут вызывать два исключения:11671168#### `exception doctest.DocTestFailure(test, example, got)`11691170Исключение, вызываемое [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner), чтобы указать, что фактический вывод примера доктеста не совпал с ожидаемым. Аргументы конструктора используются для инициализации одноименных атрибутов.11711172[`DocTestFailure`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestFailure) определяет следующие атрибуты:11731174#### `DocTestFailure.test`11751176Объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest), который выполнялся, когда пример завершился с ошибкой.11771178#### `DocTestFailure.example`11791180Неудавшийся [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example).11811182#### `DocTestFailure.got`11831184Фактический вывод примера.11851186#### `exception doctest.UnexpectedException(test, example, exc_info)`11871188Исключение, вызываемое [`DocTestRunner`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTestRunner), чтобы указать, что пример доктеста вызвал неожиданное исключение. Аргументы конструктора используются для инициализации одноименных атрибутов.11891190[`UnexpectedException`](https://python-all.ru/2.7/library/doctest.html#doctest.UnexpectedException) определяет следующие атрибуты:11911192#### `UnexpectedException.test`11931194Объект [`DocTest`](https://python-all.ru/2.7/library/doctest.html#doctest.DocTest), который выполнялся, когда пример завершился с ошибкой.11951196#### `UnexpectedException.example`11971198Неудавшийся [`Example`](https://python-all.ru/2.7/library/doctest.html#doctest.Example).11991200#### `UnexpectedException.exc_info`12011202Кортеж, содержащий информацию о неожиданном исключении, возвращаемый вызовом [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info).12031204## 25.2.8. Трибуна12051206Как уже упоминалось во введении, у [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) появилось три основных назначения:120712081. Проверка примеров в docstrings.12092. Регрессионное тестирование.12103. Исполняемая документация / литературное тестирование.12111212Эти варианты использования предъявляют разные требования, и важно их различать. В частности, наполнение строк документации запутанными тестовыми примерами приводит к плохой документации.12131214При написании docstring'ов выбирайте примеры для них с осторожностью. Это целое искусство, которому нужно учиться, и поначалу оно может даваться нелегко. Примеры должны приносить реальную пользу документации. Хороший пример зачастую дорогого стоит. Если подойти к делу со всей тщательностью, примеры станут бесценными для пользователей и многократно окупят время, потраченное на их сбор, – годы спустя, когда всё меняется. Я до сих пор поражаюсь, как часто мои примеры [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) перестают работать после «безобидных» изменений.12151216Doctest также отлично подходит для регрессионного тестирования, особенно если не жалеть пояснительного текста. Чередуя прозу и примеры, гораздо легче отслеживать, что именно тестируется и почему. Когда тест падает, хороший текст помогает быстрее понять, в чём проблема и как её исправить. Конечно, можно писать развёрнутые комментарии в коде тестов, но мало кто это делает. Многие заметили, что использование doctest вместо этого приводит к гораздо более понятным тестам. Возможно, просто потому, что в doctest писать прозу немного легче, чем код, а писать комментарии в коде – немного сложнее. Но я думаю, дело не только в этом: естественный подход при написании теста на основе doctest – это желание объяснить тонкости своего программного обеспечения и проиллюстрировать их примерами. Это, в свою очередь, естественным образом приводит к тестовым файлам, которые начинаются с самых простых функций и логически переходят к осложнениям и крайним случаям. В результате получается связное повествование, а не набор разрозненных функций, тестирующих отдельные фрагменты функциональности, казалось бы, случайным образом. Это другой подход, и он даёт другие результаты, стирая грань между тестированием и объяснением.12171218Регрессионное тестирование лучше всего проводить в отдельных объектах или файлах. Есть несколько вариантов организации тестов:12191220- Создайте текстовые файлы, содержащие тестовые примеры в виде интерактивных примеров, и тестируйте эти файлы с помощью [`testfile()`](https://python-all.ru/2.7/library/doctest.html#doctest.testfile) или [`DocFileSuite()`](https://python-all.ru/2.7/library/doctest.html#doctest.DocFileSuite). Этот подход рекомендуется, хотя его проще всего применить для новых проектов, изначально спроектированных с использованием doctest.1221- Определите функции с именем `_regrtest_topic`, которые состоят из одной строки документации, содержащей тестовые примеры для указанных тем. Эти функции можно включить в тот же файл, что и модуль, или вынести в отдельный тестовый файл.1222- Определите словарь `__test__`, отображающий темы регрессионных тестов на docstrings, содержащие тестовые примеры.12231224Если вы поместили тесты в модуль, сам модуль может быть тестовым раннером. Когда тест падает, можно настроить раннер на повторный запуск только упавшего doctest'а, пока вы отлаживаете проблему. Вот минимальный пример такого тестового раннера:12251226```python1227if __name__ == '__main__':1228 import doctest1229 flags = doctest.REPORT_NDIFF|doctest.REPORT_ONLY_FIRST_FAILURE1230 if len(sys.argv) > 1:1231 name = sys.argv[1]1232 if name in globals():1233 obj = globals()[name]1234 else:1235 obj = __test__[name]1236 doctest.run_docstring_examples(obj, globals(), name=name,1237 optionflags=flags)1238 else:1239 fail, total = doctest.testmod(optionflags=flags)1240 print("{} failures out of {} tests".format(fail, total))1241```12421243Сноски12441245**[1](https://python-all.ru/2.7/library/doctest.html#id1)**12461247Примеры, содержащие как ожидаемый вывод, так и исключение, не поддерживаются. Попытка угадать, где заканчивается одно и начинается другое, слишком чревата ошибками и приводит к запутанным тестам.1248