# `doctest` — Test interactive Python examples

Вихідний код: Lib/doctest.py

Модуль `doctest` шукає фрагменти тексту, які виглядають як інтерактивні сеанси Python, а потім виконує ці сеанси, щоб перевірити, чи вони працюють саме так, як показано. Існує кілька поширених способів використання doctest:

- Щоб перевірити актуальність рядків документів модуля, переконавшись, що всі інтерактивні приклади все ще працюють, як задокументовано.

- Щоб виконати регресійне тестування, перевіривши, що інтерактивні приклади з тестового файлу або тестового об’єкта працюють належним чином.

- Написати навчальну документацію для пакета, щедро проілюстровану прикладами введення-виведення. Залежно від того, чи наголошується на прикладах чи пояснювальному тексті, це має відтінок «грамотного тестування» або «виконуваної документації».

Ось повний, але невеликий приклад модуля:

    """
    This is the "example" module.

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

    >>> factorial(5)
    120
    """

    def factorial(n):
        """Return the factorial of n, an exact integer >= 0.

        >>> [factorial(n) for n in range(6)]
        [1, 1, 2, 6, 24, 120]
        >>> factorial(30)
        265252859812191058636308480000000
        >>> factorial(-1)
        Traceback (most recent call last):
            ...
        ValueError: n must be >= 0

        Factorials of floats are OK, but the float must be an exact integer:
        >>> factorial(30.1)
        Traceback (most recent call last):
            ...
        ValueError: n must be exact integer
        >>> factorial(30.0)
        265252859812191058636308480000000

        It must also not be ridiculously large:
        >>> factorial(1e100)
        Traceback (most recent call last):
            ...
        OverflowError: n too large
        """

        import math
        if not n >= 0:
            raise ValueError("n must be >= 0")
        if math.floor(n) != n:
            raise ValueError("n must be exact integer")
        if n+1 == n:  # catch a value like 1e300
            raise OverflowError("n too large")
        result = 1
        factor = 2
        while factor <= n:
            result *= factor
            factor += 1
        return result

    if __name__ == "__main__":
        import doctest
        doctest.testmod()

Якщо ви запустите `example.py` безпосередньо з командного рядка, `doctest` спрацює так:

    $ python example.py
    $

Немає виходу! Це нормально, і це означає, що всі приклади спрацювали. Передайте сценарію `-v`, і `doctest` надрукує докладний журнал того, що він намагається, і наприкінці виведе підсумок:

    $ python example.py -v
    Trying:
        factorial(5)
    Expecting:
        120
    ok
    Trying:
        [factorial(n) for n in range(6)]
    Expecting:
        [1, 1, 2, 6, 24, 120]
    ok

І так далі, зрештою закінчуючи:

    Trying:
        factorial(1e100)
    Expecting:
        Traceback (most recent call last):
            ...
        OverflowError: n too large
    ok
    2 items passed all tests:
       1 tests in __main__
       8 tests in __main__.factorial
    9 tests in 2 items.
    9 passed and 0 failed.
    Test passed.
    $

That’s all you need to know to start making productive use of `doctest`! Jump in. The following sections provide full details. Note that there are many examples of doctests in the standard Python test suite and libraries. Especially useful examples can be found in the standard test file `Lib/test/test_doctest/test_doctest.py`.

## Просте використання: перевірка прикладів у Docstrings

The simplest way to start using doctest (but not necessarily the way you’ll continue to do it) is to end each module `M` with:

    if __name__ == "__main__":
        import doctest
        doctest.testmod()

`doctest` then examines docstrings in module `M`.

Запуск модуля як сценарію призводить до виконання та перевірки прикладів у рядках документів:

    python M.py

Це не відображатиме нічого, якщо приклад не буде невдалим, у цьому випадку невдалий(і) приклад(и) і причину(и) помилки(и) друкуються в stdout, а останній рядок виводу буде `***Test Помилка*** N невдач.`, де N — це кількість прикладів, що не вдалося виконати.

Натомість запустіть його з перемикачем `-v`:

    python M.py -v

і детальний звіт про всі спробовані приклади друкується на стандартному виводі разом із різноманітними підсумками в кінці.

Ви можете змусити докладний режим, передавши `verbose=True` до `testmod()`, або заборонити його, передавши `verbose=False`. У жодному з цих випадків `sys.argv` не перевіряється `testmod()` (тому передача `-v` чи ні не має ефекту).

There is also a command line shortcut for running `testmod()`. You can instruct the Python interpreter to run the doctest module directly from the standard library and pass the module name(s) on the command line:

    python -m doctest -v example.py

This will import `example.py` as a standalone module and run `testmod()` on it. Note that this may not work correctly if the file is part of a package and imports other submodules from that package.

Додаткову інформацію про `testmod()` див. у розділі Базовий API.

## Просте використання: перевірка прикладів у текстовому файлі

Іншим простим застосуванням doctest є тестування інтерактивних прикладів у текстовому файлі. Це можна зробити за допомогою функції `testfile()`:

    import doctest
    doctest.testfile("example.txt")

Цей короткий сценарій виконує та перевіряє будь-які інтерактивні приклади Python, що містяться у файлі `example.txt`. Вміст файлу обробляється так, ніби це один гігантський рядок документа; файл не повинен містити програму Python! Наприклад, можливо, `example.txt` містить таке:

    The ``example`` module
    ======================

    Using ``factorial``
    -------------------

    This is an example text file in reStructuredText format.  First import
    ``factorial`` from the ``example`` module:

        >>> from example import factorial

    Now use it:

        >>> factorial(6)
        120

Запуск `doctest.testfile("example.txt")` потім знаходить помилку в цій документації:

    File "./example.txt", line 14, in example.txt
    Failed example:
        factorial(6)
    Expected:
        120
    Got:
        720

Як і у випадку з `testmod()`, `testfile()` нічого не відображатиме, якщо приклад не вдасться. Якщо приклад не вдається, то невдалий(і) приклад(и) і причина(и) невдачі(ів) друкуються у stdout, використовуючи той самий формат, що й `testmod()`.

За замовчуванням `testfile()` шукає файли в каталозі викликаючого модуля. Перегляньте розділ Базовий API для опису необов’язкових аргументів, які можна використовувати, щоб наказати йому шукати файли в інших місцях.

Подібно до `testmod()`, докладність `testfile()` можна встановити за допомогою перемикача командного рядка `-v` або за допомогою додаткового аргументу ключового слова verbose.

There is also a command line shortcut for running `testfile()`. You can instruct the Python interpreter to run the doctest module directly from the standard library and pass the file name(s) on the command line:

    python -m doctest -v example.txt

Because the file name does not end with `.py`, `doctest` infers that it must be run with `testfile()`, not `testmod()`.

Для отримання додаткової інформації про `testfile()` див. розділ Базовий API.

## Як це працює

У цьому розділі детально розглядається, як працює doctest: які рядки документації він переглядає, як він знаходить інтерактивні приклади, який контекст виконання він використовує, як він обробляє винятки та як прапорці параметрів можна використовувати для керування його поведінкою. Це інформація, яку вам потрібно знати, щоб написати приклади doctest; для отримання інформації про фактичний запуск doctest на цих прикладах дивіться наступні розділи.

### Які рядки документів перевіряються?

Здійснюється пошук у рядку документів модуля та всіх рядках документів функцій, класів і методів. Об’єкти, імпортовані в модуль, не шукаються.

In addition, there are cases when you want tests to be part of a module but not part of the help text, which requires that the tests not be included in the docstring. Doctest looks for a module-level variable called `__test__` and uses it to locate other tests. If `M.__test__` exists, it must be a dict, and each entry maps a (string) name to a function object, class object, or string. Function and class object docstrings found from `M.__test__` are searched, and strings are treated as if they were docstrings. In output, a key `K` in `M.__test__` appears with name `M.__test__.K`.

For example, place this block of code at the top of `example.py`:

    __test__ = {
        'numbers': """
    >>> factorial(6)
    720

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    """
    }

The value of `example.__test__["numbers"]` will be treated as a docstring and all the tests inside it will be run. It is important to note that the value can be mapped to a function, class object, or module; if so, `doctest` searches them recursively for docstrings, which are then scanned for tests.

Будь-які знайдені класи рекурсивно шукаються подібним чином, щоб перевірити рядки документів у їх методах і вкладених класах.

### Як розпізнаються приклади Docstring?

У більшості випадків копіювання та вставлення сеансу інтерактивної консолі працює добре, але doctest не намагається зробити точну емуляцію будь-якої конкретної оболонки Python.

    >>> # comments are ignored
    >>> x = 12
    >>> x
    12
    >>> if x == 13:
    ...     print("yes")
    ... else:
    ...     print("no")
    ...     print("NO")
    ...     print("NO!!!")
    ...
    no
    NO
    NO!!!
    >>>

Будь-який очікуваний вихід має слідувати одразу за останнім `'>>> '` або `'... '` рядком, що містить код, і очікуваний вихід (якщо такий є) поширюється на наступний `'>>> "` або рядок із пробілами.

Дрібний шрифт:

- Очікуваний вихід не може містити рядок із пробілами, оскільки такий рядок використовується для сигналізації про кінець очікуваного виведення. Якщо очікуваний результат містить порожній рядок, додайте `<BLANKLINE>` у прикладі doctest у кожному місці, де очікується порожній рядок.

- Усі жорсткі символи табуляції розгорнуті на пробіли за допомогою позицій табуляції з 8 стовпців. Вкладки у вихідних даних, згенерованих тестованим кодом, не змінюються. Оскільки будь-які жорсткі вкладки у вихідних даних зразка розгорнуті, це означає, що якщо вивід коду містить жорсткі вкладки, єдиний спосіб проходження doctest — це параметр `NORMALIZE_WHITESPACE` або директива в ефекті. Крім того, тест можна переписати, щоб зафіксувати результат і порівняти його з очікуваним значенням як частину тесту. Таку обробку вкладок у вихідному коді було досягнуто шляхом проб і помилок, і це виявилося найменш схильним до помилок способом обробки. Можна використати інший алгоритм для обробки вкладок, написавши спеціальний клас `DocTestParser`.

- Вихідні дані в stdout фіксуються, але не виводяться в stderr (зворотні дані за винятками фіксуються іншим способом).

- Якщо ви продовжуєте рядок через зворотну косу риску в інтерактивному сеансі або з будь-якої іншої причини використовуєте зворотну косу риску, вам слід використовувати необроблений рядок документації, який збереже ваші зворотні косі риски точно так, як ви їх вводите:

      >>> def f(x):
      ...     r'''Backslashes in a raw docstring: m\n'''
      >>> print(f.__doc__)
      Backslashes in a raw docstring: m\n

  В іншому випадку зворотна коса риска буде інтерпретуватися як частина рядка. Наприклад, `\n` вище буде інтерпретовано як символ нового рядка. Крім того, ви можете подвоїти кожну зворотну косу риску у версії doctest (і не використовувати необроблений рядок):

      >>> def f(x):
      ...     '''Backslashes in a raw docstring: m\\n'''
      >>> print(f.__doc__)
      Backslashes in a raw docstring: m\n

- Початковий стовпець не має значення:

      >>> assert "Easy!"
            >>> import math
                >>> math.floor(1.9)
                1

  і стільки початкових пробільних символів видаляються з очікуваного результату, скільки було показано в початковому рядку `'>>> '`, який розпочав приклад.

### Що таке контекст виконання?

By default, each time `doctest` finds a docstring to test, it uses a shallow copy of `M`’s globals, so that running tests doesn’t change the module’s real globals, and so that one test in `M` can’t leave behind crumbs that accidentally allow another test to work. This means examples can freely use any names defined at top-level in `M`, and names defined earlier in the docstring being run. Examples cannot see names defined in other docstrings.

Ви можете примусово використовувати свій власний dict як контекст виконання, передавши натомість `globs=your_dict` у `testmod()` або `testfile()`.

### А як щодо винятків?

Немає проблем, за умови, що відстеження є єдиним результатом, створеним прикладом: просто вставте відстеження. [1] Оскільки відстеження містять деталі, які можуть швидко змінюватися (наприклад, точні шляхи до файлів і номери рядків), це один випадок, коли doctest докладає всіх зусиль, щоб бути гнучким у тому, що він приймає.

Простий приклад:

    >>> [1, 2, 3].remove(42)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: list.remove(x): x not in list

Цей doctest завершується успішно, якщо виникає `ValueError`, а `list.remove(x): x немає в деталях списку`, як показано.

Очікуваний вихід для винятку повинен починатися із заголовка трасування, який може бути будь-яким із наступних двох рядків із таким самим відступом, як і перший рядок прикладу:

    Traceback (most recent call last):
    Traceback (innermost last):

Після заголовка трасування слід додатковий стек зворотного трасування, вміст якого ігнорується doctest. Стек зворотного відстеження зазвичай пропускається або дослівно копіюється з інтерактивного сеансу.

За стеком відстеження слідує найцікавіша частина: рядки, що містять тип винятку та деталі. Зазвичай це останній рядок трасування, але він може охоплювати кілька рядків, якщо виняток містить багаторядкові деталі:

    >>> raise ValueError('multi\n    line\ndetail')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: multi
        line
    detail

Останні три рядки (починаючи з `ValueError`) порівнюються з типом і деталями винятку, а решта ігноруються.

Найкраща практика — опустити стек трасування, якщо це не додає прикладу значну цінність документації. Отже, останній приклад, ймовірно, кращий як:

    >>> raise ValueError('multi\n    line\ndetail')
    Traceback (most recent call last):
        ...
    ValueError: multi
        line
    detail

Зауважте, що трейсбеки обробляються дуже спеціально. Зокрема, у переписаному прикладі використання `...` не залежить від параметра `ELLIPSIS` doctest. Багатокрапка в цьому прикладі може бути пропущена, або з таким же успіхом може бути трьома (чи трьома сотнями) комами чи цифрами, або транскриптом сценки Монті Пайтона з відступом.

Деякі деталі, які ви повинні прочитати один раз, але не повинні запам’ятовувати:

- Doctest не може здогадатися, чи ваш очікуваний результат отримано від відстеження виняткової ситуації чи від звичайного друку. Так, наприклад, приклад, який очікує `ValueError: 42 є простим`, буде передано незалежно від того, чи `ValueError` справді викликано, чи приклад просто друкує цей текст трасування. На практиці звичайний вихід рідко починається з рядка заголовка трасування, тому це не створює реальних проблем.

- Кожен рядок стека зворотного відстеження (якщо він є) повинен мати відступ далі, ніж перший рядок прикладу, або починатися з небуквено-цифрового символу. Перший рядок після заголовка зворотного відстеження з однаковим відступом і починається з буквено-цифрового символу вважається початком деталей винятку. Звичайно, це правильно для справжнього відстеження.

- Коли вказано параметр doctest `IGNORE_EXCEPTION_DETAIL`, все, що йде після крайньої лівої двокрапки, і будь-яка інформація модуля в назві винятку ігнорується.

- Інтерактивна оболонка пропускає рядок заголовка трасування для деяких `SyntaxError`s. Але doctest використовує рядок заголовка трасування, щоб відрізнити винятки від невинятків. Тож у тих рідкісних випадках, коли вам потрібно перевірити `SyntaxError`, який пропускає заголовок трасування, вам потрібно буде вручну додати рядок заголовка трасування до вашого тестового прикладу.

- For some exceptions, Python displays the position of the error using `^` markers and tildes:

      >>> 1 + None
        File "<stdin>", line 1
          1 + None
          ~~^~~~~~
      TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

  Оскільки рядки, що показують положення помилки, стоять перед типом винятку та деталями, вони не перевіряються doctest. Наприклад, наступний тест буде пройдено, навіть якщо він розмістить маркер `^` у неправильному місці:

      >>> 1 + None
        File "<stdin>", line 1
          1 + None
          ^~~~~~~~
      TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

### Прапори параметрів

Кілька прапорців параметрів контролюють різні аспекти поведінки doctest. Символічні імена для прапорів надаються як константи модуля, які можна порозрядно об’єднати АБО разом і передати до різних функцій. Імена також можна використовувати в директивах doctest, і можуть бути передані в інтерфейс командного рядка doctest через опцію `-o`.

Нове в версії 3.4: The `-o` command line option.

Перша група параметрів визначає семантику тесту, контролюючи аспекти того, як doctest вирішує, чи фактичний результат відповідає очікуваному результату прикладу:

doctest.DONT_ACCEPT_TRUE_FOR_1

  За замовчуванням, якщо очікуваний вихідний блок містить лише `1`, фактичний вихідний блок, що містить лише `1` або лише `True`, вважається збігом, і аналогічно для `0` проти `False`. Якщо вказано `DONT_ACCEPT_TRUE_FOR_1`, жодна заміна не дозволяється. Поведінка за замовчуванням відповідає тому, що Python змінив тип повернення багатьох функцій з цілого на логічний; doctests, які очікують виводу «маленького цілого», все ще працюють у цих випадках. Цей варіант, ймовірно, зникне, але не через кілька років.

doctest.DONT_ACCEPT_BLANKLINE

  За замовчуванням, якщо очікуваний блок виводу містить рядок, що містить лише рядок `<BLANKLINE>`, тоді цей рядок відповідатиме порожньому рядку у фактичному виведенні. Оскільки справді порожній рядок розмежовує очікуваний вихід, це єдиний спосіб повідомити, що очікується порожній рядок. Якщо вказано `DONT_ACCEPT_BLANKLINE`, ця заміна не дозволяється.

doctest.NORMALIZE_WHITESPACE

  Якщо вказано, усі послідовності пробілів (пробілі та нові рядки) розглядаються як однакові. Будь-яка послідовність пробілів у очікуваному виводі відповідатиме будь-якій послідовності пробілів у фактичному виведенні. За замовчуванням пробіли мають точно збігатися. `NORMALIZE_WHITESPACE` особливо корисний, коли рядок очікуваного результату дуже довгий, і ви хочете обернути його між кількома рядками у своєму джерелі.

doctest.ELLIPSIS

  Якщо вказано, маркер еліпса (`...`) в очікуваному виведенні може збігатися з будь-яким підрядком у фактичному виведенні. Це включає в себе підрядки, які охоплюють межі рядка, і порожні підрядки, тому найкраще використовувати це просто. Складне використання може призвести до тих самих типів «ой, це збігається занадто багато!» сюрпризів, до яких схильний `.*` у регулярних виразах.

doctest.IGNORE_EXCEPTION_DETAIL

  When specified, doctests expecting exceptions pass so long as an exception of the expected type is raised, even if the details (message and fully qualified exception name) don’t match.

  For example, an example expecting `ValueError: 42` will pass if the actual exception raised is `ValueError: 3*14`, but will fail if, say, a `TypeError` is raised instead. It will also ignore any fully qualified name included before the exception class, which can vary between implementations and versions of Python and the code/libraries in use. Hence, all three of these variations will work with the flag specified:

      >>> raise Exception('message')
      Traceback (most recent call last):
      Exception: message

      >>> raise Exception('message')
      Traceback (most recent call last):
      builtins.Exception: message

      >>> raise Exception('message')
      Traceback (most recent call last):
      __main__.Exception: message

  Зауважте, що `ELLIPSIS` також можна використовувати для ігнорування деталей повідомлення про винятки, але такий тест все одно може завершитися невдачею залежно від того, чи присутнє ім’я модуля чи воно точно збігається.

  Змінено в версії 3.2: `IGNORE_EXCEPTION_DETAIL` тепер також ігнорує будь-яку інформацію, пов’язану з модулем, що містить виняток, що тестується.

doctest.SKIP

  Якщо вказано, не запускати приклад взагалі. Це може бути корисним у контекстах, де приклади doctest служать як документацією, так і тестовими випадками, і приклад слід включити з метою документації, але не слід перевіряти. Наприклад, результат прикладу може бути випадковим; або приклад може залежати від ресурсів, які були б недоступні для тестового драйвера.

  Прапор SKIP також можна використовувати для тимчасового «закоментування» прикладів.

doctest.COMPARISON_FLAGS

  Бітова маска або об’єднання всіх прапорів порівняння вище.

Друга група параметрів контролює, як повідомляється про помилки тесту:

doctest.REPORT_UDIFF

  Якщо вказано, помилки, які включають багаторядкові очікувані та фактичні виходи, відображаються за допомогою уніфікованої різниці.

doctest.REPORT_CDIFF

  Якщо вказано, помилки, які включають багаторядкові очікувані та фактичні результати, відображатимуться за допомогою контекстної різниці.

doctest.REPORT_NDIFF

  Якщо вказано, відмінності обчислюються за допомогою `difflib.Differ`, використовуючи той самий алгоритм, що й популярна утиліта `ndiff.py`. Це єдиний метод, який позначає відмінності всередині ліній, а також між лініями. Наприклад, якщо рядок очікуваного виводу містить цифру `1`, а фактичний вивід містить літеру `l`, рядок вставляється з кареткою, що позначає невідповідні позиції стовпців.

doctest.REPORT_ONLY_FIRST_FAILURE

  Якщо вказано, відобразити перший невдалий приклад у кожному документотесті, але придушити вихід для всіх решти прикладів. Це завадить doctest повідомляти про правильні приклади, які вийшли з ладу через попередні помилки; але це також може приховати некоректні приклади, які завершуються невдачею незалежно від першої невдачі. Якщо вказано `REPORT_ONLY_FIRST_FAILURE`, інші приклади все ще виконуються та враховуються до загальної кількості повідомлених про помилки; пригнічується тільки вихід.

doctest.FAIL_FAST

  Якщо вказано, вийти після першого невдалого прикладу та не намагатися запустити решту прикладів. Таким чином, кількість повідомлених помилок становитиме щонайбільше 1. Цей прапорець може бути корисним під час налагодження, оскільки приклади після першої помилки навіть не створюватимуть вихід налагодження.

  The doctest command line accepts the option `-f` as a shorthand for `-o FAIL_FAST`.

  Нове в версії 3.4.

doctest.REPORTING_FLAGS

  Бітова маска або об’єднання всіх наведених вище позначок звітування.

Існує також спосіб зареєструвати нові назви прапорців параметрів, хоча це не корисно, якщо ви не маєте намір розширити внутрішні `doctest` через підкласи:

doctest.register_optionflag(name)

  Створіть новий прапор параметра з заданою назвою та поверніть ціле значення нового прапора. `register_optionflag()` можна використовувати під час створення підкласів `OutputChecker` або `DocTestRunner` для створення нових параметрів, які підтримуються вашими підкласами. `register_optionflag()` завжди слід викликати за допомогою такої ідіоми:

      MY_FLAG = register_optionflag('MY_FLAG')

### Директиви

Директиви Doctest можна використовувати для зміни прапорців параметрів для окремого прикладу. Директиви Doctest — це спеціальні коментарі Python, які слідують за вихідним кодом прикладу:

    directive             ::=  "#" "doctest:" directive_options
    directive_options     ::=  directive_option ("," directive_option)*
    directive_option      ::=  on_or_off directive_option_name
    on_or_off             ::=  "+" | "-"
    directive_option_name ::=  "DONT_ACCEPT_BLANKLINE" | "NORMALIZE_WHITESPACE" | ...

Пробіли не допускаються між «+» або «-» та назвою параметра директиви. Назва опції директиви може бути будь-якою з імен прапорців опції, пояснених вище.

Директиви doctest прикладу змінюють поведінку doctest для цього окремого прикладу. Використовуйте `+`, щоб увімкнути вказану поведінку, або `-`, щоб вимкнути її.

Наприклад, цей тест проходить:

    >>> print(list(range(20)))  # doctest: +NORMALIZE_WHITESPACE
    [0,   1,  2,  3,  4,  5,  6,  7,  8,  9,
    10,  11, 12, 13, 14, 15, 16, 17, 18, 19]

Без директиви це було б невдалим, тому що фактичний вивід не має двох пробілів перед однозначними елементами списку, а також тому, що фактичний вивід містить один рядок. Цей тест також проходить, і для цього також потрібна директива:

    >>> print(list(range(20)))  # doctest: +ELLIPSIS
    [0, 1, ..., 18, 19]

В одному фізичному рядку можна використовувати кілька директив, розділених комами:

    >>> print(list(range(20)))  # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
    [0,    1, ...,   18,    19]

Якщо для одного прикладу використовується кілька коментарів директиви, вони об’єднуються:

    >>> print(list(range(20)))  # doctest: +ELLIPSIS
    ...                         # doctest: +NORMALIZE_WHITESPACE
    [0,    1, ...,   18,    19]

Як показано в попередньому прикладі, ви можете додати до свого прикладу рядки `...`, які містять лише директиви. Це може бути корисно, коли приклад надто довгий, щоб директива могла зручно розміститися в одному рядку:

    >>> print(list(range(5)) + list(range(10, 20)) + list(range(30, 40)))
    ... # doctest: +ELLIPSIS
    [0, ..., 4, 10, ..., 19, 30, ..., 39]

Зауважте, що оскільки всі параметри вимкнено за замовчуванням, а директиви застосовуються лише до прикладу, у якому вони з’являються, увімкнення параметрів (через `+` у директиві) зазвичай є єдиним значущим вибором. Однак позначки параметрів також можна передати функціям, які запускають doctests, встановлюючи різні значення за замовчуванням. У таких випадках може бути корисним вимкнення опції за допомогою `-` у директиві.

### Попередження

`doctest` серйозно ставиться до вимог точних збігів в очікуваних результатах. Якщо хоча б один символ не збігається, тест проходить невдало. Можливо, це кілька разів вас здивує, оскільки ви дізнаєтесь, що саме робить Python і що не гарантує вихід. Наприклад, під час друку набору Python не гарантує, що елемент буде надруковано в будь-якому певному порядку, тому такий тест:

    >>> foo()
    {"Hermione", "Harry"}

вразливий! Одним з обхідних шляхів є:

    >>> foo() == {"Hermione", "Harry"}
    True

замість цього. Інше - зробити

    >>> d = sorted(foo())
    >>> d
    ['Harry', 'Hermione']

Є й інші, але ви зрозуміли.

Ще одна погана ідея — друкувати речі, які містять адресу об’єкта, наприклад

    >>> id(1.0)  # certain to fail some of the time
    7948648
    >>> class C: pass
    >>> C()  # the default repr() for instances embeds an address
    <C object at 0x00AC18F0>

Директива `ELLIPSIS` дає гарний підхід для останнього прикладу:

    >>> C()  # doctest: +ELLIPSIS
    <C object at 0x...>

Числа з плаваючою комою також підлягають невеликим варіаціям виводу на різних платформах, оскільки Python віддає перевагу бібліотеці платформи C для форматування з плаваючою комою, і бібліотеки C тут сильно відрізняються за якістю.

    >>> 1./7  # risky
    0.14285714285714285
    >>> print(1./7) # safer
    0.142857142857
    >>> print(round(1./7, 6)) # much safer
    0.142857

Числа у формі `I/2.**J` безпечні на всіх платформах, і я часто створюю приклади doctest для отримання чисел такої форми:

    >>> 3./4  # utterly safe
    0.75

Прості дроби також легше зрозуміти людям, і це покращує документацію.

## Базовий API

Функції `testmod()` і `testfile()` забезпечують простий інтерфейс для doctest, якого має бути достатньо для більшості базових застосувань. Для менш формального вступу до цих двох функцій див. розділи Просте використання: перевірка прикладів у Docstrings і Просте використання: перевірка прикладів у текстовому файлі.

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)

  Усі аргументи, окрім ім’я файлу, є необов’язковими та мають бути вказані у формі ключового слова.

  Тестові приклади у файлі з назвою ім’я_файлу. Повернення `(failure_count, test_count)`.

  Необов’язковий аргумент module_relative визначає, як слід інтерпретувати назву файлу:

  - Якщо module_relative має значення `True` (за замовчуванням), тоді filename вказує незалежний від ОС шлях до модуля. За замовчуванням цей шлях є відносно каталогу викликаючого модуля; але якщо вказано аргумент package, то він відноситься до цього пакета. Щоб забезпечити незалежність від ОС, ім’я файлу має використовувати символи `/` для розділення сегментів шляху та не може бути абсолютним шляхом (тобто воно не може починатися з `/`).

  - Якщо module_relative має значення `False`, тоді filename вказує шлях до ОС. Шлях може бути абсолютним або відносним; відносні шляхи вирішуються відносно поточного робочого каталогу.

  Необов’язковий аргумент name дає назву тесту; за замовчуванням або, якщо `None`, `os.path.basename(filename)` використовується.

  Необов’язковий аргумент package — це пакет Python або ім’я пакета Python, чий каталог слід використовувати як базовий каталог для назви файла, що стосується модуля. Якщо пакет не вказано, то каталог модуля, що викликає, використовується як базовий каталог для імен файлів, що відносяться до модуля. Це помилка вказувати package, якщо module_relative має значення `False`.

  Необов’язковий аргумент globs дає dict, який буде використовуватися як глобальні під час виконання прикладів. Для doctest створюється нова поверхнева копія цього dict, тому її приклади починаються з чистого аркуша. За замовчуванням або якщо `None`, використовується новий порожній dict.

  Необов’язковий аргумент extraglobs дає dict, об’єднаний із глобальними значеннями, які використовуються для виконання прикладів. Це працює як `dict.update()`: якщо globs і extraglobs мають спільний ключ, пов’язане значення в extraglobs з’являється в комбінованому dict. За замовчуванням або якщо `None`, додаткові глобальні значення не використовуються. Це розширена функція, яка дозволяє параметризувати doctests. Наприклад, doctest можна написати для базового класу, використовуючи загальну назву для класу, а потім повторно використовувати для тестування будь-якої кількості підкласів, передавши extraglobs dict, що відображає загальну назву на підклас, який потрібно перевірити.

  Додатковий аргумент verbose друкує багато речей, якщо true, і друкує лише помилки, якщо false; за замовчуванням або якщо `None`, це істина тоді і тільки якщо `'-v''` є в `sys.argv`.

  Необов’язковий аргумент report друкує підсумок у кінці, якщо значення true, інакше нічого не друкує в кінці. У багатослівному режимі резюме є детальним, інакше резюме є дуже коротким (насправді порожнім, якщо всі тести пройдено).

  Необов’язковий аргумент optionflags (значення за замовчуванням 0) приймає побітове АБО прапорів параметрів. Дивіться розділ Прапори параметрів.

  Додатковий аргумент raise_on_error за умовчанням має значення false. Якщо істина, виняток виникає після першої помилки або несподіваного винятку в прикладі. Це дозволяє посмертно виправляти помилки. Типовою поведінкою є продовження виконання прикладів.

  Необов’язковий аргумент parser визначає `DocTestParser` (або підклас), який слід використовувати для отримання тестів із файлів. За замовчуванням використовується звичайний аналізатор (тобто `DocTestParser()`).

  Необов’язковий аргумент encoding визначає кодування, яке слід використовувати для перетворення файлу в Юнікод.

doctest.testmod(m=None, name=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False)

  Усі аргументи є необов’язковими, і всі, крім m, мають бути вказані у формі ключового слова.

  Тестові приклади в рядках документів у функціях і класах, доступних із модуля m (або модуля `__main__`, якщо m не вказано або має значення `None`), починаючи з `m.__doc__`.

  Also test examples reachable from dict `m.__test__`, if it exists. `m.__test__` maps names (strings) to functions, classes and strings; function and class docstrings are searched for examples; strings are searched directly, as if they were docstrings.

  Пошук здійснюється лише в рядках документів, приєднаних до об’єктів, що належать модулю m.

  Повернення `(failure_count, test_count)`.

  Необов’язковий аргумент name дає назву модуля; за замовчуванням або, якщо `None`, `m.__name__` використовується.

  Optional argument exclude_empty defaults to false. If true, objects for which no doctests are found are excluded from consideration. The default is a backward compatibility hack, so that code still using `doctest.master.summarize` in conjunction with `testmod()` continues to get output for objects with no tests. The exclude_empty argument to the newer `DocTestFinder` constructor defaults to true.

  Необов’язкові аргументи extraglobs, verbose, report, optionflags, raise_on_error і globs такі самі, як і для функції `testfile()` вище, за винятком того, що globs за умовчанням має значення `m .__dict__`.

doctest.run_docstring_examples(f, globs, verbose=False, name='NoName', compileflags=None, optionflags=0)

  Тестові приклади, пов’язані з об’єктом f; наприклад, f може бути рядком, модулем, функцією або об’єктом класу.

  Неглибока копія аргументу словника globs використовується для контексту виконання.

  Необов’язковий аргумент ім’я використовується в повідомленнях про помилку та за умовчанням має значення `"NoName"`.

  Якщо додатковий аргумент verbose має значення true, вихідні дані генеруються, навіть якщо немає помилок. За замовчуванням вихідні дані генеруються лише у випадку помилки прикладу.

  Необов’язковий аргумент compileflags надає набір прапорів, які має використовувати компілятор Python під час виконання прикладів. За замовчуванням або якщо `None`, прапори виводяться відповідно до набору майбутніх функцій, знайдених у globs.

  Необов’язковий аргумент optionflags працює як для функції `testfile()` вище.

## Unittest API

As your collection of doctest’ed modules grows, you’ll want a way to run all their doctests systematically. `doctest` provides two functions that can be used to create `unittest` test suites from modules and text files containing doctests. To integrate with `unittest` test discovery, include a load_tests function in your test module:

    import unittest
    import doctest
    import my_module_with_doctests

    def load_tests(loader, tests, ignore):
        tests.addTests(doctest.DocTestSuite(my_module_with_doctests))
        return tests

Є дві основні функції для створення екземплярів `unittest.TestSuite` з текстових файлів і модулів з doctests:

doctest.DocFileSuite(*paths, module_relative=True, package=None, setUp=None, tearDown=None, globs=None, optionflags=0, parser=DocTestParser(), encoding=None)

  Перетворіть тести doctest з одного чи кількох текстових файлів у `unittest.TestSuite`.

  The returned `unittest.TestSuite` is to be run by the unittest framework and runs the interactive examples in each file. If an example in any file fails, then the synthesized unit test fails, and a `failureException` exception is raised showing the name of the file containing the test and a (sometimes approximate) line number.

  Передайте один або кілька шляхів (у вигляді рядків) до текстових файлів, які потрібно перевірити.

  Параметри можуть бути надані як аргументи ключових слів:

  Необов’язковий аргумент module_relative визначає, як слід інтерпретувати назви файлів у paths:

  - Якщо module_relative має значення `True` (за замовчуванням), тоді кожне ім’я файлу в paths визначає незалежний від ОС шлях щодо модуля. За замовчуванням цей шлях є відносно каталогу викликаючого модуля; але якщо вказано аргумент package, то він відноситься до цього пакета. Щоб забезпечити незалежність від ОС, кожне ім’я файлу має використовувати символи `/` для розділення сегментів шляху та не може бути абсолютним шляхом (тобто воно не може починатися з `/`).

  - Якщо module_relative має значення `False`, тоді кожне ім’я файлу в paths вказує шлях до ОС. Шлях може бути абсолютним або відносним; відносні шляхи вирішуються відносно поточного робочого каталогу.

  Необов’язковий аргумент package — це пакет Python або ім’я пакета Python, чий каталог слід використовувати як базовий каталог для імен файлів, пов’язаних із модулями, у paths. Якщо пакет не вказано, то каталог модуля, що викликає, використовується як базовий каталог для імен файлів, що відносяться до модуля. Це помилка вказувати package, якщо module_relative має значення `False`.

  Додатковий аргумент setUp визначає функцію налаштування для набору тестів. Це викликається перед виконанням тестів у кожному файлі. Функції setUp буде передано об’єкт `DocTest`. Функція setUp може отримати доступ до глобальних параметрів тесту як атрибута globs пройденого тесту.

  Необов’язковий аргумент tearDown визначає функцію розриву для набору тестів. Це викликається після виконання тестів у кожному файлі. Функції tearDown буде передано об’єкт `DocTest`. Функція setUp може отримати доступ до глобальних параметрів тесту як атрибута globs пройденого тесту.

  Додатковий аргумент globs — це словник, що містить початкові глобальні змінні для тестів. Для кожного тесту створюється нова копія цього словника. За замовчуванням globs — це новий порожній словник.

  Необов’язковий аргумент optionflags вказує параметри тесту за замовчуванням для тестів, створені шляхом об’єднання окремих прапорців параметрів. Дивіться розділ Прапори параметрів. Перегляньте функцію `set_unittest_reportflags()` нижче, щоб дізнатися про кращий спосіб налаштування параметрів звітування.

  Необов’язковий аргумент parser визначає `DocTestParser` (або підклас), який слід використовувати для отримання тестів із файлів. За замовчуванням використовується звичайний аналізатор (тобто `DocTestParser()`).

  Необов’язковий аргумент encoding визначає кодування, яке слід використовувати для перетворення файлу в Юнікод.

  Глобальний `__file__` додається до глобалів, наданих до doctests, завантажених із текстового файлу за допомогою `DocFileSuite()`.

doctest.DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, setUp=None, tearDown=None, checker=None)

  Перетворіть тести doctest для модуля на `unittest.TestSuite`.

  The returned `unittest.TestSuite` is to be run by the unittest framework and runs each doctest in the module. If any of the doctests fail, then the synthesized unit test fails, and a `failureException` exception is raised showing the name of the file containing the test and a (sometimes approximate) line number.

  Необов’язковий аргумент module надає модуль для тестування. Це може бути об’єкт модуля або ім’я модуля (можливо з крапками). Якщо не вказано, використовується модуль, який викликає цю функцію.

  Додатковий аргумент globs — це словник, що містить початкові глобальні змінні для тестів. Для кожного тесту створюється нова копія цього словника. За замовчуванням globs — це новий порожній словник.

  Необов’язковий аргумент extraglobs визначає додатковий набір глобальних змінних, який об’єднується в globs. За замовчуванням додаткові глобальні значення не використовуються.

  Необов’язковий аргумент test_finder — це об’єкт `DocTestFinder` (або замінник), який використовується для вилучення тестів документів із модуля.

  Необов’язкові аргументи setUp, tearDown і optionflags такі самі, як і для функції `DocFileSuite()` вище.

  Ця функція використовує ту саму техніку пошуку, що й `testmod()`.

  Змінено в версії 3.5: `DocTestSuite()` повертає порожній `unittest.TestSuite`, якщо module не містить рядків документів, замість того, щоб викликати `ValueError`.

exception doctest.failureException

  When doctests which have been converted to unit tests by `DocFileSuite()` or `DocTestSuite()` fail, this exception is raised showing the name of the file containing the test and a (sometimes approximate) line number.

Under the covers, `DocTestSuite()` creates a `unittest.TestSuite` out of `doctest.DocTestCase` instances, and `DocTestCase` is a subclass of `unittest.TestCase`. `DocTestCase` isn’t documented here (it’s an internal detail), but studying its code can answer questions about the exact details of `unittest` integration.

Similarly, `DocFileSuite()` creates a `unittest.TestSuite` out of `doctest.DocFileCase` instances, and `DocFileCase` is a subclass of `DocTestCase`.

So both ways of creating a `unittest.TestSuite` run instances of `DocTestCase`. This is important for a subtle reason: when you run `doctest` functions yourself, you can control the `doctest` options in use directly, by passing option flags to `doctest` functions. However, if you’re writing a `unittest` framework, `unittest` ultimately controls when and how tests get run. The framework author typically wants to control `doctest` reporting options (perhaps, e.g., specified by command line options), but there’s no way to pass options through `unittest` to `doctest` test runners.

З цієї причини `doctest` також підтримує поняття прапорів звітності `doctest`, специфічних для підтримки `unittest`, через цю функцію:

doctest.set_unittest_reportflags(flags)

  Встановіть прапорці звітів `doctest` для використання.

  Аргумент flags приймає побітове АБО прапорів параметрів. Дивіться розділ Прапори параметрів. Можна використовувати лише «прапори звітності».

  This is a module-global setting, and affects all future doctests run by module `unittest`: the `runTest()` method of `DocTestCase` looks at the option flags specified for the test case when the `DocTestCase` instance was constructed. If no reporting flags were specified (which is the typical and expected case), `doctest`’s `unittest` reporting flags are bitwise ORed into the option flags, and the option flags so augmented are passed to the `DocTestRunner` instance created to run the doctest. If any reporting flags were specified when the `DocTestCase` instance was constructed, `doctest`’s `unittest` reporting flags are ignored.

  Функція повертає значення прапорів звітів `unittest`, які діяли до виклику функції.

## Розширений API

Основний API — це проста оболонка, призначена для полегшення використання doctest. Він досить гнучкий і повинен відповідати потребам більшості користувачів; однак, якщо вам потрібен більш детальний контроль над тестуванням або ви бажаєте розширити можливості doctest, тоді вам слід скористатися розширеним API.

Розширений API обертається навколо двох класів контейнерів, які використовуються для зберігання інтерактивних прикладів, отриманих із випадків doctest:

- `Example`: один statement Python у поєднанні з очікуваним результатом.

- `DocTest`: колекція `Example`, зазвичай витягнутих з одного рядка документа або текстового файлу.

Додаткові класи обробки визначені для пошуку, аналізу та запуску та перевірки прикладів doctest:

- `DocTestFinder`: знаходить усі рядки документів у певному модулі та використовує `DocTestParser` для створення `DocTest` з кожного рядка документів, який містить інтерактивні приклади.

- `DocTestParser`: створює об’єкт `DocTest` із рядка (наприклад, рядка документації об’єкта).

- `DocTestRunner`: Виконує приклади в `DocTest` і використовує `OutputChecker` для перевірки їх результату.

- `OutputChecker`: порівнює фактичні результати прикладу doctest з очікуваними результатами та вирішує, чи вони збігаються.

Відносини між цими класами обробки підсумовано на наступній діаграмі:

                                list of:
    +------+                   +---------+
    |module| --DocTestFinder-> | DocTest | --DocTestRunner-> results
    +------+    |        ^     +---------+     |       ^    (printed)
                |        |     | Example |     |       |
                v        |     |   ...   |     v       |
               DocTestParser   | Example |   OutputChecker
                               +---------+

### Об’єкти DocTest

class doctest.DocTest(examples, globs, name, filename, lineno, docstring)

  Набір прикладів doctest, які слід запускати в одному просторі імен. Аргументи конструктора використовуються для ініціалізації однойменних атрибутів.

  `DocTest` визначає такі атрибути. Вони ініціалізуються конструктором і не повинні змінюватися безпосередньо.

  examples

    Список об’єктів `Example`, що кодують окремі інтерактивні приклади Python, які мають виконуватися цим тестом.

  globs

    Простір імен (він же глобальні), у якому слід запускати приклади. Це словник, що зіставляє імена зі значеннями. Будь-які зміни в просторі імен, внесені прикладами (такі як зв’язування нових змінних), будуть відображені в `globs` після виконання тесту.

  name

    Ім’я рядка, що ідентифікує `DocTest`. Як правило, це ім’я об’єкта або файлу, з якого було отримано тест.

  filename

    Ім’я файлу, з якого було видобуто цей `DocTest`; або `None`, якщо назва файлу невідома, або якщо `DocTest` не було видобуто з файлу.

  lineno

    Номер рядка в `filename`, де починається цей `DocTest`, або `None`, якщо номер рядка недоступний. Цей номер рядка відраховується від нуля відносно початку файлу.

  docstring

    Рядок, з якого було отримано тест, або `None`, якщо рядок недоступний, або якщо тест не було вилучено з рядка.

### Приклад об’єктів

class doctest.Example(source, want, exc_msg=None, lineno=0, indent=0, options=None)

  Єдиний інтерактивний приклад, що складається з оператора Python і його очікуваного результату. Аргументи конструктора використовуються для ініціалізації однойменних атрибутів.

  `Example` визначає такі атрибути. Вони ініціалізуються конструктором і не повинні змінюватися безпосередньо.

  source

    Рядок, що містить вихідний код прикладу. Цей вихідний код складається з одного оператора Python і завжди закінчується символом нового рядка; конструктор додає новий рядок, коли це необхідно.

  want

    Очікуваний результат запуску вихідного коду прикладу (або зі стандартного виводу, або з відстеження у випадку винятку). `want` закінчується символом нового рядка, якщо тільки вихід не очікується, у такому випадку це порожній рядок. За потреби конструктор додає новий рядок.

  exc_msg

    Повідомлення про виняток, створене прикладом, якщо очікується, що приклад створить виняток; або `None`, якщо не очікується створення виняткової ситуації. Це повідомлення про виняток порівнюється зі значенням, що повертається `traceback.format_exception_only()`. `exc_msg` закінчується символом нового рядка, якщо він не `None`. За потреби конструктор додає новий рядок.

  lineno

    Номер рядка в рядку, що містить цей приклад, де починається приклад. Цей номер рядка відраховується від нуля відносно початку рядка, що містить.

  indent

    Відступ прикладу в рядку, що містить, тобто кількість пробілів, які передують першому запиту прикладу.

  options

    A dictionary mapping from option flags to `True` or `False`, which is used to override default options for this example. Any option flags not contained in this dictionary are left at their default value (as specified by the `DocTestRunner`’s optionflags). By default, no options are set.

### Об’єкти DocTestFinder

class doctest.DocTestFinder(verbose=False, parser=DocTestParser(), recurse=True, exclude_empty=True)

  Клас обробки, який використовується для вилучення `DocTest`s, які мають відношення до даного об’єкта, з його рядка документації та рядків документації об’єктів, які містяться в ньому. `DocTest`s можна отримати з модулів, класів, функцій, методів, статичних методів, методів класів і властивостей.

  Необов’язковий аргумент verbose можна використовувати для відображення об’єктів, які шукав шукач. За замовчуванням значення False (без виведення).

  Необов’язковий аргумент parser визначає об’єкт `DocTestParser` (або замінник), який використовується для вилучення тестів документів із рядків документів.

  Якщо необов’язковий аргумент recurse має значення false, тоді `DocTestFinder.find()` перевірятиме лише даний об’єкт, а не будь-які об’єкти, що містяться.

  Якщо необов’язковий аргумент exclude_empty має значення false, тоді `DocTestFinder.find()` включатиме тести для об’єктів із порожніми рядками документів.

  `DocTestFinder` визначає такий метод:

  find(obj[, name][, module][, globs][, extraglobs])

    Повертає список `DocTest`, які визначені рядком документації obj або будь-якими рядками документів, що містяться в ньому.

    Необов’язковий аргумент name визначає ім’я об’єкта; це ім’я буде використано для створення імен для повернутих `DocTest`s. Якщо name не вказано, тоді використовується `obj.__name__`.

    Необов’язковий параметр module — це модуль, який містить заданий об’єкт. Якщо модуль не вказано або має значення `None`, то засіб пошуку тестів спробує автоматично визначити правильний модуль. Використовується модуль об’єкта:

    - Як простір імен за замовчуванням, якщо globs не вказано.

    - Щоб DocTestFinder не видобував DocTests з об’єктів, імпортованих з інших модулів. (Об’єкти, що містяться з модулями, відмінними від module, ігноруються.)

    - Щоб знайти ім’я файлу, що містить об’єкт.

    - Щоб допомогти знайти номер рядка об’єкта в його файлі.

    Якщо module має значення `False`, спроба знайти модуль не буде зроблена. Це незрозуміло, використовується переважно під час тестування самого doctest: якщо module має значення `False` або `None`, але не може бути знайдено автоматично, тоді всі об’єкти вважаються такими, що належать до (неіснуючого) модуль, тому всі об’єкти, що містяться, будуть (рекурсивно) шукатися для тестів документів.

    Глобальні значення для кожного `DocTest` утворюються шляхом об’єднання globs і extraglobs (прив’язки в extraglobs замінюють прив’язки в globs). Для кожного `DocTest` створюється нова копія глобального словника. Якщо globs не вказано, тоді за замовчуванням використовується __dict__ модуля, якщо вказано, або `{}` інакше. Якщо extraglobs не вказано, то за замовчуванням буде `{}`.

### Об’єкти DocTestParser

class doctest.DocTestParser

  Клас обробки, який використовується для отримання інтерактивних прикладів із рядка та використання їх для створення об’єкта `DocTest`.

  `DocTestParser` визначає такі методи:

  get_doctest(string, globs, name, filename, lineno)

    Витягніть усі приклади doctest із заданого рядка та зберіть їх у об’єкт `DocTest`.

    globs, name, filename і lineno є атрибутами для нового об’єкта `DocTest`. Перегляньте документацію для `DocTest` для отримання додаткової інформації.

  get_examples(string, name='<string>')

    Витягніть усі приклади doctest із заданого рядка та поверніть їх як список об’єктів `Example`. Номери рядків базуються на 0. Необов’язковий аргумент ім’я – це ім’я, що ідентифікує цей рядок і використовується лише для повідомлень про помилки.

  parse(string, name='<string>')

    Розділіть заданий рядок на приклади та проміжний текст і поверніть їх як список чергування `Example`і рядків. Номери рядків для `Example`s засновані на 0. Необов’язковий аргумент ім’я – це ім’я, що ідентифікує цей рядок і використовується лише для повідомлень про помилки.

### Об’єкти DocTestRunner

class doctest.DocTestRunner(checker=None, verbose=None, optionflags=0)

  Клас обробки, який використовується для виконання та перевірки інтерактивних прикладів у `DocTest`.

  Порівняння очікуваних і фактичних результатів виконується за допомогою `OutputChecker`. Це порівняння можна налаштувати за допомогою кількох позначок параметрів; дивіться розділ Прапори параметрів для отримання додаткової інформації. Якщо прапорців параметрів недостатньо, порівняння також можна налаштувати, передавши підклас `OutputChecker` до конструктора.

  The test runner’s display output can be controlled in two ways. First, an output function can be passed to `TestRunner.run()`; this function will be called with strings that should be displayed. It defaults to `sys.stdout.write`. If capturing the output is not sufficient, then the display output can be also customized by subclassing DocTestRunner, and overriding the methods `report_start()`, `report_success()`, `report_unexpected_exception()`, and `report_failure()`.

  Необов’язковий аргумент ключового слова checker визначає об’єкт `OutputChecker` (або додаткову заміну), який слід використовувати для порівняння очікуваних результатів із фактичними результатами прикладів doctest.

  Додатковий аргумент ключового слова verbose контролює докладність `DocTestRunner`. Якщо verbose має значення `True`, тоді друкується інформація про кожен приклад під час його виконання. Якщо verbose має значення `False`, друкуються лише помилки. Якщо verbose не вказано або `None`, тоді використовується докладний вивід, якщо використовується параметр командного рядка `-v`.

  Необов’язковий аргумент ключового слова optionflags можна використовувати для керування тим, як програма виконання тестів порівнює очікуваний результат із фактичним результатом і як він відображає помилки. Для отримання додаткової інформації див. розділ Прапори параметрів.

  `DocTestRunner` defines the following methods:

  report_start(out, test, example)

    Повідомте, що тестувальник збирається обробити наведений приклад. Цей метод надається, щоб дозволити підкласам `DocTestRunner` налаштовувати свій вихід; його не слід називати безпосередньо.

    приклад — це приклад, який буде оброблено. тест — це тест, який містить приклад. out — це функція виводу, яка була передана в `DocTestRunner.run()`.

  report_success(out, test, example, got)

    Повідомте, що наведений приклад виконано успішно. Цей метод надається, щоб дозволити підкласам `DocTestRunner` налаштовувати свій вихід; його не слід називати безпосередньо.

    приклад — це приклад, який буде оброблено. got — фактичний вихід із прикладу. тест — це тест, що містить приклад. out — це функція виводу, яка була передана в `DocTestRunner.run()`.

  report_failure(out, test, example, got)

    Повідомте, що наведений приклад не вдався. Цей метод надається, щоб дозволити підкласам `DocTestRunner` налаштовувати свій вихід; його не слід називати безпосередньо.

    приклад — це приклад, який буде оброблено. got — фактичний вихід із прикладу. тест — це тест, що містить приклад. out — це функція виводу, яка була передана в `DocTestRunner.run()`.

  report_unexpected_exception(out, test, example, exc_info)

    Повідомте, що наведений приклад викликав несподіваний виняток. Цей метод надається, щоб дозволити підкласам `DocTestRunner` налаштовувати свій вихід; його не слід називати безпосередньо.

    приклад — це приклад, який буде оброблено. exc_info — це кортеж, що містить інформацію про неочікуваний виняток (як повертає `sys.exc_info()`). тест — це тест, що містить приклад. out — це функція виводу, яка була передана в `DocTestRunner.run()`.

  run(test, compileflags=None, out=None, clear_globs=True)

    Run the examples in test (a `DocTest` object), and display the results using the writer function out.

    Приклади запускаються в просторі імен `test.globs`. Якщо clear_globs має значення true (за замовчуванням), цей простір імен буде очищено після виконання тесту, щоб допомогти зі збиранням сміття. Якщо ви хочете перевірити простір імен після завершення тесту, використовуйте clear_globs=False.

    compileflags надає набір прапорів, які має використовувати компілятор Python під час виконання прикладів. Якщо не вказано, за замовчуванням використовуватиметься набір прапорів майбутнього імпорту, які застосовуються до globs.

    The output of each example is checked using the `DocTestRunner`’s output checker, and the results are formatted by the `DocTestRunner.report_*()` methods.

  summarize(verbose=None)

    Print a summary of all the test cases that have been run by this DocTestRunner, and return a named tuple `TestResults(failed, attempted)`.

    Необов’язковий аргумент verbose контролює, наскільки детальним є резюме. Якщо детальність не вказана, тоді використовується детальність `DocTestRunner`.

### Об’єкти OutputChecker

class doctest.OutputChecker

  Клас, який використовується для перевірки того, чи фактичний результат із прикладу doctest відповідає очікуваному результату. `OutputChecker` визначає два методи: `check_output()`, який порівнює задану пару виходів і повертає `True`, якщо вони збігаються; і `output_difference()`, який повертає рядок, що описує різницю між двома результатами.

  `OutputChecker` визначає такі методи:

  check_output(want, got, optionflags)

    Повертає `True`, якщо фактичний результат із прикладу (got) відповідає очікуваному результату (want). Ці рядки завжди вважаються такими, що збігаються, якщо вони ідентичні; але залежно від того, які прапорці параметрів використовує програма виконання тестів, також можливі кілька типів неточної відповідності. Перегляньте розділ Прапори параметрів для отримання додаткової інформації про прапорці параметрів.

  output_difference(example, got, optionflags)

    Повертає рядок, що описує відмінності між очікуваним виходом для даного прикладу (example) і фактичним виходом (got). optionflags — це набір позначок параметрів, які використовуються для порівняння want і got.

## Налагодження

Doctest надає кілька механізмів для налагодження прикладів doctest:

- Декілька функцій перетворюють doctests на виконувані програми Python, які можна запускати в налагоджувачі Python, `pdb`.

- Клас `DebugRunner` є підкласом `DocTestRunner`, який створює виняток для першого невдалого прикладу, що містить інформацію про цей приклад. Ця інформація може бути використана для виконання посмертного налагодження на прикладі.

- Випадки `unittest`, згенеровані `DocTestSuite()`, підтримують метод `debug()`, визначений `unittest.TestCase`.

- Ви можете додати виклик до `pdb.set_trace()` у прикладі doctest, і ви перейдете до налагоджувача Python, коли цей рядок буде виконано. Потім ви можете перевірити поточні значення змінних і так далі. Наприклад, припустимо, що `a.py` містить лише цей модуль docstring:

      """
      >>> def f(x):
      ...     g(x*2)
      >>> def g(x):
      ...     print(x+3)
      ...     import pdb; pdb.set_trace()
      >>> f(3)
      9
      """

  Тоді інтерактивний сеанс Python може виглядати так:

      >>> import a, doctest
      >>> doctest.testmod(a)
      --Return--
      > <doctest a[1]>(3)g()->None
      -> import pdb; pdb.set_trace()
      (Pdb) list
        1     def g(x):
        2         print(x+3)
        3  ->     import pdb; pdb.set_trace()
      [EOF]
      (Pdb) p x
      6
      (Pdb) step
      --Return--
      > <doctest a[0]>(2)f()->None
      -> g(x*2)
      (Pdb) list
        1     def f(x):
        2  ->     g(x*2)
      [EOF]
      (Pdb) p x
      3
      (Pdb) step
      --Return--
      > <doctest a[2]>(1)?()->None
      -> f(3)
      (Pdb) cont
      (0, 3)
      >>>

Функції, які перетворюють doctests на код Python і, можливо, запускають синтезований код під налагоджувачем:

doctest.script_from_examples(s)

  Перетворення тексту з прикладами на сценарій.

  Аргумент s — це рядок, що містить приклади doctest. Рядок перетворюється на сценарій Python, де приклади doctest у s перетворюються на звичайний код, а все інше перетворюється на коментарі Python. Згенерований сценарій повертається як рядок. Наприклад,

      import doctest
      print(doctest.script_from_examples(r"""
          Set x and y to 1 and 2.
          >>> x, y = 1, 2

          Print their sum:
          >>> print(x+y)
          3
      """))

  дисплеї:

      # Set x and y to 1 and 2.
      x, y = 1, 2
      #
      # Print their sum:
      print(x+y)
      # Expected:
      ## 3

  Ця функція використовується внутрішньо іншими функціями (див. нижче), але також може бути корисною, коли ви хочете перетворити інтерактивний сеанс Python на сценарій Python.

doctest.testsource(module, name)

  Перетворення doctest для об’єкта на сценарій.

  Argument module is a module object, or dotted name of a module, containing the object whose doctests are of interest. Argument name is the name (within the module) of the object with the doctests of interest. The result is a string, containing the object’s docstring converted to a Python script, as described for `script_from_examples()` above. For example, if module `a.py` contains a top-level function `f()`, then

      import a, doctest
      print(doctest.testsource(a, "a.f"))

  prints a script version of function `f()`“s docstring, with doctests converted to code, and the rest placed in comments.

doctest.debug(module, name, pm=False)

  Налагодження документів для об’єкта.

  Аргументи module і name такі самі, як і для функції `testsource()` вище. Синтезований сценарій Python для рядка документації названого об’єкта записується у тимчасовий файл, а потім цей файл запускається під керуванням налагоджувача Python, `pdb`.

  Поверхнева копія `module.__dict__` використовується як для локального, так і для глобального контексту виконання.

  Додатковий аргумент pm визначає, чи використовується посмертне налагодження. Якщо pm має значення true, файл сценарію запускається безпосередньо, і налагоджувач бере участь лише в тому випадку, якщо сценарій завершується через виклик необробленого винятку. Якщо це так, то через `pdb.post_mortem()` викликається посмертне налагодження, передаючи об’єкт трасування з необробленого винятку. Якщо pm не вказано або має значення false, сценарій запускається під налагоджувачем із самого початку, шляхом передачі відповідного виклику `exec()` до `pdb.run()`.

doctest.debug_src(src, pm=False, globs=None)

  Налагодити doctests у рядку.

  Це схоже на функцію `debug()` вище, за винятком того, що рядок, що містить приклади doctest, вказується безпосередньо через аргумент src.

  Необов’язковий аргумент pm має те саме значення, що й у функції `debug()` вище.

  Необов’язковий аргумент globs надає словник для використання як локального, так і глобального контексту виконання. Якщо не вказано або `None`, використовується порожній словник. Якщо вказано, використовується неглибока копія словника.

Клас `DebugRunner` і спеціальні винятки, які він може спричинити, представляють найбільший інтерес для авторів фреймворку тестування, і тут буде лише схематично описано. Перегляньте вихідний код, а особливо рядок документації `DebugRunner` (який є тестом документів!) для отримання додаткової інформації:

class doctest.DebugRunner(checker=None, verbose=None, optionflags=0)

  Підклас `DocTestRunner`, який викликає виняток, щойно виникає помилка. Якщо виникає неочікуваний виняток, виникає виняток `UnexpectedException`, який містить тест, приклад і оригінальний виняток. Якщо вихідні дані не збігаються, то виникає виняток `DocTestFailure`, який містить тест, приклад і фактичний результат.

  Щоб отримати інформацію про параметри та методи конструктора, перегляньте документацію для `DocTestRunner` у розділі Розширений API.

Є два винятки, які можуть бути викликані екземплярами `DebugRunner`:

exception doctest.DocTestFailure(test, example, got)

  Виняток, викликаний `DocTestRunner`, щоб повідомити, що фактичний вихід прикладу doctest не збігається з його очікуваним результатом. Аргументи конструктора використовуються для ініціалізації однойменних атрибутів.

`DocTestFailure` визначає такі атрибути:

DocTestFailure.test

  Об’єкт `DocTest`, який запускався під час помилки прикладу.

DocTestFailure.example

  Невдалий `Example`.

DocTestFailure.got

  Фактичний результат прикладу.

exception doctest.UnexpectedException(test, example, exc_info)

  Виняток, викликаний `DocTestRunner`, щоб сигналізувати про те, що приклад doctest викликав неочікуваний виняток. Аргументи конструктора використовуються для ініціалізації однойменних атрибутів.

`UnexpectedException` визначає такі атрибути:

UnexpectedException.test

  Об’єкт `DocTest`, який запускався під час помилки прикладу.

UnexpectedException.example

  Невдалий `Example`.

UnexpectedException.exc_info

  Кортеж, що містить інформацію про неочікуваний виняток, яку повертає `sys.exc_info()`.

## Мильниця

Як згадувалося у вступі, `doctest` зріс до трьох основних застосувань:

1. Перевірка прикладів у рядках документів.

2. Регресійне тестування.

3. Виконувана документація / грамотне тестування.

Ці види використання мають різні вимоги, і їх важливо розрізняти. Зокрема, заповнення ваших рядків документації незрозумілими тестовими прикладами створює погану документацію.

Під час написання документаційного рядка обережно вибирайте приклади документаційного рядка. У цьому є певне мистецтво, якому потрібно навчитися — спочатку це може бути неприродним. Приклади повинні додати справжню цінність документації. Хороший приклад часто вартий багатьох слів. Якщо їх робити обережно, приклади будуть безцінні для ваших користувачів і багаторазово окуплять час, потрачений на їх збирання, оскільки роки йдуть і все змінюється. Мене все ще дивує, як часто один із моїх прикладів `doctest` перестає працювати після «нешкідливої» зміни.

Doctest також є чудовим інструментом для регресійного тестування, особливо якщо ви не економите на пояснювальному тексті. Перемежовуючи прозу та приклади, стає набагато легше відслідковувати, що насправді перевіряється та чому. Якщо тест провалився, хороша проза може значно полегшити з’ясування проблеми та способи її вирішення. Це правда, що ви можете писати розгорнуті коментарі під час тестування на основі коду, але мало хто з програмістів це робить. Багато хто виявив, що використання підходів doctest натомість призводить до набагато чіткіших тестів. Можливо, це просто тому, що doctest робить написання прози трохи легшим, ніж написання коду, тоді як писати коментарі в коді трохи складніше. Я думаю, що це глибше, ніж просто це: природне ставлення до написання тесту на основі doctest полягає в тому, що ви хочете пояснити тонкощі свого програмного забезпечення та проілюструвати їх прикладами. Це, у свою чергу, природним чином призводить до тестових файлів, які починаються з найпростіших функцій і логічно прогресують до ускладнень і крайніх випадків. Результатом є послідовна розповідь, а не набір ізольованих функцій, які перевіряють окремі фрагменти функціональності, здавалося б, випадковим чином. Це інше ставлення, яке дає інші результати, стираючи різницю між тестуванням і поясненням.

Регресійне тестування найкраще обмежити виділеними об’єктами або файлами. Є кілька варіантів організації тестів:

- Напишіть текстові файли, що містять тестові приклади як інтерактивні приклади, і протестуйте файли за допомогою `testfile()` або `DocFileSuite()`. Це рекомендовано, хоча це найлегше зробити для нових проектів, розроблених із самого початку для використання doctest.

- Визначте функції під назвою `_regrtest_topic`, які складаються з окремих рядків документів, що містять тестові випадки для названих тем. Ці функції можна включити в той самий файл, що й модуль, або відокремити в окремий тестовий файл.

- Визначте зіставлення словника `__test__` із тем регресійних тестів на рядки документів, що містять тестові приклади.

Якщо ви розмістили свої тести в модулі, модуль сам може бути виконавцем тестів. Коли тест виходить невдалим, ви можете організувати повторний запуск лише невдалого документу, поки ви вирішуєте проблему. Ось мінімальний приклад такого тесту:

    if __name__ == '__main__':
        import doctest
        flags = doctest.REPORT_NDIFF|doctest.FAIL_FAST
        if len(sys.argv) > 1:
            name = sys.argv[1]
            if name in globals():
                obj = globals()[name]
            else:
                obj = __test__[name]
            doctest.run_docstring_examples(obj, globals(), name=name,
                                           optionflags=flags)
        else:
            fail, total = doctest.testmod(optionflags=flags)
            print("{} failures out of {} tests".format(fail, total))

Виноски

[1]

Приклади, що містять як очікуваний результат, так і виняток, не підтримуються. Спроба вгадати, де закінчується один і починається інший, занадто схильна до помилок, і це також створює заплутаний тест.