跳到主要内容

测试

前言

本章整理 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_forg)时,使用 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 接口)。