doctest.md
1> **Источник:** https://python-all.ru/3.1/library/doctest.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 25.2. `doctest` – Тестирование интерактивных примеров Python89Модуль `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 >>> [factorial(n) for n in range(6)]31 [1, 1, 2, 6, 24, 120]32 >>> factorial(30)33 26525285981219105863630848000000034 >>> factorial(-1)35 Traceback (самый последний вызов последним):36 ...37 ValueError: n должно быть >= 03839 Факториалы чисел с плавающей точкой допустимы, но число должно быть точным целым:40 >>> factorial(30.1)41 Traceback (самый последний вызов последним):42 ...43 ValueError: n должно быть целым числом44 >>> factorial(30.0)45 2652528598121910586363084800000004647 Оно также не должно быть нелепо большим:48 >>> factorial(1e100)49 Traceback (самый последний вызов последним):50 ...51 OverflowError: n слишком велико52 """5354 import math55 if not n >= 0:56 raise ValueError("n must be >= 0")57 if math.floor(n) != n:58 raise ValueError("n must be exact integer")59 if n+1 == n: # перехватить значение, например 1e30060 raise OverflowError("n too large")61 result = 162 factor = 263 while factor <= n:64 result *= factor65 factor += 166 return result6768if __name__ == "__main__":69 import doctest70 doctest.testmod()71```7273Если запустить `example.py` непосредственно из командной строки, `doctest` делает своё волшебство:7475```python76$ python example.py77$78```7980Вывода нет! Это нормально и означает, что все примеры сработали. Передайте скрипту `-v`, и `doctest` выведет подробный журнал того, что он пробует, а в конце – сводку:8182```python83$ python example.py -v84Trying:85 factorial(5)86Expecting:87 12088ok89Trying:90 [factorial(n) for n in range(6)]91Expecting:92 [1, 1, 2, 6, 24, 120]93ok94```9596И так далее, в конечном итоге завершаясь:9798```python99Trying:100 factorial(1e100)101Expecting:102 Traceback (most recent call last):103 ...104 OverflowError: n too large105ok1062 items passed all tests:107 1 tests in __main__108 8 tests in __main__.factorial1099 tests in 2 items.1109 passed and 0 failed.111Test passed.112$113```114115Это всё, что нужно знать, чтобы начать продуктивно использовать `doctest`! Погружайтесь. Следующие разделы содержат полные подробности. Обратите внимание, что в стандартном наборе тестов и библиотеках Python есть много примеров doctest. Особенно полезные примеры можно найти в стандартном тестовом файле `Lib/test/test_doctest.py`.116117## 25.2.1. Простое использование: проверка примеров в строках документации118119Самый простой способ начать использовать doctest (но не обязательно тот, которым вы будете продолжать пользоваться) – это завершить каждый модуль `M` следующим образом:120121```python122if __name__ == "__main__":123 import doctest124 doctest.testmod()125```126127Затем `doctest` анализирует докстринги в модуле `M`.128129Запуск модуля как скрипта приводит к тому, что примеры в докстрингах выполняются и проверяются:130131```python132python M.py133```134135Это не выведет ничего, если только какой-нибудь пример не завершится ошибкой. В этом случае неудачные примеры и причины сбоев выводятся в stdout, а последняя строка вывода выглядит как `***Test Failed*** N failures.`, где *N* – количество примеров, завершившихся ошибкой.136137Вместо этого запустите его с флагом `-v`:138139```python140python M.py -v141```142143и подробный отчёт обо всех проверенных примерах выводится в стандартный вывод, а в конце – различные сводки.144145Можно принудительно включить подробный режим, передав `verbose=True` в [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod), или запретить его, передав `verbose=False`. В любом из этих случаев `sys.argv` не проверяется [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod) (поэтому передача `-v` или её отсутствие не имеет эффекта).146147Существует также сокращение в командной строке для запуска [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod). Можно указать интерпретатору Python запустить модуль doctest непосредственно из стандартной библиотеки и передать имена модулей в командной строке:148149```python150python -m doctest -v example.py151```152153Это импортирует `example.py` как самостоятельный модуль и запустит на нём [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod). Обратите внимание, что это может работать неправильно, если файл является частью пакета и импортирует другие подмодули из этого пакета.154155Дополнительную информацию о [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod) см. в разделе [*Basic API*](https://python-all.ru/3.1/library/doctest.html#doctest-basic-api).156157## 25.2.2. Простое использование: проверка примеров в текстовом файле158159Ещё одно простое применение doctest – тестирование интерактивных примеров в текстовом файле. Это можно сделать с помощью функции [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile):160161```python162import doctest163doctest.testfile("example.txt")164```165166Этот короткий скрипт выполняет и проверяет любые интерактивные примеры Python, содержащиеся в файле `example.txt`. Содержимое файла обрабатывается так, как если бы это была одна гигантская строка документации; файлу не нужно содержать программу на Python! Например, возможно, `example.txt` содержит следующее:167168```python169The ``example`` module170======================171172Using ``factorial``173-------------------174175This is an example text file in reStructuredText format. First import176``factorial`` from the ``example`` module:177178 >>> from example import factorial179180Now use it:181182 >>> factorial(6)183 120184```185186Запуск `doctest.testfile("example.txt")` затем находит ошибку в этой документации:187188```python189File "./example.txt", line 14, in example.txt190Failed example:191 factorial(6)192Expected:193 120194Got:195 720196```197198Как и [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod), [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) не будет ничего выводить, если пример не завершится сбоем. Если же пример завершается сбоем, то неудачные примеры и причины сбоев выводятся в stdout в том же формате, что и в [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod).199200По умолчанию [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) ищет файлы в каталоге вызывающего модуля. Описание необязательных аргументов, которые можно использовать, чтобы указать ему искать файлы в других местах, см. в разделе [*Basic API*](https://python-all.ru/3.1/library/doctest.html#doctest-basic-api).201202Как и у [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod), степень подробности [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) можно задать с помощью флага командной строки `-v` или необязательного ключевого аргумента *verbose*.203204Существует также сокращение в командной строке для запуска [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile). Можно указать интерпретатору Python запустить модуль doctest непосредственно из стандартной библиотеки и передать имена файлов в командной строке:205206```python207python -m doctest -v example.txt208```209210Поскольку имя файла не заканчивается на `.py`, `doctest` заключает, что его нужно запускать с [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile), а не с [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod).211212Дополнительную информацию о [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) см. в разделе [*Basic API*](https://python-all.ru/3.1/library/doctest.html#doctest-basic-api).213214## 25.2.3. Как это работает215216В этом разделе подробно рассматривается, как работает doctest: какие docstrings он просматривает, как находит интерактивные примеры, какой контекст выполнения использует, как обрабатывает исключения и как опции могут управлять его поведением. Это информация, которую нужно знать для написания примеров doctest; сведения о непосредственном запуске doctest на этих примерах приведены в следующих разделах.217218### 25.2.3.1. Какие строки документации проверяются?219220Проверяются docstring модуля, а также docstrings всех функций, классов и методов. Объекты, импортированные в модуль, не проверяются.221222Кроме того, если `M.__test__` существует и "истинно", это должен быть словарь, и каждая запись сопоставляет (строковое) имя с объектом функции, объектом класса или строкой. Строки документации объектов функций и классов, найденные через `M.__test__`, ищутся, а строки обрабатываются так, как если бы они были строками документации. В выводе ключ `K` в `M.__test__` появляется с именем223224```python225<name of M>.__test__.K226```227228Любые найденные классы аналогично рекурсивно проверяются на наличие docstrings в содержащихся в них методах и вложенных классах.229230### 25.2.3.2. Как распознаются примеры из строк документации?231232В большинстве случаев копирование и вставка сессии интерактивной консоли работает нормально, но doctest не пытается точно эмулировать какой-либо конкретный Python shell.233234```python235>>> # комментарии игнорируются236>>> x = 12237>>> x23812239>>> if x == 13:240... print("yes")241... else:242... print("no")243... print("NO")244... print("NO!!!")245...246no247NO248NO!!!249>>>250```251252Любой ожидаемый вывод должен сразу следовать за последней строкой `'>>> '` или `'... '`, содержащей код, и ожидаемый вывод (если есть) простирается до следующей строки `'>>> '` или строки, состоящей только из пробелов.253254Мелкий шрифт:255256- Ожидаемый вывод не может содержать строку, состоящую только из пробелов, поскольку такая строка воспринимается как сигнал конца ожидаемого вывода. Если ожидаемый вывод содержит пустую строку, поместите `<BLANKLINE>` в пример doctest в каждом месте, где ожидается пустая строка.257- Все символы жесткой табуляции заменяются пробелами с шагом в 8 столбцов. Табуляция в выводе тестируемого кода не изменяется. Поскольку все символы табуляции в образце вывода *заменяются*, это означает, что если вывод кода содержит жесткую табуляцию, doctest может пройти только при наличии опции или директивы [`NORMALIZE_WHITESPACE`](https://python-all.ru/3.1/library/doctest.html#doctest.NORMALIZE_WHITESPACE). В качестве альтернативы тест можно переписать так, чтобы захватывать вывод и сравнивать его с ожидаемым значением в рамках теста. Такой подход к обработке табуляции в исходном коде был найден методом проб и ошибок и оказался наименее подверженным ошибкам. Можно использовать другой алгоритм обработки табуляции, написав собственный класс [`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser).258- Вывод в stdout перехватывается, но не вывод в stderr (трассировки исключений перехватываются другим способом).259- Если вы продолжаете строку обратной косой чертой в интерактивной сессии или по любой другой причине используете обратную косую черту, следует использовать сырой docstring, который сохранит обратные косые черты точно в том виде, как вы их ввели:260261 ```python262 >>> def f(x):263 ... r'''Backslashes in a raw docstring: m\n'''264 >>> print(f.__doc__)265 Backslashes in a raw docstring: m\n266 ```267268 В противном случае обратная косая черта будет интерпретироваться как часть строки. Например, «\\» выше интерпретировалась бы как символ новой строки. В качестве альтернативы можно удвоить каждую обратную косую черту в версии doctest (и не использовать сырую строку):269270 ```python271 >>> def f(x):272 ... '''Обратная косая черта в сырой докстринге: m\\n'''273 >>> print(f.__doc__)274 Backslashes in a raw docstring: m\n275 ```276- Начальный столбец не имеет значения:277278 ```python279 >>> assert "Easy!"280 >>> import math281 >>> math.floor(1.9)282 1283 ```284285 а также из ожидаемого вывода удаляется столько начальных пробельных символов, сколько их было в исходной строке `'>>> '`, с которой начинался пример.286287### 25.2.3.3. Каков контекст выполнения?288289По умолчанию каждый раз, когда `doctest` находит docstring для тестирования, он использует *поверхностную копию* глобальных переменных `M`, чтобы выполнение тестов не изменяло реальные глобальные переменные модуля, и чтобы один тест в `M` не оставлял следов, которые случайно помогли бы другому тесту сработать. Это означает, что примеры могут свободно использовать любые имена, определённые на верхнем уровне в `M`, и имена, определённые ранее в выполняемом docstring. Примеры не видят имена, определённые в других docstring.290291Можно принудительно использовать собственный словарь в качестве контекста выполнения, передав `globs=your_dict` в [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod) или [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile).292293### 25.2.3.4. Что насчет исключений?294295Никаких проблем, при условии, что трассировка – единственный вывод, выдаваемый примером: просто вставьте трассировку. [\[1\]](https://python-all.ru/3.1/library/doctest.html#id2) Поскольку трассировки содержат детали, которые могут быстро меняться (например, точные пути к файлам и номера строк), это тот случай, когда doctest старается быть гибким в том, что он принимает.296297Простой пример:298299```python300>>> [1, 2, 3].remove(42)301Traceback (most recent call last):302 File "<stdin>", line 1, in ?303ValueError: list.remove(x): x not in list304```305306Этот doctest завершается успешно, если возбуждается [`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError), с сообщением `list.remove(x): x not in list`, как показано.307308Ожидаемый вывод для исключения должен начинаться с заголовка трассировки, которым может быть одна из следующих двух строк, с отступом, совпадающим с первой строкой примера:309310```python311Traceback (most recent call last):312Traceback (innermost last):313```314315За заголовком трассировки следует необязательный стек трассировки, содержимое которого игнорируется doctest. Стек трассировки обычно опускается или копируется дословно из интерактивного сеанса.316317За стеком трассировки следует самая интересная часть: строка(и), содержащие тип исключения и его описание. Обычно это последняя строка трассировки, но может занимать несколько строк, если у исключения многострочное описание:318319```python320>>> raise ValueError('multi\n line\ndetail')321Traceback (most recent call last):322 File "<stdin>", line 1, in ?323ValueError: multi324 line325detail326```327328Последние три строки (начиная с [`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError)) сравниваются с типом и сообщением исключения, а остальные игнорируются.329330Лучшая практика – опускать стек трассировки, если он не добавляет существенной документационной ценности примеру. Так что последний пример, вероятно, лучше оформить так:331332```python333>>> raise ValueError('multi\n line\ndetail')334Traceback (most recent call last):335 ...336ValueError: multi337 line338detail339```340341Обратите внимание, что трассировки обрабатываются особым образом. В частности, в переписанном примере использование `...` не зависит от опции [`ELLIPSIS`](https://python-all.ru/3.1/library/doctest.html#doctest.ELLIPSIS) модуля doctest. Многоточие в этом примере можно опустить или заменить тремя (или тремястами) запятыми, цифрами или даже отформатированной стенограммой скетча Монти Пайтона.342343Некоторые детали, которые стоит прочитать один раз, но запоминать не обязательно:344345- Doctest не может угадать, взялся ли ожидаемый вывод из трассировки исключения или из обычной печати. Так, например, пример, ожидающий `ValueError: 42 является простым числом` будет пройден, независимо от того, действительно ли возбуждено [`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError) или пример просто печатает этот текст трассировки. На практике обычный вывод редко начинается со строки заголовка трассировки, так что это не создаёт реальных проблем.346- Каждая строка стека трассировки (если присутствует) должна иметь отступ больше, чем первая строка примера, *или* начинаться с небуквенно-цифрового символа. Первая строка после заголовка трассировки с таким же отступом и начинающаяся с буквенно-цифрового символа считается началом описания исключения. Конечно, это корректно работает для настоящих трассировок.347- Когда указана опция doctest [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/3.1/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL), всё, что идёт после самой левой двоеточия, игнорируется.348- Интерактивная оболочка опускает строку заголовка трассировки для некоторых [`SyntaxError`](https://python-all.ru/3.1/library/exceptions.html#SyntaxError). Но doctest использует строку заголовка трассировки, чтобы отличать исключения от не-исключений. Поэтому в редком случае, когда нужно протестировать [`SyntaxError`](https://python-all.ru/3.1/library/exceptions.html#SyntaxError), в котором отсутствует заголовок трассировки, потребуется вручную добавить строку заголовка трассировки в тестовый пример.349- Для некоторых [`SyntaxError`](https://python-all.ru/3.1/library/exceptions.html#SyntaxError) Python отображает позицию символа синтаксической ошибки, используя маркер `^`:350351 ```python352 >>> 1 1353 File "<stdin>", line 1354 1 1355 ^356 SyntaxError: invalid syntax357 ```358359 Поскольку строки, показывающие положение ошибки, идут до типа и описания исключения, они не проверяются doctest. Например, следующий тест будет пройден, даже если `^`-маркер поставлен в неверное место:360361 ```python362 >>> 1 1363 Traceback (most recent call last):364 File "<stdin>", line 1365 1 1366 ^367 SyntaxError: invalid syntax368 ```369370### 25.2.3.5. Флаги опций и директивы371372Ряд флагов опций управляют различными аспектами поведения doctest. Символические имена для флагов предоставляются в виде констант модуля, которые можно объединять операцией OR и передавать различным функциям. Эти имена также можно использовать в директивах doctest (см. ниже).373374Первая группа опций определяет семантику тестов, управляя аспектами того, как doctest решает, соответствует ли фактический вывод ожидаемому выводу примера:375376#### `doctest.DONT_ACCEPT_TRUE_FOR_1`377378По умолчанию, если блок ожидаемого вывода содержит просто379380`1`381382, блок фактического вывода, содержащий просто383384`1`385386или просто387388`True`389390, считается совпадением, и аналогично для391392`0`393394по сравнению с395396`False`397398. Когда указан399400[`DONT_ACCEPT_TRUE_FOR_1`](https://python-all.ru/3.1/library/doctest.html#doctest.DONT_ACCEPT_TRUE_FOR_1)401402, ни одна из замен не допускается. Поведение по умолчанию учитывает, что Python изменил тип возвращаемого значения многих функций с целого числа на булев; doctests, ожидающие вывод «маленького целого», всё ещё работают в этих случаях. Эта опция, вероятно, исчезнет, но не в ближайшие годы.403404#### `doctest.DONT_ACCEPT_BLANKLINE`405406По умолчанию, если блок ожидаемого вывода содержит строку, содержащую только строку407408`<BLANKLINE>`409410, то эта строка будет соответствовать пустой строке в фактическом выводе. Поскольку настоящая пустая строка разделяет ожидаемый вывод, это единственный способ указать, что ожидается пустая строка. Когда указан411412[`DONT_ACCEPT_BLANKLINE`](https://python-all.ru/3.1/library/doctest.html#doctest.DONT_ACCEPT_BLANKLINE)413414, эта замена не допускается.415416#### `doctest.NORMALIZE_WHITESPACE`417418Если указано, все последовательности пробельных символов (пробелы и новые строки) считаются равными. Любая последовательность пробельных символов в ожидаемом выводе будет соответствовать любой последовательности пробельных символов в фактическом выводе. По умолчанию пробельные символы должны совпадать в точности.419420[`NORMALIZE_WHITESPACE`](https://python-all.ru/3.1/library/doctest.html#doctest.NORMALIZE_WHITESPACE)421422особенно полезен, когда строка ожидаемого вывода очень длинная, и вы хотите перенести её на несколько строк в исходном коде.423424#### `doctest.ELLIPSIS`425426Когда указано, маркер многоточия (427428`...`429430) в ожидаемом выводе может соответствовать любой подстроке в фактическом выводе. Это включает подстроки, выходящие за границы строк, и пустые подстроки, поэтому лучше использовать эту возможность просто. Сложное использование может привести к тем же сюрпризам «ой, совпало слишком много!», к которым склонен431432`.*`433434в регулярных выражениях.435436#### `doctest.IGNORE_EXCEPTION_DETAIL`437438Если указано, пример, который ожидает исключение, проходит, если возбуждается исключение ожидаемого типа, даже если сообщение исключения не совпадает. Например, пример, ожидающий `ValueError: 42`, будет пройден, если фактически возбуждённое исключение – `ValueError: 3*14`, но не пройдёт, если, например, возбуждён [`TypeError`](https://python-all.ru/3.1/library/exceptions.html#TypeError).439440Обратите внимание, что аналогичного эффекта можно достичь, используя [`ELLIPSIS`](https://python-all.ru/3.1/library/doctest.html#doctest.ELLIPSIS), и [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/3.1/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL) может исчезнуть, когда выпуски Python до 2.4 станут неинтересны. А до тех пор [`IGNORE_EXCEPTION_DETAIL`](https://python-all.ru/3.1/library/doctest.html#doctest.IGNORE_EXCEPTION_DETAIL) – единственный чёткий способ написать doctest, которому безразличны подробности исключения, и который при этом продолжает проходить тестирование на выпусках Python до 2.4 (директивы doctest для них выглядят как комментарии). Например,441442```python443>>> (1, 2)[3] = 'moo' #doctest: +IGNORE_EXCEPTION_DETAIL444Traceback (most recent call last):445 File "<stdin>", line 1, in ?446TypeError: object doesn't support item assignment447```448449проходит на Python 2.4 и Python 2.3. Подробность изменилась в 2.4 – теперь говорится «does not» вместо «doesn’t».450451#### `doctest.SKIP`452453Если этот флаг указан, пример не выполняется вообще. Это может быть полезно в ситуациях,\\nкогда доктесты служат одновременно документацией и тестовыми примерами, и пример\\nдолжен быть включён для документации, но не должен проверяться. Например, вывод\\nпримера может быть случайным, или пример может зависеть от ресурсов,\\nнедоступных для тестового драйвера.454455Флаг SKIP также можно использовать для временного «закомментирования» примеров.456457#### `doctest.COMPARISON_FLAGS`458459Битовая маска, объединяющая все перечисленные выше флаги сравнения.460461Вторая группа опций управляет тем, как сообщается о неудачных тестах:462463#### `doctest.REPORT_UDIFF`464465Если указан, ошибки, включающие многострочные ожидаемый и фактический вывод, отображаются в виде unified diff.466467#### `doctest.REPORT_CDIFF`468469Если указан, ошибки, включающие многострочные ожидаемый и фактический вывод, отображаются в виде context diff.470471#### `doctest.REPORT_NDIFF`472473Если указано, различия вычисляются с помощью474475`difflib.Differ`476477, используя тот же алгоритм, что и популярная утилита478479`ndiff.py`480481. Это единственный метод, который отмечает различия как внутри строк, так и между строками. Например, если строка ожидаемого вывода содержит цифру482483`1`484485, а фактический вывод содержит букву486487`l`488489, вставляется строка с символом «^», отмечающим несовпадающие позиции столбцов.490491#### `doctest.REPORT_ONLY_FIRST_FAILURE`492493Если указано, отображается первый завершившийся с ошибкой пример в каждом doctest, но вывод для всех остальных примеров подавляется. Это предотвращает сообщение doctest о корректных примерах, которые стали неверными из-за предыдущих ошибок; однако это может также скрыть некорректные примеры, которые падают независимо от первой ошибки. Когда указано494495[`REPORT_ONLY_FIRST_FAILURE`](https://python-all.ru/3.1/library/doctest.html#doctest.REPORT_ONLY_FIRST_FAILURE)496497, остальные примеры по-прежнему выполняются и учитываются в общем числе сообщенных ошибок; подавляется только вывод.498499#### `doctest.REPORTING_FLAGS`500501Битовая маска, объединяющая все перечисленные выше флаги отчёта.502503«Директивы doctest» могут использоваться для изменения флагов опций для отдельных примеров. Директивы doctest представляют собой специальный комментарий Python, следующий за исходным кодом примера:504505```506507directive ::= "#" "doctest:" directive_options508directive_options ::= directive_option ("," directive_option)\*509directive_option ::= on_or_off directive_option_name510on_or_off ::= "+" \| "-"511directive_option_name ::= "DONT_ACCEPT_BLANKLINE" \| "NORMALIZE_WHITESPACE" \| ...512```513514Пробелы не допускаются между `+` или `-` и именем опции\\nдирективы. Имя опции директивы может быть любым из имён флагов опций,\\nописанных выше.515516Директивы доктестов примера изменяют поведение doctest только для этого\\nодного примера. Используйте `+` для включения указанного поведения или\\n`-` для его отключения.517518Например, этот тест проходит:519520```python521>>> print(list(range(20))) #doctest: +NORMALIZE_WHITESPACE522[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,52310, 11, 12, 13, 14, 15, 16, 17, 18, 19]524```525526Без директивы он бы не прошёл, и потому что в фактическом выводе нет\\nдвух пробелов перед элементами списка из одной цифры, и потому что фактический вывод\\nнаходится на одной строке. Этот тест тоже проходит и тоже требует директивы\\nдля этого:527528```python529>>> print(list(range(20))) # doctest: +ELLIPSIS530[0, 1, ..., 18, 19]531```532533Несколько директив можно использовать в одной физической строке, разделяя их запятыми:534535```python536>>> print(list(range(20))) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE537[0, 1, ..., 18, 19]538```539540Если для одного примера используется несколько директив-комментариев, то они объединяются:541542```python543>>> print(list(range(20))) # doctest: +ELLIPSIS544... # doctest: +NORMALIZE_WHITESPACE545[0, 1, ..., 18, 19]546```547548Как показано в предыдущем примере, можно добавлять строки `...` в пример, содержащие только директивы. Это может быть полезно, когда пример слишком длинный, чтобы директива удобно поместилась на той же строке:549550```python551>>> print(list(range(5)) + list(range(10, 20)) + list(range(30, 40)))552... # doctest: +ELLIPSIS553[0, ..., 4, 10, ..., 19, 30, ..., 39]554```555556Обратите внимание: поскольку все опции по умолчанию отключены, а директивы применяются только к тому примеру, в котором они находятся, включение опций (через `+` в директиве) обычно является единственным осмысленным выбором. Однако флаги опций также могут передаваться функциям, запускающим доктесты, устанавливая другие значения по умолчанию. В таких случаях отключение опции через `-` в директиве может быть полезным.557558Существует также способ зарегистрировать новые имена флагов опций, хотя это бессмысленно, если вы не собираетесь расширять внутренние механизмы `doctest` через создание подклассов:559560#### `doctest.register_optionflag(name)`561562Создает новый опциональный флаг с заданным именем и возвращает целочисленное значение нового флага. [`register_optionflag()`](https://python-all.ru/3.1/library/doctest.html#doctest.register_optionflag) можно использовать при создании подклассов [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker) или [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner) для создания новых опций, поддерживаемых своими подклассами. [`register_optionflag()`](https://python-all.ru/3.1/library/doctest.html#doctest.register_optionflag) всегда следует вызывать, используя следующую идиому:563564```python565MY_FLAG = register_optionflag('MY_FLAG')566```567568### 25.2.3.6. Предупреждения569570`doctest` серьёзно относится к требованию точного совпадения ожидаемого вывода. Если не совпадает хотя бы один символ, тест проваливается. Это, вероятно, удивит вас несколько раз, пока вы узнаете, что именно Python гарантирует и не гарантирует относительно вывода. Например, при печати словаря Python не гарантирует, что пары ключ-значение будут выведены в каком-то определённом порядке, поэтому тест вроде571572```python573>>> foo()574{"Hermione": "hippogryph", "Harry": "broomstick"}575```576577является уязвимым! Один из способов обойти это – сделать578579```python580>>> foo() == {"Hermione": "hippogryph", "Harry": "broomstick"}581True582```583584вместо этого. Другой способ – сделать585586```python587>>> d = sorted(foo().items())588>>> d589[('Harry', 'broomstick'), ('Hermione', 'hippogryph')]590```591592Есть и другие, но идея понятна.593594Ещё одна плохая идея – печатать то, что содержит адрес объекта, например595596```python597>>> id(1.0) # обязательно иногда будет ошибаться5987948648599>>> class C: pass600>>> C() # стандартный repr() для экземпляров содержит адрес601<__main__.C instance at 0x00AC18F0>602```603604Директива [`ELLIPSIS`](https://python-all.ru/3.1/library/doctest.html#doctest.ELLIPSIS) дает хороший подход для последнего примера:605606```python607>>> C() #doctest: +ELLIPSIS608<__main__.C instance at 0x...>609```610611Числа с плавающей запятой также подвержены небольшим различиям в выводе на разных платформах, поскольку Python полагается на системную библиотеку C для форматирования чисел с плавающей запятой, а качество библиотек C сильно различается.612613```python614>>> 1./7 # рискованно6150.14285714285714285616>>> print(1./7) # безопаснее6170.142857142857618>>> print(round(1./7, 6)) # гораздо безопаснее6190.142857620```621622Числа вида `I/2.**J` безопасны на всех платформах, и примеры для doctest часто намеренно составляются так, чтобы получались числа такой формы:623624```python625>>> 3./4 # абсолютно безопасно6260.75627```628629Простые дроби также легче понимаются людьми, что улучшает документацию.630631## 25.2.4. Базовый API632633Функции [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod) и [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) предоставляют простой интерфейс к doctest, которого должно быть достаточно для большинства базовых применений. Для менее формального введения в эти две функции см. разделы [*Простое использование: проверка примеров в docstrings*](https://python-all.ru/3.1/library/doctest.html#doctest-simple-testmod) и [*Простое использование: проверка примеров в текстовом файле*](https://python-all.ru/3.1/library/doctest.html#doctest-simple-testfile).634635#### `doctest.testfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, parser=DocTestParser(), encoding=None)`636637Все аргументы, кроме *filename*, являются необязательными и должны указываться в форме ключевых слов.638639Тестирует примеры в файле с именем *filename*. Возвращает `(failure_count, test_count)`.640641Необязательный аргумент *module\_relative* определяет, как следует интерпретировать имя файла:642643- Если *module\_relative* равен `True` (по умолчанию), то *filename* задает независимый от ОС путь, относительный модуля. По умолчанию этот путь относителен каталога вызывающего модуля; но если указан аргумент *package*, то путь относителен этого пакета. Для обеспечения независимости от ОС в *filename* следует использовать символ `/` для разделения сегментов пути, и он не может быть абсолютным путем (т.е. не должен начинаться с `/`).644- Если *module\_relative* равен `False`, то *filename* задает путь, зависящий от ОС. Путь может быть абсолютным или относительным; относительные пути разрешаются относительно текущего рабочего каталога.645646Необязательный аргумент *name* задает имя теста; по умолчанию или если `None`, используется `os.path.basename(filename)`.647648Необязательный аргумент *package* – это пакет Python или имя пакета Python, чей каталог должен использоваться как базовый каталог для имени файла, относительного модуля. Если пакет не указан, то в качестве базового каталога для имен файлов, относительных модуля, используется каталог вызывающего модуля. Указывать *package*, если *module\_relative* равно `False`, является ошибкой.649650Необязательный аргумент *globs* задает словарь, используемый в качестве глобальных переменных при выполнении примеров. Для doctest создается новая поверхностная копия этого словаря, так что примеры начинают с чистого листа. По умолчанию или если `None`, используется новый пустой словарь.651652Необязательный аргумент *extraglobs* задает словарь, объединяемый с глобальными переменными, используемыми для выполнения примеров. Это работает как [`dict.update()`](https://python-all.ru/3.1/library/stdtypes.html#dict.update): если *globs* и *extraglobs* имеют общий ключ, соответствующее значение из *extraglobs* появляется в объединенном словаре. По умолчанию или если `None`, дополнительные глобальные переменные не используются. Это расширенная возможность, позволяющая параметризацию doctest. Например, doctest может быть написан для базового класса с использованием обобщенного имени класса, а затем повторно использован для тестирования любого количества подклассов путем передачи словаря *extraglobs*, отображающего обобщенное имя на тестируемый подкласс.653654Необязательный аргумент *verbose* выводит много информации, если равен true, и только ошибки, если false; по умолчанию или если `None`, он равен true тогда и только тогда, когда `'-v'` присутствует в `sys.argv`.655656Необязательный аргумент *report*: если истина, выводит сводку в конце, иначе ничего не выводит. В подробном режиме сводка подробная, в противном случае – очень краткая (фактически пустая, если все тесты пройдены).657658Необязательный аргумент *optionflags* объединяет флаги опций через логическое ИЛИ. См. раздел [*Option Flags and Directives*](https://python-all.ru/3.1/library/doctest.html#doctest-options).659660Необязательный аргумент *raise\_on\_error* по умолчанию равен false. Если true, при первой ошибке или неожиданном исключении в примере выбрасывается исключение. Это позволяет выполнять посмертную отладку ошибок. Поведение по умолчанию – продолжать выполнение примеров.661662Необязательный аргумент *parser* задает [`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser) (или подкласс), который следует использовать для извлечения тестов из файлов. По умолчанию используется обычный парсер (т.е. `DocTestParser()`).663664Необязательный аргумент *encoding* задаёт кодировку, которая должна использоваться для преобразования файла в Unicode.665666#### `doctest.testmod(m=None, name=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False)`667668Все аргументы необязательны, и все, кроме *m*, должны передаваться как именованные.669670Тестирует примеры в docstrings функций и классов, доступных из модуля *m* (или модуля [`__main__`](https://python-all.ru/3.1/library/__main__.html#module-__main__), если *m* не указан или равен `None`), начиная с `m.__doc__`.671672Также тестирует примеры, доступные из словаря `m.__test__`, если он существует и не равен `None`. `m.__test__` отображает имена (строки) на функции, классы и строки; docstrings функций и классов проверяются на наличие примеров; строки проверяются напрямую, как если бы они были docstrings.673674Проверяются только строки документации, прикреплённые к объектам, принадлежащим модулю *m*.675676Возвращает `(failure_count, test_count)`.677678Необязательный аргумент *name* задает имя модуля; по умолчанию или если `None`, используется `m.__name__`.679680Необязательный аргумент *exclude\_empty* по умолчанию равен false. Если true, объекты, для которых не найдено ни одного doctest, исключаются из рассмотрения. Значение по умолчанию – это хак для обратной совместимости, чтобы код, все еще использующий `doctest.master.summarize()` вместе с [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod), продолжал получать вывод для объектов без тестов. Аргумент *exclude\_empty* конструктора более нового [`DocTestFinder`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFinder) по умолчанию равен true.681682Необязательные аргументы *extraglobs*, *verbose*, *report*, *optionflags*, *raise\_on\_error* и *globs* аналогичны таковым для функции [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) выше, за исключением того, что *globs* по умолчанию равен `m.__dict__`.683684Существует также функция для запуска doctest-ов, связанных с одним объектом. Эта функция предоставляется для обратной совместимости. Ее не планируется объявлять устаревшей, но она редко бывает полезной:685686#### `doctest.run_docstring_examples(f, globs, verbose=False, name="NoName", compileflags=None, optionflags=0)`687688Тестирует примеры, связанные с объектом *f*; например, *f* может быть модулем, функцией или объектом класса.689690Для контекста выполнения используется поверхностная копия словаря *globs*.691692Необязательный аргумент *name* используется в сообщениях об ошибках и по умолчанию равен `"NoName"`.693694Если необязательный аргумент *verbose* равен true, вывод создаётся, даже если нет ошибок. По умолчанию вывод создаётся только в случае ошибки в примере.695696Необязательный аргумент *compileflags* задаёт набор флагов, которые должен использовать компилятор Python при выполнении примеров. По умолчанию или если `None`, флаги выводятся на основе набора будущих возможностей, обнаруженных в *globs*.697698Необязательный аргумент *optionflags* работает так же, как для функции [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) выше.699700## 25.2.5. API unittest701702По мере роста коллекции модулей с doctest'ами возникает потребность систематически запускать все их doctest'ы. `doctest` предоставляет две функции, которые можно использовать для создания тестовых наборов [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest) из модулей и текстовых файлов, содержащих doctest'ы. Затем эти тестовые наборы можно запускать с помощью тестовых исполнителей [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest):703704```python705import unittest706import doctest707import my_module_with_doctests, and_another708709suite = unittest.TestSuite()710for mod in my_module_with_doctests, and_another:711 suite.addTest(doctest.DocTestSuite(mod))712runner = unittest.TextTestRunner()713runner.run(suite)714```715716Существует две основные функции для создания экземпляров [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite) на основе текстовых файлов и модулей с doctest:717718#### `doctest.DocFileSuite(*paths, module_relative=True, package=None, setUp=None, tearDown=None, globs=None, optionflags=0, parser=DocTestParser(), encoding=None)`719720Преобразует тесты doctest из одного или нескольких текстовых файлов в [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite).721722Возвращаемый [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite) должен выполняться фреймворком unittest и запускает интерактивные примеры в каждом файле. Если пример в каком-либо файле не срабатывает, то созданный тест модуля завершается неудачей, и возникает исключение `failureException` с указанием имени файла, содержащего тест, и (иногда приблизительным) номером строки.723724Передаётся один или несколько путей (в виде строк) к текстовым файлам для проверки.725726Параметры могут быть указаны в виде именованных аргументов:727728Необязательный аргумент *module\_relative* определяет, как должны интерпретироваться имена файлов в *paths*:729730- Если *module\_relative* равно `True` (по умолчанию), то каждое имя файла в *paths* задаёт независимый от ОС путь относительно модуля. По умолчанию этот путь относителен к каталогу вызывающего модуля; но если указан аргумент *package*, то он относителен к этому пакету. Чтобы гарантировать независимость от ОС, каждое имя файла должно использовать символы `/` для разделения сегментов пути и не должно быть абсолютным путём (т.е. не должно начинаться с `/`).731- Если *module\_relative* равно `False`, то каждое имя файла в *paths* задаёт путь, зависящий от ОС. Путь может быть абсолютным или относительным; относительные пути разрешаются относительно текущего рабочего каталога.732733Необязательный аргумент *package* – это пакет Python или имя пакета Python, каталог которого должен использоваться как базовый каталог для имён файлов, относительных модуля, в *paths*. Если пакет не указан, то в качестве базового каталога для имён файлов, относительных модуля, используется каталог вызывающего модуля. Указывать *package*, если *module\_relative* равно `False`, является ошибкой.734735Необязательный аргумент *setUp* задаёт функцию настройки для тестового набора. Она вызывается перед запуском тестов в каждом файле. Функции *setUp* будет передан объект [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest). Функция setUp может получить доступ к глобальным переменным теста через атрибут *globs* переданного теста.736737Необязательный аргумент *tearDown* задаёт функцию завершения для тестового набора. Она вызывается после запуска тестов в каждом файле. Функции *tearDown* будет передан объект [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest). Функция setUp может получить доступ к глобальным переменным теста через атрибут *globs* переданного теста.738739Необязательный аргумент *globs* – это словарь, содержащий начальные глобальные переменные для тестов. Для каждого теста создаётся новая копия этого словаря. По умолчанию *globs* – новый пустой словарь.740741Необязательный аргумент *optionflags* задаёт стандартные параметры doctest для тестов, формируемые объединением отдельных флагов опций через логическое ИЛИ. См. раздел [*Option Flags and Directives*](https://python-all.ru/3.1/library/doctest.html#doctest-options). Функция [`set_unittest_reportflags()`](https://python-all.ru/3.1/library/doctest.html#doctest.set_unittest_reportflags) ниже описывает более удобный способ задания параметров отчёта.742743Необязательный аргумент *parser* задаёт объект [`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser) (или подкласс), который следует использовать для извлечения тестов из файлов. По умолчанию используется обычный анализатор (т.е. `DocTestParser()`).744745Необязательный аргумент *encoding* задаёт кодировку, которая должна использоваться для преобразования файла в Unicode.746747Глобальная переменная `__file__` добавляется в область глобальных переменных, передаваемых doctest, загруженному из текстового файла с помощью [`DocFileSuite()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocFileSuite).748749#### `doctest.DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, setUp=None, tearDown=None, checker=None)`750751Преобразует тесты doctest для модуля в [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite).752753Возвращаемый [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite) должен выполняться фреймворком unittest и запускает каждый doctest в модуле. Если какой-либо из doctest завершится неудачей, то созданный модульный тест завершается неудачей, и возникает исключение `failureException` с указанием имени файла, содержащего тест, и (иногда приблизительным) номером строки.754755Необязательный аргумент *module* задаёт тестируемый модуль. Это может быть объект модуля или (возможно, с точками) имя модуля. Если он не указан, используется модуль, из которого вызывается эта функция.756757Необязательный аргумент *globs* – это словарь, содержащий начальные глобальные переменные для тестов. Для каждого теста создаётся новая копия этого словаря. По умолчанию *globs* – новый пустой словарь.758759Необязательный аргумент *extraglobs* задаёт дополнительный набор глобальных переменных, который объединяется с *globs*. По умолчанию дополнительные глобальные переменные не используются.760761Необязательный аргумент *test\_finder* – это объект [`DocTestFinder`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFinder) (или его полноценная замена), который извлекает doctest из модуля.762763Необязательные аргументы *setUp*, *tearDown* и *optionflags* аналогичны одноимённым аргументам функции [`DocFileSuite()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocFileSuite) выше.764765Эта функция использует тот же метод поиска, что и [`testmod()`](https://python-all.ru/3.1/library/doctest.html#doctest.testmod).766767Внутренне [`DocTestSuite()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestSuite) создаёт [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite) из экземпляров `doctest.DocTestCase`, а `DocTestCase` является подклассом [`unittest.TestCase`](https://python-all.ru/3.1/library/unittest.html#unittest.TestCase). `DocTestCase` не документирован здесь (это внутренняя деталь), но изучение его кода может ответить на вопросы о точных деталях интеграции с [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest).768769Аналогично, [`DocFileSuite()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocFileSuite) создаёт [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite) из экземпляров `doctest.DocFileCase`, а `DocFileCase` является подклассом `DocTestCase`.770771Таким образом, оба способа создания [`unittest.TestSuite`](https://python-all.ru/3.1/library/unittest.html#unittest.TestSuite) запускают экземпляры `DocTestCase`. Это важно по тонкой причине: при самостоятельном запуске функций `doctest` можно напрямую управлять используемыми опциями `doctest`, передавая флаги опций функциям `doctest`. Однако при написании фреймворка [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest) именно [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest) в конечном счёте управляет тем, когда и как выполняются тесты. Автор фреймворка обычно хочет управлять опциями отчёта `doctest` (возможно, заданными, например, через параметры командной строки), но нет способа передать опции через [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest) исполнителям тестов `doctest`.772773По этой причине `doctest` также поддерживает понятие флагов отчёта `doctest`, специфичных для поддержки [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest), с помощью этой функции:774775#### `doctest.set_unittest_reportflags(flags)`776777Устанавливает используемые флаги отчёта `doctest`.778779Аргумент *flags* объединяет флаги опций через логическое ИЛИ. См. раздел [*Option Flags and Directives*](https://python-all.ru/3.1/library/doctest.html#doctest-options). Можно использовать только «флаги отчёта».780781Это глобальная настройка модуля, которая влияет на все будущие doctest'ы, запускаемые модулем [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest): метод `runTest()` класса `DocTestCase` проверяет флаги опций, указанные для тестового случая при создании экземпляра `DocTestCase`. Если флаги отчёта не были указаны (что является типичным и ожидаемым случаем), флаги отчёта `doctest` для [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest) объединяются по ИЛИ с флагами опций, и дополненные таким образом флаги опций передаются экземпляру [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner), созданному для выполнения doctest'а. Если какие-либо флаги отчёта были указаны при создании экземпляра `DocTestCase`, флаги отчёта `doctest` для [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest) игнорируются.782783Функция возвращает значение флагов отчётности [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest), действовавших до её вызова.784785## 25.2.6. Расширенный API786787Базовый API – это простая обёртка, предназначенная для упрощения использования doctest. Он достаточно гибок и должен удовлетворять потребности большинства пользователей; однако, если требуется более детальный контроль над тестированием или расширение возможностей doctest, следует использовать расширенный API.788789Расширенный API строится вокруг двух классов-контейнеров, которые используются для хранения интерактивных примеров, извлечённых из тестовых сценариев doctest:790791- [`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example): одна инструкция [*statement*](https://python-all.ru/3.1/glossary.html#term-statement) на языке Python в паре с ожидаемым выводом.792- [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest): набор объектов [`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example), обычно извлекаемый из одной строки документации или текстового файла.793794Для поиска, разбора, выполнения и проверки примеров doctest определены дополнительные классы обработки:795796- [`DocTestFinder`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFinder): находит все строки документации в заданном модуле и использует [`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser) для создания [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) из каждой строки документации, содержащей интерактивные примеры.797- [`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser): создаёт объект [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) из строки (например, docstring объекта).798- [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner): выполняет примеры в [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) и использует [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker) для проверки их вывода.799- [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker): сравнивает фактический вывод из примера doctest с ожидаемым выводом и определяет, совпадают ли они.800801Взаимосвязи между этими классами обработки показаны на следующей диаграмме.802803```python804 list of:805+------+ +---------+806|module| --DocTestFinder-> | DocTest | --DocTestRunner-> results807+------+ | ^ +---------+ | ^ (printed)808 | | | Example | | |809 v | | ... | v |810 DocTestParser | Example | OutputChecker811 +---------+812```813814### 25.2.6.1. Объекты DocTest815816#### `class doctest.DocTest(examples, globs, name, filename, lineno, docstring)`817818Коллекция примеров doctest, которые должны выполняться в едином пространстве имён. Аргументы конструктора используются для инициализации одноимённых переменных-членов.819820[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) определяет следующие переменные-члены. Они инициализируются конструктором и не должны изменяться напрямую.821822#### `examples`823824Список объектов825826[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example)827828, описывающих отдельные интерактивные примеры на Python, которые должны быть выполнены этим тестом.829830#### `globs`831832Пространство имён (глобальные переменные), в котором должны выполняться примеры. Это словарь, отображающий имена в значения. Все изменения пространства имён, сделанные примерами (например, привязка новых переменных), будут отражены в833834[`globs`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest.globs)835836после выполнения теста.837838#### `name`839840Строковое имя, идентифицирующее841842[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)843844. Обычно это имя объекта или файла, из которого был извлечён тест.845846#### `filename`847848Имя файла, из которого был извлечён этот849850[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)851852; или853854`None`855856, если имя файла неизвестно или если857858[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)859860не был извлечён из файла.861862#### `lineno`863864Номер строки в865866[`filename`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest.filename)867868, с которой начинается этот869870[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)871872; или873874`None`875876, если номер строки недоступен. Номер строки отсчитывается от нуля относительно начала файла.877878#### `docstring`879880Строка, из которой был извлечён тест, или «None», если строка недоступна, или если тест не был извлечён из строки.881882### 25.2.6.2. Объекты Example883884#### `class doctest.Example(source, want, exc_msg=None, lineno=0, indent=0, options=None)`885886Один интерактивный пример, состоящий из оператора Python и ожидаемого вывода. Аргументы конструктора используются для инициализации одноимённых переменных-членов.887888[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example) определяет следующие переменные-члены. Они инициализируются конструктором и не должны изменяться напрямую.889890#### `source`891892Строка, содержащая исходный код примера. Этот исходный код состоит из одного оператора Python и всегда заканчивается символом новой строки; конструктор добавляет символ новой строки при необходимости.893894#### `want`895896Ожидаемый вывод после выполнения исходного кода примера (либо из stdout, либо трассировка в случае исключения).897898[`want`](https://python-all.ru/3.1/library/doctest.html#doctest.Example.want)899900завершается символом новой строки, если не ожидается, что вывод отсутствует; в этом случае он представляет собой пустую строку. Конструктор добавляет символ новой строки при необходимости.901902#### `exc_msg`903904Сообщение об исключении, сгенерированное примером, если ожидается, что пример вызовет исключение; или905906`None`907908, если исключение не ожидается. Это сообщение об исключении сравнивается с возвращаемым значением909910[`traceback.format_exception_only()`](https://python-all.ru/3.1/library/traceback.html#traceback.format_exception_only)911912.913914[`exc_msg`](https://python-all.ru/3.1/library/doctest.html#doctest.Example.exc_msg)915916завершается символом новой строки, если только не равно917918`None`919920. Конструктор добавляет символ новой строки при необходимости.921922#### `lineno`923924Номер строки внутри строки, содержащей этот пример, с которой начинается пример. Этот номер строки отсчитывается от нуля относительно начала содержащей строки.925926#### `indent`927928Отступ примера в содержащей строке, т.е. количество пробелов перед первым приглашением примера.929930#### `options`931932Словарь, сопоставляющий флаги опций со значениями933934`True`935936или937938`False`939940, используется для переопределения стандартных опций для этого примера. Любые флаги опций, не вошедшие в этот словарь, сохраняют своё значение по умолчанию (как указано в941942[`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner)943944‘s945946`optionflags`947948). По умолчанию опции не заданы.949950### 25.2.6.3. Объекты DocTestFinder951952#### `class doctest.DocTestFinder(verbose=False, parser=DocTestParser(), recurse=True, exclude_empty=True)`953954Обрабатывающий класс, используемый для извлечения объектов [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest), относящихся к заданному объекту, из его строки документации и строк документации вложенных в него объектов. [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) могут быть извлечены из объектов следующих типов: модули, функции, классы, методы, статические методы, методы класса и свойства.955956Необязательный аргумент *verbose* можно использовать для вывода объектов, которые ищет поисковик. По умолчанию `False` (вывод отсутствует).957958Необязательный аргумент *parser* задаёт объект [`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser) (или его полноценную замену), который используется для извлечения доктестов из строк документации.959960Если необязательный аргумент *recurse* равен false, то [`DocTestFinder.find()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFinder.find) будет проверять только переданный объект, но не содержащиеся в нём объекты.961962Если необязательный аргумент *exclude\_empty* равен false, то [`DocTestFinder.find()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFinder.find) включит тесты для объектов с пустыми строками документации.963964[`DocTestFinder`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFinder) определяет следующий метод:965966#### `find(obj[, name][, module][, globs][, extraglobs])`967968Возвращает список объектов [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest), определённых строкой документации *obj* или строками документации любых содержащихся в нём объектов.969970Необязательный аргумент *name* задаёт имя объекта; это имя будет использоваться для формирования имён возвращаемых [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest). Если *name* не указан, то используется `obj.__name__`.971972Необязательный параметр *module* – это модуль, содержащий переданный объект. Если модуль не указан или равен None, то поисковик тестов попытается автоматически определить правильный модуль. Модуль объекта используется:973974- В качестве пространства имён по умолчанию, если *globs* не указан.975- Чтобы предотвратить извлечение DocTests объектом DocTestFinder из объектов, импортированных из других модулей. (Содержащиеся объекты, чей модуль отличается от *module*, игнорируются.)976- Для поиска имени файла, содержащего объект.977- Для помощи в определении номера строки объекта в его файле.978979Если *module* равен `False`, никаких попыток найти модуль не будет. Это неочевидное поведение, в основном используемое при тестировании самого doctest: если *module* равен `False` или `None`, но не может быть найден автоматически, то считается, что все объекты принадлежат (несуществующему) модулю, и поэтому все содержащиеся объекты будут (рекурсивно) проверены на наличие доктестов.980981Глобальные переменные для каждого [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) формируются путём объединения *globs* и *extraglobs* (привязки в *extraglobs* переопределяют привязки в *globs*). Для каждого [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest) создаётся новая поверхностная копия словаря глобальных переменных. Если *globs* не указан, то по умолчанию используется *\_\_dict\_\_* модуля, если он указан, или `{}` в противном случае. Если *extraglobs* не указан, то по умолчанию `{}`.982983### 25.2.6.4. Объекты DocTestParser984985#### `class doctest.DocTestParser`986987Класс обработки, используемый для извлечения интерактивных примеров из строки и создания на их основе объекта [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest).988989[`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser) определяет следующие методы:990991#### `get_doctest(string, globs, name, filename, lineno)`992993Извлекает все примеры доктестов из заданной строки и собирает их в объект [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest).994995*globs*, *name*, *filename* и *lineno* являются атрибутами нового объекта [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest). Дополнительные сведения см. в документации [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest).996997#### `get_examples(string, name='<string>')`998999Извлекает все примеры доктестов из заданной строки и возвращает их в виде списка объектов10001001[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example)10021003. Номера строк начинаются с 0. Необязательный аргумент10041005*name*10061007– это имя, идентифицирующее данную строку; используется только для сообщений об ошибках.10081009#### `parse(string, name='<string>')`10101011Разделяет заданную строку на примеры и промежуточный текст и возвращает их в виде списка, чередующего объекты10121013[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example)10141015и строки. Номера строк для10161017[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example)10181019начинаются с 0. Необязательный аргумент10201021*name*10221023– это имя, идентифицирующее данную строку; используется только для сообщений об ошибках.10241025### 25.2.6.5. Объекты DocTestRunner10261027#### `class doctest.DocTestRunner(checker=None, verbose=None, optionflags=0)`10281029Класс обработки, используемый для выполнения и проверки интерактивных примеров в [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest).10301031Сравнение ожидаемого и фактического вывода выполняется с помощью [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker). Это сравнение можно настроить с помощью ряда флагов опций; подробнее см. раздел [*Option Flags and Directives*](https://python-all.ru/3.1/library/doctest.html#doctest-options). Если флагов опций недостаточно, то сравнение можно также настроить, передав конструктору подкласс [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker).10321033Вывод тестового исполнителя можно управлять двумя способами. Во-первых, можно передать функцию вывода в `TestRunner.run()`; эта функция будет вызываться со строками, которые нужно отобразить. По умолчанию используется `sys.stdout.write`. Если захвата вывода недостаточно, то вывод также можно настроить, создав подкласс DocTestRunner и переопределив методы [`report_start()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.report_start), [`report_success()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.report_success), [`report_unexpected_exception()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.report_unexpected_exception) и [`report_failure()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.report_failure).10341035Необязательный именованный аргумент *checker* задаёт объект [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker) (или его замену), который должен использоваться для сравнения ожидаемых результатов с фактическими результатами примеров doctest.10361037Необязательный именованный аргумент *verbose* управляет многословностью [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner). Если *verbose* равен `True`, то информация выводится о каждом примере по мере его выполнения. Если *verbose* равен `False`, то выводятся только неудачи. Если *verbose* не указан или равен `None`, то многословный вывод используется только тогда, когда используется флаг командной строки `-v`.10381039Необязательный именованный аргумент *optionflags* можно использовать для управления тем, как тестовый запускатор сравнивает ожидаемый вывод с фактическим и как отображает ошибки. Дополнительные сведения см. в разделе [*Option Flags and Directives*](https://python-all.ru/3.1/library/doctest.html#doctest-options).10401041[`DocTestParser`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestParser) определяет следующие методы:10421043#### `report_start(out, test, example)`10441045Сообщает, что исполнитель тестов собирается обработать данный пример. Этот метод предоставляется, чтобы подклассы [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner) могли настроить свой вывод; не следует вызывать его напрямую.10461047*example* – это пример, который будет обработан. *test* – это тест, *содержащий пример*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.run).10481049#### `report_success(out, test, example, got)`10501051Сообщает, что данный пример выполнился успешно. Этот метод предоставляется, чтобы подклассы [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner) могли настроить свой вывод; не следует вызывать его напрямую.10521053*example* – это пример, который будет обработан. *got* – это фактический вывод из примера. *test* – это тест, содержащий *example*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.run).10541055#### `report_failure(out, test, example, got)`10561057Сообщает, что данный пример завершился неудачей. Этот метод предоставляется, чтобы подклассы [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner) могли настроить свой вывод; не следует вызывать его напрямую.10581059*example* – это пример, который будет обработан. *got* – это фактический вывод из примера. *test* – это тест, содержащий *example*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.run).10601061#### `report_unexpected_exception(out, test, example, exc_info)`10621063Сообщает, что данный пример вызвал неожиданное исключение. Этот метод предоставляется, чтобы подклассы [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner) могли настроить свой вывод; не следует вызывать его напрямую.10641065*example* – это пример, который будет обработан. *exc\_info* – это кортеж, содержащий информацию о неожиданном исключении (как возвращается [`sys.exc_info()`](https://python-all.ru/3.1/library/sys.html#sys.exc_info)). *test* – это тест, содержащий *example*. *out* – это функция вывода, переданная в [`DocTestRunner.run()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner.run).10661067#### `run(test, compileflags=None, out=None, clear_globs=True)`10681069Запускает примеры из *test* (объект [`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)) и отображает результаты с помощью функции записи *out*.10701071Примеры выполняются в пространстве имён `test.globs`. Если *clear\_globs* равно истине (по умолчанию), то это пространство имён будет очищено после выполнения теста, чтобы помочь сборке мусора. Если требуется изучить пространство имён после завершения теста, используйте *clear\_globs=False*.10721073*compileflags* задаёт набор флагов, которые должен использовать компилятор Python при выполнении примеров. Если не указан, по умолчанию используется набор флагов future-import, действующих для *globs*.10741075Вывод каждого примера проверяется с помощью средства проверки вывода [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner), а результаты форматируются методами `DocTestRunner.report_*()`.10761077#### `summarize(verbose=None)`10781079Выводит сводку всех тестовых случаев, выполненных данным DocTestRunner, и возвращает [*именованный кортеж*](https://python-all.ru/3.1/glossary.html#term-named-tuple) `TestResults(failed, attempted)`.10801081Необязательный аргумент *verbose* управляет детализацией сводки. Если многословность не указана, используется многословность [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner).10821083### 25.2.6.6. Объекты OutputChecker10841085#### `class doctest.OutputChecker`10861087Класс, используемый для проверки, соответствует ли фактический вывод из примера doctest ожидаемому выводу. [`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker) определяет два метода: [`check_output()`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker.check_output), который сравнивает заданную пару выводов и возвращает истину, если они совпадают; и [`output_difference()`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker.output_difference), который возвращает строку, описывающую различия между двумя выводами.10881089[`OutputChecker`](https://python-all.ru/3.1/library/doctest.html#doctest.OutputChecker) определяет следующие методы:10901091#### `check_output(want, got, optionflags)`10921093Возвращает10941095`True`10961097, если фактический вывод примера (10981099*got*11001101) совпадает с ожидаемым выводом (11021103*want*11041105). Эти строки всегда считаются совпадающими, если они идентичны; но в зависимости от того, какие флаги опций использует тестовый запускатор, возможны также несколько типов нестрогого совпадения. Подробнее о флагах опций см. в разделе11061107[*Option Flags and Directives*](https://python-all.ru/3.1/library/doctest.html#doctest-options)11081109.11101111#### `output_difference(example, got, optionflags)`11121113Возвращает строку с описанием различий между ожидаемым выводом для заданного примера (11141115*example*11161117) и фактическим выводом (11181119*got*11201121).11221123*optionflags*11241125– это набор флагов опций, используемых для сравнения11261127*want*11281129и11301131*got*11321133.11341135## 25.2.7. Отладка11361137Doctest предоставляет несколько механизмов для отладки примеров doctest:11381139- Several functions convert doctests to executable Python programs, which can be run under the Python debugger, [`pdb`](https://python-all.ru/3.1/library/pdb.html#module-pdb).1140- Класс [`DebugRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DebugRunner) является подклассом [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner), который вызывает исключение при первом же несоответствии примера, содержащее информацию об этом примере. Эти сведения можно использовать для посмертной отладки примера.1141- Тестовые случаи [`unittest`](https://python-all.ru/3.1/library/unittest.html#module-unittest), созданные функцией [`DocTestSuite()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestSuite), поддерживают метод [`debug()`](https://python-all.ru/3.1/library/doctest.html#doctest.debug), определённый в [`unittest.TestCase`](https://python-all.ru/3.1/library/unittest.html#unittest.TestCase).1142- Можно добавить вызов [`pdb.set_trace()`](https://python-all.ru/3.1/library/pdb.html#pdb.set_trace) в примере doctest; при выполнении этой строки произойдёт вход в отладчик Python. После этого можно просматривать текущие значения переменных и т.д. Например, пусть `a.py` содержит только следующую строку документации модуля:11431144 ```python1145 """1146 >>> def f(x):1147 ... g(x*2)1148 >>> def g(x):1149 ... print(x+3)1150 ... import pdb; pdb.set_trace()1151 >>> f(3)1152 91153 """1154 ```11551156 Тогда интерактивный сеанс Python может выглядеть так:11571158 ```python1159 >>> import a, doctest1160 >>> doctest.testmod(a)1161 --Return--1162 > <doctest a[1]>(3)g()->None1163 -> import pdb; pdb.set_trace()1164 (Pdb) list1165 1 def g(x):1166 2 print(x+3)1167 3 -> import pdb; pdb.set_trace()1168 [EOF]1169 (Pdb) p x1170 61171 (Pdb) step1172 --Return--1173 > <doctest a[0]>(2)f()->None1174 -> g(x*2)1175 (Pdb) list1176 1 def f(x):1177 2 -> g(x*2)1178 [EOF]1179 (Pdb) p x1180 31181 (Pdb) step1182 --Return--1183 > <doctest a[2]>(1)?()->None1184 -> f(3)1185 (Pdb) cont1186 (0, 3)1187 >>>1188 ```11891190Функции, которые преобразуют doctest в код Python и, возможно, запускают полученный код под отладчиком:11911192#### `doctest.script_from_examples(s)`11931194Преобразует текст с примерами в скрипт.11951196Аргумент *s* – это строка, содержащая примеры doctest. Строка преобразуется в скрипт Python, где примеры doctest из *s* преобразуются в обычный код, а всё остальное – в комментарии Python. Сгенерированный скрипт возвращается в виде строки. Например,11971198```python1199import doctest1200print(doctest.script_from_examples(r"""1201 Set x and y to 1 and 2.1202 >>> x, y = 1, 212031204 Print their sum:1205 >>> print(x+y)1206 31207"""))1208```12091210выводит:12111212```python1213# Установите x и y в 1 и 2.1214x, y = 1, 21215#1216# Выведите их сумму:1217print(x+y)1218# Ожидаемый результат:1219## 31220```12211222Эта функция используется внутренне другими функциями (см. ниже), но также может быть полезна, когда требуется преобразовать интерактивный сеанс Python в скрипт Python.12231224#### `doctest.testsource(module, name)`12251226Преобразует доктест объекта в скрипт.12271228Аргумент *module* – это объект модуля или точечное имя модуля, содержащего объект, doctest-ы которого представляют интерес. Аргумент *name* – это имя (внутри модуля) объекта с интересующими doctest-ами. Результат – строка, содержащая docstring этого объекта, преобразованный в скрипт Python, как описано выше для [`script_from_examples()`](https://python-all.ru/3.1/library/doctest.html#doctest.script_from_examples). Например, если модуль `a.py` содержит функцию верхнего уровня `f()`, то12291230```python1231import a, doctest1232print(doctest.testsource(a, "a.f"))1233```12341235выводит скриптовую версию docstring функции `f()`, где doctest-ы преобразованы в код, а остальное помещено в комментарии.12361237#### `doctest.debug(module, name, pm=False)`12381239Отладка доктестов для объекта.12401241Аргументы *module* и *name* те же, что и для функции [`testsource()`](https://python-all.ru/3.1/library/doctest.html#doctest.testsource) выше. Синтезированный скрипт Python для docstring указанного объекта записывается во временный файл, а затем этот файл запускается под управлением отладчика Python, [`pdb`](https://python-all.ru/3.1/library/pdb.html#module-pdb).12421243Поверхностная копия `module.__dict__` используется как для локального, так и для глобального контекста выполнения.12441245Необязательный аргумент *pm* определяет, используется ли посмертная отладка. Если *pm* имеет истинное значение, скрипт выполняется напрямую, и отладчик подключается только в том случае, если скрипт завершается из-за необработанного исключения. Если это происходит, вызывается посмертная отладка через [`pdb.post_mortem()`](https://python-all.ru/3.1/library/pdb.html#pdb.post_mortem) с передачей объекта traceback из необработанного исключения. Если *pm* не указан или равен false, скрипт выполняется под отладчиком с самого начала, путём передачи соответствующего вызова [`exec()`](https://python-all.ru/3.1/library/functions.html#exec) в [`pdb.run()`](https://python-all.ru/3.1/library/pdb.html#pdb.run).12461247#### `doctest.debug_src(src, pm=False, globs=None)`12481249Отладка доктестов в строке.12501251Эта функция аналогична [`debug()`](https://python-all.ru/3.1/library/doctest.html#doctest.debug) выше, за исключением того, что строка с примерами doctest задаётся напрямую через аргумент *src*.12521253Необязательный аргумент *pm* имеет тот же смысл, что и в функции [`debug()`](https://python-all.ru/3.1/library/doctest.html#doctest.debug) выше.12541255Необязательный аргумент *globs* задаёт словарь, используемый как в качестве локального, так и глобального контекста выполнения. Если он не указан или равен `None`, используется пустой словарь. Если указан, используется поверхностная копия словаря.12561257Класс [`DebugRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DebugRunner) и специальные исключения, которые он может вызывать, представляют наибольший интерес для разработчиков тестовых фреймворков, и здесь будут лишь кратко описаны. Подробнее см. в исходном коде, особенно в docstring класса [`DebugRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DebugRunner) (который сам является doctest!).12581259#### `class doctest.DebugRunner(checker=None, verbose=None, optionflags=0)`12601261Подкласс [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner), который вызывает исключение сразу при обнаружении несоответствия. Если происходит неожиданное исключение, вызывается исключение [`UnexpectedException`](https://python-all.ru/3.1/library/doctest.html#doctest.UnexpectedException), содержащее тест, пример и исходное исключение. Если вывод не совпадает, вызывается исключение [`DocTestFailure`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFailure), содержащее тест, пример и фактический вывод.12621263Информацию о параметрах конструктора и методах см. в документации [`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner) в разделе [*Advanced API*](https://python-all.ru/3.1/library/doctest.html#doctest-advanced-api).12641265Существует два исключения, которые могут вызываться экземплярами [`DebugRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DebugRunner):12661267#### `exception doctest.DocTestFailure(test, example, got)`12681269Исключение, вызываемое12701271[`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner)12721273, когда фактический вывод примера doctest не совпадает с ожидаемым. Аргументы конструктора инициализируют одноимённые атрибуты.12741275[`DocTestFailure`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestFailure) определяет следующие атрибуты:12761277#### `DocTestFailure.test`12781279Объект12801281[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)12821283, который выполнялся во время сбоя примера.12841285#### `DocTestFailure.example`12861287Объект12881289[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example)12901291, в котором произошла ошибка.12921293#### `DocTestFailure.got`12941295Фактический вывод примера.12961297#### `exception doctest.UnexpectedException(test, example, exc_info)`12981299Исключение, вызываемое13001301[`DocTestRunner`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTestRunner)13021303, когда пример doctest порождает неожиданное исключение. Аргументы конструктора инициализируют одноимённые атрибуты.13041305[`UnexpectedException`](https://python-all.ru/3.1/library/doctest.html#doctest.UnexpectedException) определяет следующие атрибуты:13061307#### `UnexpectedException.test`13081309Объект13101311[`DocTest`](https://python-all.ru/3.1/library/doctest.html#doctest.DocTest)13121313, который выполнялся во время сбоя примера.13141315#### `UnexpectedException.example`13161317Объект13181319[`Example`](https://python-all.ru/3.1/library/doctest.html#doctest.Example)13201321, в котором произошла ошибка.13221323#### `UnexpectedException.exc_info`13241325Кортеж с информацией о непредвиденном исключении, возвращаемый13261327[`sys.exc_info()`](https://python-all.ru/3.1/library/sys.html#sys.exc_info)13281329.13301331## 25.2.8. Трибуна13321333Как упоминалось во введении, `doctest` со временем приобрёл три основных применения:133413351. Проверка примеров в docstrings.13362. Регрессионное тестирование.13373. Исполняемая документация / литературное тестирование.13381339Эти варианты использования предъявляют разные требования, и важно их различать. В частности, наполнение строк документации запутанными тестовыми примерами приводит к плохой документации.13401341При написании docstring выбирайте примеры с осторожностью. В этом есть свой навык, который нужно освоить – сначала это может быть неестественно. Примеры должны приносить реальную пользу документации. Хороший пример часто может заменить много слов. Если подойти к делу с умом, примеры станут бесценны для ваших пользователей и многократно окупят время, затраченное на их сбор, по мере того как годы идут и всё меняется. Я до сих пор удивляюсь, как часто один из моих примеров в `doctest` перестаёт работать после «безобидного» изменения.13421343Doctest также отлично подходит для регрессионного тестирования, особенно если не жалеть пояснительного текста. Чередуя прозу и примеры, гораздо легче отслеживать, что именно тестируется и почему. Когда тест падает, хороший текст помогает быстрее понять, в чём проблема и как её исправить. Конечно, можно писать развёрнутые комментарии в коде тестов, но мало кто это делает. Многие заметили, что использование doctest вместо этого приводит к гораздо более понятным тестам. Возможно, просто потому, что в doctest писать прозу немного легче, чем код, а писать комментарии в коде – немного сложнее. Но я думаю, дело не только в этом: естественный подход при написании теста на основе doctest – это желание объяснить тонкости своего программного обеспечения и проиллюстрировать их примерами. Это, в свою очередь, естественным образом приводит к тестовым файлам, которые начинаются с самых простых функций и логически переходят к осложнениям и крайним случаям. В результате получается связное повествование, а не набор разрозненных функций, тестирующих отдельные фрагменты функциональности, казалось бы, случайным образом. Это другой подход, и он даёт другие результаты, стирая грань между тестированием и объяснением.13441345Регрессионное тестирование лучше всего проводить в отдельных объектах или файлах. Есть несколько вариантов организации тестов:13461347- Создавайте текстовые файлы, содержащие тестовые примеры в виде интерактивных примеров, и проверяйте эти файлы с помощью [`testfile()`](https://python-all.ru/3.1/library/doctest.html#doctest.testfile) или [`DocFileSuite()`](https://python-all.ru/3.1/library/doctest.html#doctest.DocFileSuite). Этот подход рекомендуется, хотя его проще всего применять в новых проектах, изначально спроектированных для работы с doctest.1348- Определяйте функции с именами вида `_regrtest_topic`, состоящие из одной строки документации, содержащей тестовые примеры для указанных тем. Такие функции можно включить в тот же файл, что и модуль, или вынести в отдельный тестовый файл.1349- Определите словарь `__test__`, отображающий темы регрессионного тестирования в строки документации, содержащие тестовые примеры.13501351Сноски13521353| [\[1\]](https://python-all.ru/3.1/library/doctest.html#id1) | Примеры, содержащие как ожидаемый вывод, так и исключение, не поддерживаются. Попытка угадать, где заканчивается одно и начинается другое, слишком чревата ошибками и приводит к запутанным тестам. |1354| --- | --- |1355