[Опираясь на wim-е правильный ответ, но объяснить, почему немного больше, с видом на нижележащих doctest
семантики.]
Пример терпит неудачу, потому что он использует синтаксис PS2 (...
) вместо PS1 синтаксис (>>>
) перед отдельными простыми заявлениями.
Изменение ...
в >>>
:
#!/usr/bin/env python2.7
# encoding: utf-8
class Dummy(object):
'''Dummy: demonstrates a doctest problem
>>> from StringIO import StringIO
>>> s = StringIO()
>>> print("s is created")
s is created
'''
if __name__ == "__main__":
import doctest
doctest.testmod()
Теперь исправленный пример, переименованный doctest_pass.py
, работает без ошибок. Он не производит никакого вывода, а это означает, что все тесты проходят:
% src/doctest_pass.py
Почему синтаксис >>>
правильно? Ссылка на библиотеку Python для doctest, 25.2.3.2. How are Docstring Examples Recognized? должна быть местом, где можно найти ответ, но это не очень понятно об этом синтаксисе.
Doctest просматривает документацию, ища «Примеры». Где он видит строку PS1 >>>
, она берет все оттуда до конца строки в качестве примера. Он также добавляет следующие строки, которые начинаются с строки PS2 ...
в пример (см.: _EXAMPLE_RE
в классе doctest.DocTestParser
, строки 584-595). Он берет последующие строки до следующей пустой строки или строки, начинающейся с строки PS1, в качестве Wanted Output.
Doctest компилирует каждый пример, как Python «интерактивное заявление», используя встроенную функцию compile()
в exec
statement (См: doctest.DocTestRunner.__run()
, строки 1314-1315).
«interactive statement» - это список инструкций, заканчивающийся символом новой строки, или Compound Statement. Составной оператор, например. a if
или try
, «в общем, [... охватывает] несколько строк, хотя в простых воплощениях целая составная инструкция может содержаться в одной строке."Вот несколько строк составного оператора:.
if 1 > 0:
print("As expected")
else:
print("Should not happen")
Список утверждение один или более simple statement с на одной строке, разделенных точкой с запятой
from StringIO import StringIO
s = StringIO(); print("s is created")
Итак, doctest на вопрос не удалось из-за него содержащий один простой пример с тремя простыми операторами и разделителями с запятой. Изменение строк PS2 для строк PS1 преуспевает, поскольку оно превращает docstring в последовательность из трех примеров, каждая из которых имеет один простой оператор. Хотя эти три строки работают вместе, чтобы настроить один тест на один элемент функциональности, они не являются одним испытательным прибором. Это три теста, два из которых устанавливают состояние, но на самом деле не тестируют основные функции.
Кстати, вы можете увидеть количество примеров, которые doctest
распознает с помощью флага -v
. Обратите внимание, что в нем говорится: «3 tests in __main__.Dummy
». Можно подумать о трех линиях как одном тестовом блоке, но doctest
видит три примера. Первые два примера не имеют ожидаемого результата. Когда в примере выполняется и не генерируется вывод, это считается «проходом».
% src/doctest_pass.py -v
Trying:
from StringIO import StringIO
Expecting nothing
ok
Trying:
s = StringIO()
Expecting nothing
ok
Trying:
print("s is created")
Expecting:
s is created
ok
1 items had no tests:
__main__
1 items passed all tests:
3 tests in __main__.Dummy
3 tests in 2 items.
3 passed and 0 failed.
Test passed.
В одной док-строке примеры выполняются последовательно. Изменения состояния из каждого примера сохраняются для следующих примеров в одной и той же документации. Таким образом, оператор import
определяет имя модуля, оператор присваивания s =
использует это имя модуля и определяет имя переменной и т. Д. Документация доктрины, 25.2.3.3. What’s the Execution Context?, наклонно раскрывает это, когда она говорит: «примеры могут свободно использовать ... имена, определенные ранее в выполняемой docstring».
Предыдущее предложение в этом разделе: «Каждый раз, когда доктрина находит проверку docstring для проверки, она использует неглубокую копию глобалов M, так что ... один тест в M не может оставлять за собой крохи, которые случайно позволяют другому тесту работать ", немного вводит в заблуждение. Это правда, что один тест в M не может повлиять на тест в другой докшлинке. Однако в пределах одной докшлинга предыдущий тест, безусловно, оставит за собой крохи, что может повлиять на последующие тесты.
Почему пример в Справочнике по библиотеке Python для doctest, 25.2.3.2. How are Docstring Examples Recognized?, показывает пример с синтаксисом ...
? В этом примере показан оператор if
, который представляет собой составной оператор на нескольких строках. Вторая и последующая строки отмечены строками PS2.
Что происходит с '...' вместо '>>>' на нескольких строках non-continuation? – user2357112
Как видно из ответов, проблема действительно в синтаксисе синтаксиса, а не в StringIO. Я удаляю тег StringIO и переписываю вопрос, чтобы не упоминать StringIO. –