我要对成功/失败的登录进行单元测试。成功的登录有效,但失败的登录无效。
我检查通过flask.flash
添加的错误消息是否在响应的数据中。不是,但是当我手动检查登录名时,系统似乎按预期工作。我可以使用正确的凭据登录,不能使用错误的凭据登录,输入错误的凭据时,可以看到“无效的电子邮件或密码”烧瓶闪烁消息。
为什么在单元测试中看不到flask.flash
响应?
app.py:
#!/usr/bin/env python
# 3rd party modules
from flask import Flask, redirect, url_for, flash, render_template
from flask_wtf import FlaskForm
from wtforms import BooleanField
from wtforms import StringField, PasswordField, SubmitField
from flask_login import (
LoginManager,
current_user,
login_user,
login_required,
logout_user,
UserMixin,
)
app = Flask(__name__)
app.secret_key = b"secret"
app.config["WTF_CSRF_ENABLED"] = False
login_manager = LoginManager(app)
login_manager.login_view = "login"
@login_manager.user_loader
def load_user(user_id):
return User()
class User(UserMixin):
id = "foobar"
class LoginForm(FlaskForm):
email = StringField("Email")
password = PasswordField("Password")
remember_me = BooleanField("Remember Me")
submit = SubmitField("Log In")
@app.route("/")
def index():
return redirect(url_for("login"))
@app.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return redirect(url_for("success"))
form = LoginForm()
if form.validate_on_submit():
invalid_email = form.email.data != "foo@example.com"
invalid_password = form.password.data != "bar"
if invalid_email or invalid_password:
flash("Invalid email or password", "error")
return redirect(url_for("login"))
user = User()
login_user(user, remember=form.remember_me.data)
return redirect(url_for("success"))
else:
print("Form was not submitted or validated.")
print("DEGUG: Form errors:")
print(form.errors)
return render_template("login.html", form=form)
@app.route("/success")
@login_required
def success():
return "You are logged in!"
if __name__ == "__main__":
app.run(port=5000)
templates / login.html:
<form action="" method="post" class="" role="form">
{{ form.hidden_tag() }}
{% if form.email.errors %}
{% for error in form.email.errors %}
{{ error }}
{% endfor %}
{% endif %}
{{ form.email(size=32, class_="form-control", placeholder="Enter email") }}
<hr />
{{ form.password(size=32, class_="form-control", placeholder="Enter Password", autocomplete="current-password") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
{{ error }}
{% endfor %}
{{ form.submit(class_="btn btn-primary login-btn btn-block") }}
</form>
test_auth.py:
#!/usr/bin/env python
# core modules
import logging
# 3rd party modules
import pytest
# internal modules
import app
logger = logging.getLogger(__name__)
@pytest.fixture
def client():
"""Start with a blank database."""
app_obj = app.app
client = app_obj.test_client()
yield client
def test_login_succeeds(client):
resp = login(client, "foo@example.com", "bar")
assert "Invalid" not in resp.data.decode("utf-8")
def test_login_fails(client):
resp = login(client, "foo@example.com", "wrong")
assert "Invalid" in resp.data.decode("utf-8")
def login(client, email, password):
return client.post(
"/login",
data=dict(submit="Log In", email=email, password=password, csrf_token="foo"),
follow_redirects=True,
)
def logout(client):
return client.get("/logout", follow_redirects=True)