(二十二)用测试客户端核对页面与数据库
1. 每个测试独立准备数据库
# 项目文件:shelf_project/tests/conftest.py
import pytest
from bs4 import BeautifulSoup
from werkzeug.security import generate_password_hash
from shelfweb import create_app
from shelfweb.db import get_db, init_db
@pytest.fixture(scope="session")
def hashes():
# 只复用计算出的摘要,登录仍经过真正的校验。
return {name: generate_password_hash(f"learn-{name}") for name in ["alice", "bob"]}
@pytest.fixture
def app(tmp_path, hashes):
application = create_app(
{
"TESTING": True,
"SECRET_KEY": "only-for-tests",
"DATABASE": str(tmp_path / "books.sqlite3"),
},
instance_path=tmp_path / "instance",
)
with application.app_context():
init_db()
connection = get_db()
with connection:
connection.executemany(
"INSERT INTO users(username,password_hash) VALUES (?,?)", hashes.items()
)
return application
@pytest.fixture
def client(app):
return app.test_client()
def csrf(client, path="/auth/login"):
response = client.get(path)
assert response.status_code == 200
return BeautifulSoup(response.data, "html.parser").select_one(
'input[name="csrf_token"]'
)["value"]
def login(client, name="alice"):
token = csrf(client)
response = client.post(
"/auth/login",
data={"username": name, "password": f"learn-{name}", "csrf_token": token},
)
assert response.status_code == 303
return response
def create(client, title="Python Web", **values):
data = {
"title": title,
"tags": "基础, 网络",
"csrf_token": csrf(client, "/books/new"),
**values,
}
return client.post("/books/new", data=data)TESTING=True 让未处理异常直接暴露给测试。这里仍注册了数据库和 HTTP 异常处理器,因此这些已经处理的失败依旧返回具体状态。
测试用 BeautifulSoup 从实际 HTML 取隐藏字段,再通过真实登录表单取得 Cookie。client 自动保存后续响应中的 Cookie,下一次请求继续发送。.get_cookie 可以核对 Cookie 是否改变,session_transaction 可以在测试中检查会话字段,或准备专门的状态。
2. 失败也核对记录与连接
| 测试链 | 核对的结果 |
|---|---|
| 新增 → 详情 → 修改 → 删除 | 状态、跳转、公开字段和最后的记录 |
| 保存后刷新 | 重复 GET,没有重复新增,flash 只显示一次 |
| 空白、过长、重复字段、附加归属 | 表单 422,不写入 |
| 同名新增或改名 | 409,原记录不变 |
| bob 读取或修改 alice 的书 | 403,记录归属与内容保留 |
| 改坏 Cookie 签名 | 无法恢复登录,JSON 返回 401 |
| 退出后重放旧 Cookie | 服务器登录记录已经删除,仍为 401 |
| 缺少、重复或旧 CSRF 令牌 | 400,不执行书籍写入 |
| INSERT 已执行后注入数据库异常 | 500,事务回滚,下一请求记录数为零 |
| 同一请求多次取连接 | 复用一次,正常和失败结束后均关闭 |
| 新工厂打开相同文件 | 书籍和有效登录仍可恢复 |
# 在 shelf_project 目录执行本项目测试。
uv run python -m pytest -q
完整检查见 书籍测试、身份与转义测试 和 资源及重开测试。测试方法可以对照 Flask 测试文档。