Модульный тест не выполняется на wtforms - PullRequest
0 голосов
/ 30 марта 2019

При использовании pytest для проведения юнит-тестов при отправке данных в колбы в мас-формах, данные поля формы всегда равны '', что похоже на то, что данные неправильно "публикуются" в формах, и это вызывает form.validate_on_submit() всегда возвращай False. Я отключил WTF_CSRF_ENABLED при тестировании.

Я сделал минимальный проект, чтобы продемонстрировать эту проблему. Я не включил базу данных здесь, потому что база данных отлично работает в моем реальном проекте.

Эта минимальная структура проекта здесь:

.
├── app.py
├── templates
│   └── login.html
└── tests
    └── test_login.py

test_login.py:

import unittest
from flask import current_app
from app import create_app


class BasicsTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app()
        self.app.config['WTF_CSRF_ENABLED'] = False
        self.app_context = self.app.app_context()
        self.app_context.push()
        self.client = self.app.test_client()

    def tearDown(self):
        self.app_context.pop()

    def test_app_exists(self):
        self.assertFalse(current_app is None)

    def test_home_page(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)

    def test_login(self):
        response = self.client.post(
            '/login', data={
                'username': 'a',
                'password': 'a'
            })

app.py:

from flask import Flask, redirect, render_template, url_for, Blueprint
from flask_wtf import FlaskForm
from wtforms import PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired, Length

bp = Blueprint('myapp', __name__)


@bp.route('/')
def home():
    return 'hello'


@bp.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm(prefix='form-login-')
    if form.validate_on_submit():
        return redirect(url_for('home'))
    return render_template('login.html', form=form)


class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Log In')


def create_app():
    app = Flask('__name__')
    app.config['SECRET_KEY'] = 'secretkey'
    app.register_blueprint(bp)
    return app

1 Ответ

2 голосов
/ 30 марта 2019

Оказывается, что когда у ваших wtforms есть свойство prefix, то способ, которым вы отправляете данные, должен измениться.данные в форме:

response = self.client.post(
            '/login', data={
                'username': 'a',
                'password': 'a'
            })

Он не будет правильно передавать данные, пока вы не добавите prefix, который вы используете в форме, в словарь данных, например:

response = self.client.post(
            '/login', data={
                'form-login-username': 'a',
                'form-login-password': 'a'
            })

Всетеперь работает нормально!

Но если вы хотите получить данные поля формы, вам все равно следует использовать form.username.data, без каких-либо prefix.

...