【问题标题】:Testing a POST that uses Flask-WTF validate_on_submit测试使用 Flask-WTF validate_on_submit 的 POST
【发布时间】:2016-10-01 10:56:44
【问题描述】:

我在测试 POST 以向数据库中添加一个类别时遇到了困难,我使用 Flask_WTF 进行验证和 CSRF 保护。对于 CRUD 操作 pm 我的网站。我使用过 Flask、Flask_WTF 和 Flask-SQLAlchemy。这是我的第一个独立项目,我发现自己对如何测试 Flask-WTForm validate_on_submit 函数有点迷茫。

以下是模型:

class Users(db.Model):
    id = db.Column(db.Integer, primary_key=True, unique=True)
    name = db.Column(db.String(80), nullable=False)
    email = db.Column(db.String(250), unique=True)

class Category(db.Model):
    id = db.Column(db.Integer, primary_key=True, unique=True)
    name = db.Column(db.String(250), nullable=False, unique=True)
    users_id = db.Column(db.Integer, db.ForeignKey('users.id'))

这是表格:

class CategoryForm(Form):
    name = StringField(
        'Name', [validators.Length(min=4, max=250, message="name problem")])

这是控制器:

@category.route('/category/add', methods=['GET', 'POST'])
@login_required
def addCategory():
    """ Add a new category.
        Returns: Redirect Home.
    """
    # Initiate the form.
    form = CategoryForm()
    # On POST of a valid form, add the new category.
    if form.validate_on_submit():
        category = Category(
            form.name.data, login_session['users_id'])
        db.session.add(category)
        db.session.commit()
        flash('New Category %s Successfully Created' % category.name)
        return redirect(url_for('category.showHome'))
    else:
        # Render the form to add the category.
        return render_template('newCategory.html', form=form)

如何使用 validate_on_submit 函数为 if 语句编写测试?

【问题讨论】:

    标签: python python-2.7 wtforms flask-wtforms


    【解决方案1】:

    您的应用应该有不同的配置,具体取决于您是在本地/在生产中/在执行单元测试。您可以设置的一种配置是

    WTF_CSRF_ENABLED = False
    

    flask-wtforms documentation

    【讨论】:

    【解决方案2】:

    使用 py.test 和 Delightful testing with pytest and SQLAlchemy 推荐的 conftest.py,这是一个确认添加类别的测试。

    def test_add_category_post(app, session):
        """Does add category post a new category?"""
        TESTEMAIL = "test@test.org"
        TESTUSER = "Joe Test"
        user = Users.query.filter(Users.email==TESTEMAIL).first()
        category = Category(name="Added Category", users_id=user.id)
        form = CategoryForm(formdata=None, obj=category)
        with app.test_client() as c:
            with c.session_transaction() as sess:
                sess['email'] = TESTEMAIL
                sess['username'] = TESTUSER 
                sess['users_id'] = user.id
                response = c.post(
                    '/category/add', data=form.data, follow_redirects=True)
        assert response.status_code == 200
        added_category = Category.query.filter(
            Category.name=="Added Category").first()
        assert added_category
        session.delete(added_category)
        session.commit()
    

    请注意,新类别被分配给一个变量,然后用于创建一个表单。表单的数据在帖子中使用。

    【讨论】:

    • 我不必要地迷惑了 WTForm 类的工作原理。在查看了 Flask-WTF 和 WTFrom 的源代码后,我能够澄清 Flask-WTF 的 validate_on_submit() 只是 Flask-WTF 的 is_submitted() 和 WTForm validate()。 is_submitted() 检查响应和 POST 或 PUT 方法。
    • 我会感谢更专业的用户提供的意见。将类别放入表单然后将表单用作发布数据是否不必要?提前致谢。
    • 我也非常感谢专家用户的更多意见。我即将开始编写这类测试,我怀疑您确实不需要需要使用实际表单来创建POST 数据,但我可以想象它可能会使事情更容易。我将通过在正常路线使用期间简单地打印请求POST 数据来测试这个问题(即,将print(request.form) 添加到实际路线),但我怀疑它只会包含在易于识别的变量中到 WTForm 变量命名约定。测试后会报告。
    • 过早的报告:request.form 中的数据包含在 ImmutableMultiDict 中,我不熟悉该对象,但会阅读其文档。但是,我要注意的一件事是,csrf 令牌可能会因不使用 WTF 表单而带来挑战。由于您使用validate_on_submit() 方法,我将假设您正在使用csrf 令牌,因此我想该令牌已经在发布数据中生成。如果没有表格,我的怀疑是,您将没有csrf 令牌,您将无法正确验证。将进一步调查。
    • 迟来的更新:普通字典也能正常工作。 CSRF 令牌是一个问题,但对于这个确切的问题有不同的答案(并非所有解决方案都始终有效)。
    猜你喜欢
    • 2023-03-15
    • 2018-03-15
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    相关资源
    最近更新 更多