测试
前言
本章整理 Flask 测试:使用 Pytest 做单元测试,使用 Flask 内置的 test_client 做 API 自动化测试。
安装:
python -m pip install pytest
基础用法:test_client
app.test_client() 可以在不启动服务器的情况下模拟 HTTP 请求:
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.get("/ping")
def ping():
return jsonify({"msg": "pong"})
@app.post("/items")
def create_item():
data = request.get_json()
return jsonify({"name": data["name"], "price": data["price"]}), 201
test_app.py:
import pytest
from app import app
@pytest.fixture
def client():
app.config["TESTING"] = True
return app.test_client()
def test_ping(client):
resp = client.get("/ping")
assert resp.status_code == 200
assert resp.get_json() == {"msg": "pong"}
def test_create_item(client):
resp = client.post("/items", json={"name": "apple", "price": 3.5})
assert resp.status_code == 201
assert resp.get_json() == {"name": "apple", "price": 3.5}
运行:
python -m pytest test_app.py -v
测试请求上下文
需要测试不经过 HTTP 的代码(如 url_for、g)时,使用 app.test_request_context():
def test_request_context():
with app.test_request_context("/?q=1"):
assert request.method == "GET"
assert request.args.get("q") == "1"
assert url_for("ping") == "/ping"
测试认证与异常
def test_unauthorized(client):
resp = client.get("/me")
assert resp.status_code == 401
def test_login_then_access(client):
resp = client.post("/login", json={"username": "zhangsan", "password": "123456"})
token = resp.get_json()["access_token"]
resp = client.get("/me", headers={"Authorization": f"Bearer {token}"})
assert resp.status_code == 200
使用 requests 做端到端测试
服务启动后,也可以用 requests 直接访问真实 HTTP 接口(适合接口联调/冒烟测试):
import json
import requests
headers = {"Content-Type": "application/json"}
def test_api():
resp = requests.post(
"http://127.0.0.1:5000/adduser",
data=json.dumps({"username": "test", "password": "123456", "email": "test@demo.com"}),
headers=headers,
)
assert resp.json()["code"] == 200
提示
数据库相关接口的测试示例见 连接数据库/flask-sqlalchemy的基本使用(使用 pytest 测试 CRUD 接口)。