В doctest есть ли способ обрабатывать кодовый блок yaml как переменную?

#python #yaml #pytest #doctest

#python #yaml #pytest #doctest

Вопрос:

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

Например:

 >>> my_yaml = """
... foo:
...   bar:
...    - baz1
...    - baz2
... """
>>> my_yaml_dict = yaml.load(my_yaml_string, Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
  

Чтобы сделать код более читаемым и доступным для копирования, я бы хотел отобразить только блок yaml, а сам тест поместить в скрытый блок кода.

Это работает:

 >>> my_yaml = """
... foo:
...   bar:
...    - baz1
...    - baz2
... """

.. invisible-code-block: python

    >>> my_yaml_dict = yaml.load(my_yaml_string, Loader=yaml.FullLoader)
    >>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
  

Однако блок yaml все еще инкапсулирован my_yaml="""...""" , что затрудняет копирование и вставку.

Есть ли способ обрабатывать сам кодовый блок как переменную? Я представляю что-то в этом роде:

 .. code-block:: yaml # doctest:  varname=my_yaml_string

    foo:
      bar:
       - baz1
       - baz2

.. invisible-code-block: python

    >>> my_yaml_dict = yaml.load(my_yaml_string, Loader=yaml.FullLoader)
    >>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
  

Ответ №1:

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

Любой ожидаемый результат должен немедленно следовать за последней строкой «>>>» или «…», содержащей код, а ожидаемый результат (если таковой имеется) распространяется на следующую строку «>>>» или всю строку с пробелами. https://docs.python.org/3/library/doctest.html#how-are-docstring-examples-recognized

Альтернативным решением может быть перемещение указанных данных Yaml во внешнюю переменную, переменную, которая не определена в блоке doctest:

 my_yaml_string = """
foo:
    bar:
      - baz1
      - baz2
"""
  

Вышеуказанная переменная может быть использована непосредственно из блока doctest:

 >>> my_yaml_dict = yaml.load(my_yaml_string, Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
  

Кроме my_yaml_string того, переменная может быть определена в другом модуле, чтобы не влиять на производительность во время выполнения:

 >>> import test_constants
>>> my_yaml_dict = yaml.load(test_constants.my_yaml_string, Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
  

Кроме того, тестовые данные могут быть полностью перенесены в отдельный файл. Дополнительным преимуществом этого является включение покрытия статического анализатора для выбранного языка сериализации данных (в данном случае Yaml):

 # test_data.yaml
foo:
    bar:
      - baz1
      - baz2
  
 >>> my_yaml_dict = yaml.load(open("test_data.yaml"), Loader=yaml.FullLoader)
>>> assert "baz_2" in my_yaml_dict["foo"]["bar"]
  

Обратите внимание, что это "test_data.yaml" может потребоваться преобразовать в абсолютный путь, в зависимости от того, как выполняются doctests .

Комментарии:

1. Разделение тестовых данных на другие файлы выглядит многообещающе. Я попробую. Спасибо!