Pytest 在烧瓶 wtforms 上失败
Pytest fails on flask wtforms
我想用pytest测试登录功能,但是测试失败。
实际上,我项目中的真正问题是当我尝试 POST
数据到登录表单时 form.validate_on_submit()
总是 False
(所有 form.field.data
是 ''
)。
所以我决定做一个最小的项目看看发生了什么。
我这里没有包括数据库,因为数据库在我的实际项目中工作正常,我想弄清楚的是为什么似乎没有数据可以发布。
但是到了下面这个最小项目的时候,又出现了一个问题:response的staus code变成了404
.
我在这个最小项目和我的真实项目中都设置了 app.config['WTF_CSRF_ENABLED'] = False
。
这个最小的项目结构在这里:
.
├── Pipfile
├── Pipfile.lock
├── app.py
├── templates
│ └── login.html
└── tests
└── test_login.py
test_login.py:
import pytest
from app import create_app
@pytest.fixture(scope='module')
def app():
app = create_app()
with app.app_context():
app.config['WTF_CSRF_ENABLED'] = False
yield app
@pytest.fixture
def client(app):
return app.test_client()
def test_login(client):
response = client.post('/login', data={'username': '1', 'password': '1'})
# response.status_code is 404 here
assert response.headers['Location'] == 'http://localhost/'
app.py:
from flask import Flask, redirect, render_template, url_for
from flask_wtf import FlaskForm
from wtforms import PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField(validators=[DataRequired()])
password = PasswordField(validators=[DataRequired()])
submit = SubmitField()
def create_app():
app = Flask('__name__')
app.config['SECRET_KEY'] = "secretkey"
return app
app = create_app()
@app.route('/')
def home():
return 'hello'
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
return redirect(url_for('home'))
return render_template('login.html', form=form)
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form method="POST">
{{ form.hidden_tag() }}
{{ form.username() }}
{{ form.password() }}
{{ form.submit() }}
</form>
</body>
</html>
我选择的虚拟环境是pipenv
和pyenv
,这里是我的Pipfile
:
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pytest = "*"
[packages]
flask-wtf = "*"
[requires]
python_version = "3.7"
原来我没有正确使用工厂模式。 Blueprint
应在工厂中使用并注册到应用程序。有关详细信息,请查看此 .
我想用pytest测试登录功能,但是测试失败。
实际上,我项目中的真正问题是当我尝试 POST
数据到登录表单时 form.validate_on_submit()
总是 False
(所有 form.field.data
是 ''
)。
所以我决定做一个最小的项目看看发生了什么。
我这里没有包括数据库,因为数据库在我的实际项目中工作正常,我想弄清楚的是为什么似乎没有数据可以发布。
但是到了下面这个最小项目的时候,又出现了一个问题:response的staus code变成了404
.
我在这个最小项目和我的真实项目中都设置了 app.config['WTF_CSRF_ENABLED'] = False
。
这个最小的项目结构在这里:
.
├── Pipfile
├── Pipfile.lock
├── app.py
├── templates
│ └── login.html
└── tests
└── test_login.py
test_login.py:
import pytest
from app import create_app
@pytest.fixture(scope='module')
def app():
app = create_app()
with app.app_context():
app.config['WTF_CSRF_ENABLED'] = False
yield app
@pytest.fixture
def client(app):
return app.test_client()
def test_login(client):
response = client.post('/login', data={'username': '1', 'password': '1'})
# response.status_code is 404 here
assert response.headers['Location'] == 'http://localhost/'
app.py:
from flask import Flask, redirect, render_template, url_for
from flask_wtf import FlaskForm
from wtforms import PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField(validators=[DataRequired()])
password = PasswordField(validators=[DataRequired()])
submit = SubmitField()
def create_app():
app = Flask('__name__')
app.config['SECRET_KEY'] = "secretkey"
return app
app = create_app()
@app.route('/')
def home():
return 'hello'
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
return redirect(url_for('home'))
return render_template('login.html', form=form)
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form method="POST">
{{ form.hidden_tag() }}
{{ form.username() }}
{{ form.password() }}
{{ form.submit() }}
</form>
</body>
</html>
我选择的虚拟环境是pipenv
和pyenv
,这里是我的Pipfile
:
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pytest = "*"
[packages]
flask-wtf = "*"
[requires]
python_version = "3.7"
原来我没有正确使用工厂模式。 Blueprint
应在工厂中使用并注册到应用程序。有关详细信息,请查看此