В таверне, как загрузить общую сцену? - PullRequest
0 голосов
/ 03 июля 2018

Я использую https://github.com/taverntesting/tavern, но следующее, вероятно, действительно вопрос PyYAML.

Нам бы хотелось иметь каталог тестов, в котором каждый файл соответствует конечной точке API.

api/v1/test_thing1.tavern.yaml
api/v1/test_thing2.tavern.yaml

и так далее. Каждый документ YAML будет нуждаться в login, который может идти в common_stages.yaml в верхней части дерева. Почти все, что я пробовал, заканчивается этой ошибкой от PyYAML

yaml.scanner.ScannerError: mapping values are not allowed here

common_stages.yaml выглядит так:

---
stages:
- name: &login_required
  request:
    url: "{host}/api/v1/login"
    json:
      username: "{username}"
      password: "{password}"
    method: POST
    headers:
      content-type: application/json
  response:
    status_code: 201
    cookies:
      - session
    headers:
      content-type: application/json

и тестовый файл выглядит так:

---
test_name: Get thing1 list

includes:
  - !include ../../common.yaml

stages:
  - name: Get category list
    request:
      url: "{host}/api/v1/thing1"
      method: GET
    response:
      status_code: 200
      headers:
        content-type: application/json

Я попытался добавить include_stages в список с помощью common. Я попытался включить его в stages строке test_thing1.tavern.yaml. Радости нет.

Все примеры Tavern показывают документ YAML в виде одного длинного файла. Что хорошо для демонстрации, но не для реального использования.

1 Ответ

0 голосов
/ 03 июля 2018

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

И ваши файлы загружаются нормально, без ошибок , если вы !include правильный файл . В своем вопросе вы ссылаетесь на common_stages.yaml, а в вашем test_thing1.tavern.yaml вы !include ../../common.yaml. Поэтому, скорее всего, у вашего common.yaml есть синтаксическая ошибка, а у common_stages.yaml, который вы здесь указываете, нет.

Доказательство того, что ваши файлы загружаются нормально:

import os
from pathlib import Path
import yaml

from yaml.reader import Reader
from yaml.scanner import Scanner
from yaml.parser import Parser
from yaml.composer import Composer
from yaml.constructor import SafeConstructor
from yaml.resolver import Resolver

# this class slightly simplified from 
# https://github.com/taverntesting/tavern/blob/master/tavern/util/loader.py
class IncludeLoader(Reader, Scanner, Parser, Composer, Resolver,
        SafeConstructor):
    """YAML Loader with `!include` constructor and which can remember anchors
    between documents"""

    def __init__(self, stream):
        """Initialise Loader."""

        # pylint: disable=non-parent-init-called

        try:
            self._root = os.path.split(stream.name)[0]
        except AttributeError:
            self._root = os.path.curdir
        self.anchors = {}
        Reader.__init__(self, stream)
        Scanner.__init__(self)
        Parser.__init__(self)
        SafeConstructor.__init__(self)
        Resolver.__init__(self)


def construct_include(loader, node):
    """Include file referenced at node."""

    # pylint: disable=protected-access
    filename = os.path.abspath(os.path.join(
        loader._root, loader.construct_scalar(node)
    ))
    extension = os.path.splitext(filename)[1].lstrip('.')

    if extension not in ('yaml', 'yml'):
        raise BadSchemaError("Unknown filetype '{}'".format(filename))

    with open(filename, 'r') as f:
        return yaml.load(f, IncludeLoader)


IncludeLoader.add_constructor("!include", construct_include)

Path('common.yaml').write_text("""\
---
stages:
- name: &login_required
  request:
    url: "{host}/api/v1/login"
    json:
      username: "{username}"
      password: "{password}"
    method: POST
    headers:
      content-type: application/json
  response:
    status_code: 201
    cookies:
      - session
    headers:
      content-type: application/json
""")

t_yaml = 'test_thing1.tavern.yaml'
Path(t_yaml).write_text("""\
---
test_name: Get thing1 list

includes:
  - !include common.yaml

stages:
  - name: Get category list
    request:
      url: "{host}/api/v1/thing1"
      method: GET
    response:
      status_code: 200
      headers:
        content-type: application/json
""")


data = yaml.load(open(t_yaml), Loader=IncludeLoader)

print(data['includes'][0]['stages'][0]['request']['url'])

Выход:

{host}/api/v1/login
...