[Основываясь на правильном ответе 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. Как распознаются примеры строк документации? должно быть место, где можно найти ответ, но этот синтаксис не очень ясен.
Doctest сканирует строку документации в поисках «Примеров». Там, где он видит строку PS1 >>>
, он берет все оттуда до конца строки в качестве примера. Он также добавляет в пример все следующие строки, начинающиеся со строки PS2 ...
(см.: _EXAMPLE_RE
в классе doctest.DocTestParser
, строки 584-595). Он принимает последующие строки до следующей пустой строки или строки, начинающейся со строки PS1, в качестве желаемого вывода.
Doctest компилирует каждый пример как интерактивный оператор Python, используя compile()
встроенная функция в exec
операторе ( См.: doctest.DocTestRunner.__run()
, строки 1314-1315).
"интерактивный оператор" — это список операторов, заканчивающийся новой строки или составной оператор. Составное утверждение, например. оператор if
или try
, «как правило, [… занимает] несколько строк, хотя в простых воплощениях весь составной оператор может содержаться в одной строке». Вот многострочный составной оператор:
if 1 > 0:
print("As expected")
else:
print("Should not happen")
Список операторов – это один или несколько простых операторов, расположенных в одной строке, разделенных через точку с запятой.
from StringIO import StringIO
s = StringIO(); print("s is created")
Итак, doctest вопроса не прошел, потому что он содержал один пример с тремя простыми утверждениями и без разделителей с запятой. Замена строк PS2 на строки PS1 прошла успешно, поскольку строка документации превращается в последовательность из трех примеров, каждый из которых содержит одно простое выражение. Хотя эти три строки работают вместе, чтобы настроить один тест одной части функциональности, они не являются единым тестовым приспособлением. Это три теста, два из которых настраивают состояние, но не проверяют основную функциональность.
Кстати, вы можете увидеть количество примеров, которые 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 =
использует это имя модуля и определяет имя переменной и так далее. Документация по doctest, 25.2.3.3 . Что такое контекст выполнения?, косвенно раскрывает это, когда говорит: «Примеры могут свободно использовать… имена, определенные ранее в выполняемой строке документации».
Предыдущее предложение в этом разделе: «Каждый раз, когда doctest находит строку документации для тестирования, он использует неглубокую копию глобальных переменных M, так что… один тест в M не может оставить после себя крошки, которые случайно позволят другому тесту работать», — это немного вводит в заблуждение. Это правда, что один тест в M не может повлиять на тест в другой строке документации. Однако в пределах одной строки документации более ранний тест обязательно оставит после себя крохи, которые вполне могут повлиять на более поздние тесты.
Почему пример в справочнике по библиотеке Python для doctest, 25.2.3.2. Как распознаются примеры строк документа?, показать пример с синтаксисом ...
? В этом примере показан оператор if
, составной оператор, состоящий из нескольких строк. Вторая и последующие строки отмечены строками PS2.
person
Jim DeLaHunt
schedule
11.12.2016
...
вместо>>>
в нескольких строках без продолжения? - person user2357112 supports Monica   schedule 10.12.2016