You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复Flask-WTF自定义验证器的pytest测试AttributeError问题

Flask-WTF自定义密码验证器错误修复

问题分析

make_password_contain_capital的参数定义是正确的——Flask-WTF自定义验证器的标准签名就是(form, field),其中field是WTForms的字段实例,自带data属性。报错的直接原因是测试代码中传入了字符串作为field参数,而字符串没有data属性,触发AttributeError。

同时代码还存在两个额外问题:

  • raise ValidationError语句的括号未闭合,存在语法错误
  • 在验证器中调用flash不符合职责划分,验证器仅需完成校验并抛出错误,提示逻辑应放在表单处理流程中

修复步骤

1. 修复自定义验证器代码(auth/functions.py)

from wtforms import ValidationError

def make_password_contain_capital(form, field):
    '''
    验证密码是否包含大写字母,不包含则抛出ValidationError
    用于RegistrationForm的password和confirm_password字段
    ''' 
    password = field.data   
    # 检查是否存在大写字母
    has_capital = any(char.isupper() for char in password)
    if not has_capital: 
        raise ValidationError("密码必须包含至少一个大写字母")
    # 验证通过无需额外操作,Flask-WTF会自动处理后续流程

2. 修复测试代码(tests/non_db_functions/login_routes.py)

测试时需要传入符合要求的field对象(带有data属性),可以用unittest.mock模拟字段,或直接使用表单的实际字段:

from app.auth.functions import make_password_contain_capital
from wsgi import app
from app.auth.forms import LoginForm
from wtforms.validators import ValidationError
import pytest
from unittest.mock import Mock

# 测试用例1:密码包含大写字母,验证通过不报错
def test_password_with_capital():
    with app.test_request_context():
        form = LoginForm()
        # 模拟WTForms字段对象
        mock_field = Mock()
        mock_field.data = 'Aejfpwo;fkjeo;'
        # 验证通过,不应抛出异常
        make_password_contain_capital(form, mock_field)

# 测试用例2:密码无大写字母,验证失败抛出异常
def test_password_without_capital():
    with app.test_request_context():
        form = LoginForm()
        mock_field = Mock()
        mock_field.data = 'aejfpwo;fkjeo;'
        with pytest.raises(ValidationError):
            make_password_contain_capital(form, mock_field)

如果不想用Mock,也可以直接操作表单的实际字段:

def test_password_without_capital():
    with app.test_request_context():
        form = LoginForm(password='aejfpwo;fkjeo;')
        # 假设LoginForm中定义了password字段
        make_password_contain_capital(form, form.password)

3. 修正测试逻辑

原测试代码逻辑矛盾:传入包含大写的密码,却期望抛出ValidationError,与验证器逻辑相悖。修正后拆分两个测试用例,分别覆盖“验证通过”和“验证失败”场景。

运行测试

保持原命令执行即可:

$env:FLASK_ENV="pytest"
pytest -q --capture=no

内容的提问来源于stack exchange,提问作者jrgop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:00:57