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

如何使用pytest测试Flask框架编写的登录路由接口?

Flask login路由pytest测试编写方案

前置依赖与基础配置

  • 提前安装依赖:pytest、pytest-flask、flask-sqlalchemy(项目本身已有的依赖无需重复安装)
  • 在测试目录下新建conftest.py,编写通用测试fixture:
import pytest
from your_app import create_app, db
from your_app.models import User
from werkzeug.security import generate_password_hash

@pytest.fixture(scope="function")
def app():
    # 配置测试用app
    app = create_app()
    app.config.update({
        "TESTING": True,
        "SQLALCHEMY_DATABASE_URI": "sqlite:///:memory:",
        "WTF_CSRF_ENABLED": False,
        "SECRET_KEY": "test_secret_key"
    })
    # 初始化数据库
    with app.app_context():
        db.create_all()
        yield app
        db.session.remove()
        db.drop_all()

@pytest.fixture(scope="function")
def client(app):
    # 返回测试客户端
    return app.test_client()

@pytest.fixture(scope="function")
def test_user(app):
    # 预先创建测试用户
    with app.app_context():
        user = User(
            user_name="test_user",
            password=generate_password_hash("test_pass123")
        )
        db.session.add(user)
        db.session.commit()
        # 重新查询后返回,避免detached问题
        return User.query.filter_by(user_name="test_user").first()

注意把代码中your_app替换为你实际的项目入口文件路径

测试用例(覆盖路由所有逻辑分支)

在测试目录下新建test_auth.py,编写以下测试用例:

1. 已登录用户访问登录页,自动跳转到个人页

def test_login_redirect_when_authenticated(client, test_user):
    # 先登录测试用户
    client.post(
        "/auth/login",
        data={"user_name": "test_user", "password": "test_pass123"}
    )
    # 访问登录页
    response = client.get("/auth/login", follow_redirects=False)
    # 验证302重定向到/me
    assert response.status_code == 302
    assert response.headers["Location"].endswith("/auth/me")

2. 未登录用户GET请求访问登录页,返回登录模板

def test_login_get_request(client):
    response = client.get("/auth/login")
    assert response.status_code == 200
    # 验证返回页面包含登录表单关键词,可根据你的模板内容调整
    assert b"user_name" in response.data
    assert b"password" in response.data

3. 登录提交不存在的用户名,返回对应错误提示

def test_login_nonexistent_username(client):
    response = client.post(
        "/auth/login",
        data={"user_name": "nonexist", "password": "any_pass"},
        follow_redirects=True
    )
    # 验证错误flash消息
    flash_messages = response.context["get_flashed_messages"](with_categories=True)
    assert ("err", "Username does not exist") in flash_messages
    # 验证未跳转,仍在登录页
    assert response.status_code == 200

4. 登录提交正确用户名、错误密码,返回对应错误提示

def test_login_wrong_password(client, test_user):
    response = client.post(
        "/auth/login",
        data={"user_name": "test_user", "password": "wrong_pass"},
        follow_redirects=True
    )
    flash_messages = response.context["get_flashed_messages"](with_categories=True)
    assert ("err", "Incorrect password, try again.") in flash_messages
    assert response.status_code == 200

5. 登录提交正确用户名密码,登录成功跳转到个人页

def test_login_success(client, test_user):
    response = client.post(
        "/auth/login",
        data={"user_name": "test_user", "password": "test_pass123"},
        follow_redirects=False
    )
    # 验证重定向到个人页
    assert response.status_code == 302
    assert response.headers["Location"].endswith("/auth/me")
    # 验证成功flash消息
    follow_response = client.get("/auth/me")
    flash_messages = follow_response.context["get_flashed_messages"](with_categories=True)
    assert ("accepted", "Logged in successfully!") in flash_messages
    # 验证用户已登录
    with client.session_transaction() as sess:
        assert sess["_user_id"] == str(test_user.id)

注意:如果你的auth蓝图挂载的路径前缀不是/auth,把测试用例中的路径前缀替换为你实际使用的前缀即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:06:03