test: 后端 pytest 测试基建 (Phase0) — 6 用例全绿 + 部署前备份SOP合规
This commit is contained in:
1 parent
9e9c506ba9
commit
13578ba4c2
7 files changed
+89
No files matched your search
@@ -0,0 +1,12 @@
|
|||||||
|
"""Pytest 根配置:保证测试运行时 backend 包根目录在 sys.path 中。
|
||||||
|
|
||||||
|
运行方式(容器内,使用项目 venv):
|
||||||
|
cd /app/backend/python
|
||||||
|
/app/backend/python/.venv/bin/python -m pytest
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
if ROOT not in sys.path:
|
||||||
|
sys.path.insert(0, ROOT)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[pytest]
|
||||||
|
testpaths = tests
|
||||||
|
python_files = test_*.py
|
||||||
|
python_classes = Test*
|
||||||
|
python_functions = test_*
|
||||||
|
asyncio_mode = auto
|
||||||
|
asyncio_default_fixture_loop_scope = function
|
||||||
|
addopts = -q --strict-markers
|
||||||
|
filterwarnings =
|
||||||
|
ignore::DeprecationWarning
|
||||||
|
ignore::PendingDeprecationWarning
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Phase 0 测试基建 — 开发/测试依赖(不进入生产 requirements.txt)
|
||||||
|
pytest==8.3.4
|
||||||
|
pytest-asyncio==0.24.0
|
||||||
|
httpx==0.27.2
|
||||||
Whitespace-only changes.
@@ -0,0 +1,20 @@
|
|||||||
|
"""应用市场场景分类器回归(稳定模块,无外部依赖)。
|
||||||
|
|
||||||
|
仅校验分类法结构本身不被破坏;不调用 _classify_scene(其内部会请求 LLM)。
|
||||||
|
分类法是前端筛选/徽章的数据源,结构回归会导致全站分类错乱。
|
||||||
|
"""
|
||||||
|
from app.api.market import MARKET_SCENES
|
||||||
|
|
||||||
|
|
||||||
|
def test_market_scenes_is_14_flat():
|
||||||
|
assert len(MARKET_SCENES) == 14
|
||||||
|
|
||||||
|
|
||||||
|
def test_market_scenes_unique_ids_and_required_keys():
|
||||||
|
ids = [s["id"] for s in MARKET_SCENES]
|
||||||
|
assert len(set(ids)) == 14 # 无重复 id
|
||||||
|
for s in MARKET_SCENES:
|
||||||
|
assert "id" in s
|
||||||
|
assert "label" in s
|
||||||
|
assert "desc" in s
|
||||||
|
assert isinstance(s["label"], str) and s["label"].strip()
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
"""Phase 0 安全网 — 后端冒烟测试。
|
||||||
|
|
||||||
|
核心价值:证明整个后端(含 chat.py 等巨型模块)在测试环境下能无错误导入并挂载路由。
|
||||||
|
任何破坏 import 的脆弱补丁都会在此立刻变红,从而把"改了没生效 / 启动即崩"挡在部署前。
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def test_app_imports_and_has_routes():
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
assert app is not None
|
||||||
|
# 真实路由数远超 0;若 chat.py 等模块 import 失败,本测试在 import 阶段即报错
|
||||||
|
assert len(app.routes) > 50
|
||||||
|
|
||||||
|
|
||||||
|
def test_openapi_schema_builds():
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
schema = app.openapi()
|
||||||
|
assert "paths" in schema
|
||||||
|
assert len(schema["paths"]) > 0
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
"""短信宝脚手架回归(稳定模块,纯函数)。
|
||||||
|
|
||||||
|
验证登录密码 MD5 算法与短信宝约定一致(32 位小写十六进制)。
|
||||||
|
这是短信验证码功能(注册/改密/充值)能连通短信宝的前提。
|
||||||
|
"""
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
from app.sms_client import smsbao_md5
|
||||||
|
|
||||||
|
|
||||||
|
def test_smsbao_md5_matches_hashlib():
|
||||||
|
samples = ["XHR521yhf", "abc123", "密码测试", ""]
|
||||||
|
for pw in samples:
|
||||||
|
assert smsbao_md5(pw) == hashlib.md5(pw.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def test_smsbao_md5_is_32_lower_hex():
|
||||||
|
out = smsbao_md5("XHR521yhf")
|
||||||
|
assert len(out) == 32
|
||||||
|
assert out == out.lower()
|
||||||
|
assert all(c in "0123456789abcdef" for c in out)
|
||||||
Reference in new issue
Block a user