Как протестировать вложенные / повторно созданные исключения с помощью doctest? - PullRequest
0 голосов
/ 12 ноября 2018

Следующий игрушечный скрипт иллюстрирует проблему:

#!/usr/bin/env python3

def bomb():
    """
    >>> bomb()
    Traceback (most recent call last):
      File "<string>", line 18, in bomb
    ZeroDivisionError: division by zero
    <BLANKLINE>
    During handling of the above exception, another exception occurred:
    <BLANKLINE>
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 20, in bomb
    Exception: re-raised
    """
    try:
        1/0
    except Exception as exception:
        raise Exception('re-raised')

if __name__ == '__main__' and '__file__' in globals():
    import sys
    if len(sys.argv) > 1 and sys.argv[1] == '-t':
        import doctest
        doctest.testmod()
    else:
        bomb()

Если я выполню bomb() в интерпретаторе python, я получу вывод, указанный строкой документации:

% python3
Python 3.5.1 (default, May 24 2016, 20:04:39)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exec(open('demo.py').read())
>>> bomb()
Traceback (most recent call last):
  File "<string>", line 18, in bomb
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 20, in bomb
Exception: re-raised
>>>

doctest, однако, неправильно сообщает об ошибке:

**********************************************************************
File "./demo.py", line 5, in __main__.bomb
Failed example:
    bomb()
Expected:
    Traceback (most recent call last):
      File "<string>", line 16, in bomb
    ZeroDivisionError: division by zero
    <BLANKLINE>
    During handling of the above exception, another exception occurred:
    <BLANKLINE>
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 18, in bomb
    Exception: re-raised
Got:
    Traceback (most recent call last):
      File "./demo.py", line 18, in bomb
        1/0
    ZeroDivisionError: division by zero
    <BLANKLINE>
    During handling of the above exception, another exception occurred:
    <BLANKLINE>
    Traceback (most recent call last):
      File "/usr/lib/python3.5/doctest.py", line 1320, in __run
        compileflags, 1), test.globs)
      File "<doctest __main__.bomb[0]>", line 1, in <module>
        bomb()
      File "./demo.py", line 20, in bomb

1 Ответ

0 голосов
/ 01 января 2019

Проблема в том, как внутренне работает doctest. В основном он загружает, компилирует и проверяет фрагменты python внутри одного и того же интерпретатора python.

Это отличается тем, как python загружает и выполняет данный фрагмент кода.

Это фрагмент doctest, который делает магию:

# Don't blink!  This is where the user's code gets run.
exec(compile(example.source, filename, "single",
     compileflags, 1), test.globs)

Когда исполняемый код вызывается и возникает исключение, трассировка содержит часть стекового фрейма механизма doctest, что отличает его от ожидаемого.

Из документации doctest :

За заголовком трассировки следует дополнительный стек трассировки, у которого содержимое игнорируется doctest. Стек трассировки обычно пропущен или скопирован дословно из интерактивного сеанса.

Теперь, последняя часть этого, кажется, применима только для единичных исключений ; «множественные или вложенные исключения» не работают таким образом, и вы не сможете проверить их трассировки. Смотрите эту тему .

Если вы все еще хотите это проверить, вы можете использовать другой «механизм проверки документов», например , например . Он имеет режим совместимости с doctest , поэтому вам не нужно переписывать все.

Отказ от ответственности: Я автор по примеру . Как я объяснил в этой теме , я действительно большой поклонник doctests, но у него есть свои ограничения. Я надеюсь, что по примеру сможет заполнить пробел и быть полезным для других людей.

...