Я пишу модульные тесты для метода проверки формы в приложении Flask, которое содержит несколько разных кнопок «Отправить» для управления логическим потоком.
Метод проверки формы ожидает получить объект ImmutibleMultiDict
, который включает имя кнопки и значение, например ('btn', 'Save')
или ('btn', 'Update')
или ('btn', 'Delete')
. К сожалению, я не могу понять, как издеваться или предоставлять различные ответы кнопок в pytest.
Ниже приведен пример кода из метода проверки формы с некоторыми различными действиями в зависимости от того, какая кнопка использовалась при отправке («Обновить» или «Сохранить»):
def validate(self):
if request.form['btn'] == 'Update':
if cn_continent_name and en_continent_name:
flash('You have not made a change. There is nothing to update.', 'warning')
return False
if not _check_clean_chinese():
return False
if request.form['btn'] == 'Save':
# check if Chinese name already exists in the DB
if cn_continent_name:
self.cn_name.errors.append("Chinese Continent Name already registered")
return False
# check the if English name already exists in the DB
en_continent_name = ContinentsTable.query.filter_by(en_name=self.en_name.data).first()
if en_continent_name:
self.en_name.errors.append("English Country Name already registered")
return False
Приведенный ниже тест метода проверки формы не работает, поскольку отсутствует информация о значении имени кнопки, которая соответствует тестируемой логике проверки формы, которая ожидает проверки наличия request.form['btn'] = 'Save'
или request.form['btn'] = 'Update'
.
class TestContinentsForm:
"""Continents form."""
def test_validate_continent_cn_name_already_registered(self, continent):
"""Enter Continent cn_name that is already registered."""
form = ContinentsForm(cn_name=continent.cn_name, en_name='NewEngName')
assert form.validate() is False
assert 'Chinese Continent Name already registered' in form.cn_name.errors
Ниже приведен сбой теста с кодом ошибки, и причина, по которой он имеет ошибку, заключается в том, что проверка ожидает объект werkzeug ImmutibleMutltiDict, который включает имя кнопки, которая использовалась для отправки формы, но я не указал должным образом имя кнопки в объект ImmutibleMultiDict.
Я пробовал десятки вещей, но в приведенном ниже тесте прокомментирован один пример request.form.add('btn','Save')
, который не работает, потому что не может напрямую изменять объект ImmutibleMutliDict:
self = <tests.test_forms.TestContinentsForm object at 0x10f8be908>
continent = Asia, 亚洲, yà zhōu!
def test_validate_continent_cn_name_already_registered(self, continent):
"""Enter Continent cn_name that is already registered."""
form = ContinentsForm(cn_name=continent.cn_name, en_name='NewEngName')
#request.form.add('btn','Save')
#assert 'Save' in request.form
>assert form.validate() is False
test_forms.py:96:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../aoscrdb_app/user/forms/locations/continents_form.py:70: in validate
if 'Delete' in request.form['btn']:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ImmutableMultiDict([]), key = 'btn'
def __getitem__(self, key):
"""Return the first data value for this key;
raises KeyError if not found.
:param key: The key to be looked up.
:raise KeyError: if the key does not exist.
"""
if key in self:
return dict.__getitem__(self, key)[0]
>raise exceptions.BadRequestKeyError(key)
E werkzeug.exceptions.HTTPException.wrap.<locals>.newcls: 400: Bad Request
../venv/lib/python3.5/site-packages/werkzeug/datastructures.py:402: BadRequestKeyError
Чтобы правильно протестировать проверку формы, объект ImmutableMultiDict должен выглядеть так, включая данные ('btn', 'Save')
:
This is reqest.form =>ImmutableMultiDict([('cn_name', '中地'), ('btn', 'Save'),
('en_name', 'Middle Earth'),
('csrf_token', '1455956207##90932fcb2d1481be007f90e32040b6aba3e5fe68')])
Я использую pytest и factory-boy, а ниже приведены соответствующие приспособления pytest и factory. Я пытался создать другие приспособления pytest, которые включают данные кнопки, но это также не сработало для меня:
@pytest.fixture()
def continent(db):
"""A continent for the tests."""
continent = ContinentFactory()
db.session.commit()
return continent
class ContinentFactory(BaseFactory):
"""Continent factory."""
cn_name = '亚洲'
en_name = 'Asia'
class Meta:
"""Factory configuration."""
model = ContinentsTable
Я считаю, что кнопки должны быть сохранены в словаре, таком как {'btn': 'Save'}
, и доступны для тестовой среды, но я не могу найти лучший способ реализации. Спасибо!
request.form['btn'] = 'Save'
илиrequest.form['btn'] = 'Update'
- person Bob Jordan   schedule 20.02.2016('btn', 'Save)
в случае «Сохранить - person Bob Jordan   schedule 24.02.2016