如何使用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
相关产品推荐
相关产品推荐

