使用 pytest 测试 flask_wtf/wtforms

Testing flask_wtf/wtforms with pytest

我想测试一个处理非平凡形式的 POST 路由(通过使用 flask.request.form)。我并没有真正找到一个很好的教程,因为大多数传递 json 数据而不是形式(或者是相同的?)。

我试着用下面的方式写代码:

import pytest
import app #app.app is the Flask app

@pytest.fixture
def client():
    app.app.config['TESTING'] = True

    with app.app.test_client() as client:
        with app.app.app_context():
            yield client


def test_route_webapp_post(client):
    form = app.forms.ImputeForm.make_form(data_dict=app.data_dictionary.data_dict,
                                        numeric_fields=app.binaries_dict['numeric_mappers'].keys(),
                                        recordname2description=app.binaries_dict['recordname2description'])
    rv = client.post('/web_app',form=form)
    assert rv.status_code==200

表单是动态生成的,我并不总是提前知道字段是什么:

from flask_wtf import FlaskForm
from wtforms import SelectField, DecimalField, BooleanField

class ImputeForm(FlaskForm):

    @classmethod
    def make_form(cls, data_dict, numeric_fields, recordname2description, request_form=None):

        for key in numeric_fields:

            setattr(cls, key, DecimalField(id=key, label=recordname2description[key].split('(')[0]))
            setattr(cls, 'mask_' + key, BooleanField(label='mask_' + key))

        for key in data_dict:

            setattr(cls, key, SelectField(id=key, label=recordname2description[key],
                                          choices=[(-1, 'None selected')]+list(data_dict[key].items())))
            setattr(cls, 'mask_' + key, BooleanField(label='mask_' + key))


        instance = cls(request_form)
        return instance

但这并没有真正起作用,因为我无法在测试用例中创建一个表单并获取

E           RuntimeError: Working outside of request context.
E           
E           This typically means that you attempted to use functionality that needed
E           an active HTTP request.  Consult the documentation on testing for
E           information about how to avoid this problem.

那么测试我的表单的正确方法是什么(特别是我可以发送一个空的表单)?

正确的方法是创建 python 字典并将其作为 "data" 传递,而不是尝试创建表单。

在特定情况下,这涉及创建一个新函数:

def make_from_data( data_dict, numeric_fields):

    data = dict()

    for key in numeric_fields:

        data[key]='234'
        data['mask_' + key]='y'

    for key in data_dict:

        data[key]=-1
        data['mask_' + key]='y'

    return data

并按如下方式传递:

def test_route_webapp_post(client):

    data = make_from_data(data_dict=app.data_dictionary.data_dict,
                                    numeric_fields=app.binaries_dict['numeric_mappers'].keys())
    rv = client.post('/web_app',data=data)
    assert rv.status_code==200