[英]How to send image with form data in test case with unittest in flask application?
[英]How to send QuerySelectField form data to a Flask view in a unittest?
我正在嘗試在我正在處理的 flask 應用程序中測試編輯和添加視圖。 該網站的一個版本已部署並且視圖工作正常,但我正在進行的測試似乎沒有正確傳遞 QuerySelectField 數據。 此外,在測試中,我檢查表單數據是否有效並且它確實有效,所以它應該通過。
下面是測試:
class TestingWhileLoggedIn(TestCase):
def create_app(self):
app = c_app(TestConfiguration)
return app
# executed prior to each test
def setUp(self):
self.app_context = self.app.app_context()
self.app_context.push()
db.create_all()
login(self.client, '******', '******')
# executed after each test
def tearDown(self):
db.session.remove()
db.drop_all()
self.app_context.pop()
logout(self.client)
def test_add_post_page_li(self):
p_cat = PostCategory(name='Resources')
p_cat1 = PostCategory(name='Ressdgources')
p_cat2 = PostCategory(name='Ressdgsdgources')
p_cat3 = PostCategory(name='Reurces')
db.session.add(p_cat)
db.session.add(p_cat1)
db.session.add(p_cat2)
db.session.add(p_cat3)
db.session.commit()
all_cats = PostCategory.query.all()
self.assertEqual([p_cat,p_cat1,p_cat2,p_cat3], all_cats)
response = self.client.get('/add_post', follow_redirects=False)
self.assertEqual(response.status_code, 200)
data = dict(title='Hello', content='fagkjkjas', category=p_cat)
form = PostForm(data=data)
# this test passes!
self.assertEqual(form.validate(), True)
# printing the data to see what it is
print(form.data)
response_1 = self.client.post('/add_post', follow_redirects=False, data=form.data, content_type='multipart/form-data')
# this one fails
self.assertEqual(response_1.status_code, 302)
new_post = db.session.query(Post).filter_by(name='Hello').first()
self.assertNotEqual(new_post, None)
以下是測試中的終端 output。 最后兩次失敗與我發布的問題相同,因此我將它們排除在外。
.......................................{'title': None, 'category': None, 'content': None, 'submit': False}
{'title': 'Hello', 'category': <PostCategory 'Resources'>, 'content': 'fagkjkjas', 'submit': False}
{'title': 'Hello', 'category': None, 'content': 'fagkjkjas', 'submit': True}
F.F.......F..
======================================================================
FAIL: test_add_post_page_li (__main__.TestingWhileLoggedIn)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 165, in test_add_post_page_li
self.assertEqual(response_1.status_code, 302)
AssertionError: 200 != 302
字典打印輸出來自我注入的一些打印語句,以幫助我理解問題。 第一個字典是當沒有表單提交到 add_post 視圖時,第二個字典來自測試,它顯示已填寫的類別字段,最后一個來自顯示未填充類別的 add_post 視圖。
下面是 add_post 視圖:
@blogs.route('/add_post', methods=['GET', 'POST'])
def add_post():
"""
Add a blog post
"""
if not session.get('logged_in'):
return redirect(url_for('other.home'))
form = PostForm()
print(form.data)
if form.validate_on_submit():
new_post = Post(name=form.title.data, content=form.content.data, category_id=form.category.data.id, category=form.category.data)
print('hello')
try:
db.session.add(new_post)
db.session.commit()
except:
# not the best behaviour and should change
return redirect(url_for('other.home'))
return redirect(url_for('other.home'))
return render_template('add_post.html', form=form)
這是包含 PostForm 的 forms.py 文件
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
from wtforms.ext.sqlalchemy.fields import QuerySelectField
from ..models import PostCategory
#
# This function is designed to obtain choices for the categories in the PostForm.
#
def category_choices() :
return PostCategory.query
#
# PostForm
# Purpose:
# Gives the user a way to input information into the post table.
#
# Fields:
# Title: String Field (Required)
# Category: QuerySelectField (Required)
# Obtains the categories from the database. As of right now there exists
# only two categories (Travel and Projects)
#
# Content: Text Field (Required)
# Submit: Submit Field
#
class PostForm(FlaskForm):
"""
Form that lets the user add a new post
"""
title = StringField('Title', validators=[DataRequired()])
category = QuerySelectField('Category', validators=[DataRequired()], query_factory=category_choices)
content = TextAreaField('Content', validators=[DataRequired()])
submit = SubmitField('Submit')
#
# PostCategoryForm
# Purpose:
# allows user to add new subcategories
#
# Fields:
# Name: String Field (Required)
# Submit: SubmitField
#
class PostCategoryForm(FlaskForm) :
"""
Form used to submit new subcategories
"""
name = StringField('Name', validators=[DataRequired()])
submit = SubmitField('Submit')
下面是配置文件
import os
from os.path import abspath, dirname, join
# _cwd = dirname(abspath(__file__))
_basedir = os.path.abspath(os.path.dirname(__file__))
TOP_LEVEL_DIR = os.path.abspath(os.curdir)
class Config(object) :
pass
class BaseConfiguration(object):
SQLALCHEMY_TRACK_MODIFICATIONS = False
class ProductionConfiguration(BaseConfiguration):
SQLALCHEMY_DATABASE_URI = '**********************'
SQLALCHEMY_POOL_PRE_PING = True
SQLALCHEMY_ENGINE_OPTIONS = {'pool_recycle' : 3600}
SECRET_KEY = '******************'
UPLOAD_FOLDER = TOP_LEVEL_DIR + '/app/static'
class TestConfiguration(BaseConfiguration):
TESTING = True
WTF_CSRF_ENABLED = False
SECRET_KEY = '*************'
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(_basedir, 'testing.sqlite')
在我看來,wtforms 在測試環境中沒有發送 QuerySelectView 但我不知道為什么。 任何幫助表示贊賞。
編輯:在我最初的問題中,我沒有明確表示這只是具有 QuerySelectField 的 forms 的問題。 沒有 QuerySelectField 的 Forms 正在工作並通過所有測試。
Flask discord 服務器上的一個樂於助人的人能夠為我回答這個問題。
問題是 Flask-wtforms 不會傳遞 model 的整個實例,而是只傳遞主鍵。 解決方案是只傳遞數據字典中的主鍵,如下所示:
class TestingWhileLoggedIn(TestCase):
def create_app(self):
app = c_app(TestConfiguration)
return app
# executed prior to each test
def setUp(self):
self.app_context = self.app.app_context()
self.app_context.push()
db.create_all()
login(self.client, '******', '*****')
# executed after each test
def tearDown(self):
db.session.remove()
db.drop_all()
self.app_context.pop()
logout(self.client)
def test_add_post_page_li(self):
p_cat = PostCategory(name='Resources')
p_cat1 = PostCategory(name='Ressdgources')
p_cat2 = PostCategory(name='Ressdgsdgources')
p_cat3 = PostCategory(name='Reurces')
db.session.add(p_cat)
db.session.add(p_cat1)
db.session.add(p_cat2)
db.session.add(p_cat3)
db.session.commit()
all_cats = PostCategory.query.all()
self.assertEqual([p_cat,p_cat1,p_cat2,p_cat3], all_cats)
response = self.client.get('/add_post', follow_redirects=False)
self.assertEqual(response.status_code, 200)
# the following line was changed from having category=p_cat to
# category=p_cat.id
data = dict(title='Hello', content='fagkjkjas', category=p_cat.id)
#
# The following code has been commented out since it is no longer needed
#
# form = PostForm(data=data)
#
# this would not pass anymore
# self.assertEqual(form.validate(), True)
#
# printing the data to see what it is
# print(form.data)
# This line was changed from having data=form.data to data=data
response_1 = self.client.post('/add_post', follow_redirects=False, data=data, content_type='multipart/form-data')
# this one fails
self.assertEqual(response_1.status_code, 302)
new_post = db.session.query(Post).filter_by(name='Hello').first()
self.assertNotEqual(new_post, None)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.