Встраивание тестового кода или данных в строки doctest

Я хотел бы иметь несколько doctests в тестовых данных и/или функциях общего доступа к файлам. Есть ли способ сделать это, не находя их во внешнем файле или в коде тестируемого файла?

Обновить

"""This is the docstring for the module ``fish``.

I've discovered that I can access the module under test
  from within the doctest, and make changes to it, eg


>>> import fish
>>> fish.data = {1: 'red', 2: 'blue'}
"""

def jef():
    """
    Modifications made to the module will persist across subsequent tests:

    >>> import fish
    >>> fish.data[1]
    'red'
    """
    pass

def seuss():
    """
    Although the doctest documentation claims that
      "each time doctest finds a docstring to test,
       it uses a shallow copy of M‘s globals",
      modifications made to the module by a doctest
      are not imported into the context of subsequent docstrings:

    >>> data
    Traceback (most recent call last):
      ...
    NameError: name 'data' is not defined
    """
    pass

Итак, я предполагаю, что doctest копирует модуль один раз, а затем копирует копию для каждой строки документации?

В любом случае импорт модуля в каждую строку документации кажется полезным, хотя и неудобным.

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

Мне пришло в голову, что (теоретически) возможно динамически создать модуль, чтобы содержать это пространство имен. Однако пока я не получил никаких указаний о том, как это сделать, из вопроса, который я задал об этом Некоторое время назад. Любая информация приветствуется! (как ответ на соответствующий вопрос)

В любом случае я бы предпочел, чтобы изменения распространялись непосредственно в пространство имен последующих строк документации. Итак, мой первоначальный вопрос остается в силе, с этим в качестве определителя.


person intuited    schedule 20.07.2010    source источник


Ответы (2)


Это то, что заставляет людей отказываться от doctests: по мере того, как ваши тесты становятся все более сложными, вам нужны настоящие инструменты программирования, чтобы иметь возможность разрабатывать свои тесты так же, как вы разрабатываете код продукта.

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

Вам понадобится использовать реальный код, чтобы определить часть вашей тестовой инфраструктуры. Если вам нравятся доктесты, вы можете использовать эту инфраструктуру из своих доктестов.

person Ned Batchelder    schedule 20.07.2010
comment
Согласованный. Доктесты отлично подходят для иллюстрации базового использования и тестирования API, но для более глубоких тестов вам понадобятся более традиционные модульные тесты. Положительным моментом является то, что вы можете запускать свои doctests из основных фреймворков модульного тестирования. - person Ryan Ginstrom; 07.11.2010
comment
Суть была не в том, чтобы использовать doctests для тестирования, а в том, чтобы иметь возможность повторно использовать объекты в примерах использования в различных функциях или классах. - person intuited; 08.02.2011

Это возможно возможно, хотя, возможно, и не афишируется так громко.

Чтобы получить грамотные модули с тестами, которые используют общий контекст выполнения (т. е. отдельные тесты могут делиться и повторно использовать свои результаты), нужно посмотреть соответствующая часть документации, в которой говорится:

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

...

Вы можете принудительно использовать собственный словарь в качестве контекста выполнения, передав вместо него globs=your_dict в testmod() или testfile().

Учитывая это, мне удалось перепроектировать модуль doctest, который помимо использования копий (т.е. copy()), он также очищает глобальный словарь (используя clear()) после каждого теста.

Таким образом, можно исправить свой собственный словарь глобальных переменных примерно так:

class Context(dict):
    def clear(self):
        pass
    def copy(self):
        return self 

а затем используйте его как:

import doctest
from importlib import import_module

module = import_module('some.module')
doctest.testmod(module,
                # Make a copy of globals so tests in this
                # module don't affect the tests in another
                glob=Context(module.__dict__.copy()))
person K3---rnc    schedule 06.02.2016