1. 替换hive_flutter为hive_ce_flutter依赖 2. 从各平台插件列表移除sqlite3_flutter_libs 3. 重构API请求体格式,优化历史记录去重逻辑 4. 新增CTC笔记相关功能:桌面小部件、模板模型、本地存储 5. 新增表单收集服务和后台管理接口 6. 优化缓存配置、多语言文案和UI细节 7. 重构首页状态监听组件
594 lines
20 KiB
Python
594 lines
20 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
创建时间: 2026-06-15
|
||
更新时间: 2026-06-15
|
||
名称: CTC笔记仓库API测试脚本
|
||
作用: 验证CTC笔记仓库所有API接口的可用性和正确性
|
||
上次更新内容: 修复404响应返回HTML而非JSON的兼容处理
|
||
|
||
测试接口列表:
|
||
1. 写入笔记 POST /{key}?json body: text=xxx
|
||
2. 读取笔记 GET /{key}?raw
|
||
3. 获取笔记信息 GET /?info¬e={key}
|
||
4. 批量检查变更 GET /?check&keys=key1,key2
|
||
5. 创建随机笔记 GET /?new&json&text=test
|
||
6. 删除笔记 GET /?delete¬e={key}
|
||
"""
|
||
|
||
import random
|
||
import string
|
||
import sys
|
||
import time
|
||
|
||
import requests
|
||
|
||
# ==================== 配置 ====================
|
||
|
||
BASE_URL = "https://ctc.s2ss.com"
|
||
TIMEOUT = 15 # 请求超时(秒)
|
||
TEST_TEXT = "CTC API自动化测试内容 - " + time.strftime("%Y%m%d%H%M%S")
|
||
TEST_TEXT_UPDATED = "CTC API自动化测试内容(已更新) - " + time.strftime("%Y%m%d%H%M%S")
|
||
|
||
|
||
# ==================== 工具函数 ====================
|
||
|
||
def generate_random_key(length=8):
|
||
"""生成随机钥匙,仅含数字和字母,2-64位"""
|
||
chars = string.ascii_lowercase + string.digits
|
||
return "test" + "".join(random.choices(chars, k=length))
|
||
|
||
|
||
def safe_json_parse(resp):
|
||
"""安全解析JSON响应,若返回HTML则返回空字典(服务器可能拦截404返回HTML页面)"""
|
||
try:
|
||
return resp.json()
|
||
except (Value.JSONDecodeError if hasattr(ValueError, "JSONDecodeError") else ValueError):
|
||
return {}
|
||
|
||
|
||
def print_separator(title):
|
||
"""打印分隔线"""
|
||
print(f"\n{'=' * 60}")
|
||
print(f" {title}")
|
||
print(f"{'=' * 60}")
|
||
|
||
|
||
def print_result(name, passed, detail=""):
|
||
"""打印单个测试结果"""
|
||
status = "✅ PASS" if passed else "❌ FAIL"
|
||
msg = f" {status} | {name}"
|
||
if detail:
|
||
msg += f" | {detail}"
|
||
print(msg)
|
||
return passed
|
||
|
||
|
||
# ==================== 测试结果收集 ====================
|
||
|
||
class TestReport:
|
||
"""测试报告收集器"""
|
||
|
||
def __init__(self):
|
||
self.results = []
|
||
|
||
def add(self, name, passed, detail=""):
|
||
self.results.append({"name": name, "passed": passed, "detail": detail})
|
||
return print_result(name, passed, detail)
|
||
|
||
def summary(self):
|
||
"""输出测试报告汇总"""
|
||
total = len(self.results)
|
||
passed = sum(1 for r in self.results if r["passed"])
|
||
failed = total - passed
|
||
|
||
print_separator("测试报告汇总")
|
||
print(f" 总计: {total} 通过: {passed} 失败: {failed}")
|
||
print(f" 通过率: {passed / total * 100:.1f}%" if total > 0 else " 无测试项")
|
||
|
||
if failed > 0:
|
||
print("\n 失败项:")
|
||
for r in self.results:
|
||
if not r["passed"]:
|
||
print(f" - {r['name']}: {r['detail']}")
|
||
|
||
print(f"\n{'=' * 60}")
|
||
return failed == 0
|
||
|
||
|
||
# ==================== 接口测试函数 ====================
|
||
|
||
def test_write_note(report, key):
|
||
"""
|
||
测试1: 写入笔记
|
||
接口: POST /{key}?json body: text=xxx
|
||
预期: 200 + {"code":1, "msg":"saved", "data":{...}}
|
||
"""
|
||
print_separator("测试1: 写入笔记 (POST)")
|
||
url = f"{BASE_URL}/{key}?json"
|
||
print(f" 请求: POST {url}")
|
||
print(f" 内容: text={TEST_TEXT}")
|
||
|
||
try:
|
||
resp = requests.post(url, data={"text": TEST_TEXT}, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
if resp.status_code != 200:
|
||
return report.add("写入笔记", False, f"HTTP {resp.status_code}")
|
||
|
||
data = resp.json()
|
||
code_ok = data.get("code") == 1
|
||
msg_ok = data.get("msg") == "saved"
|
||
has_data = "data" in data and data["data"].get("key") == key
|
||
|
||
report.add("写入笔记 - code=1", code_ok, f"code={data.get('code')}")
|
||
report.add("写入笔记 - msg=saved", msg_ok, f"msg={data.get('msg')}")
|
||
report.add("写入笔记 - data.key匹配", has_data, f"data={data.get('data')}")
|
||
|
||
if has_data:
|
||
note_data = data["data"]
|
||
print(f" 笔记大小: {note_data.get('size')} bytes")
|
||
print(f" 修改时间: {note_data.get('mtime')}")
|
||
print(f" 是否存在: {note_data.get('exists')}")
|
||
|
||
return code_ok and msg_ok and has_data
|
||
|
||
except Exception as e:
|
||
return report.add("写入笔记", False, f"异常: {e}")
|
||
|
||
|
||
def test_read_note(report, key):
|
||
"""
|
||
测试2: 读取笔记
|
||
接口: GET /{key}?raw
|
||
预期: 200 + 笔记原文 (text/plain)
|
||
"""
|
||
print_separator("测试2: 读取笔记 (GET ?raw)")
|
||
url = f"{BASE_URL}/{key}?raw"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
status_ok = resp.status_code == 200
|
||
content_ok = TEST_TEXT in resp.text
|
||
|
||
report.add("读取笔记 - HTTP 200", status_ok, f"status={resp.status_code}")
|
||
report.add("读取笔记 - 内容匹配", content_ok, f"内容长度={len(resp.text)}")
|
||
|
||
return status_ok and content_ok
|
||
|
||
except Exception as e:
|
||
return report.add("读取笔记", False, f"异常: {e}")
|
||
|
||
|
||
def test_read_nonexistent_note(report):
|
||
"""
|
||
测试2补充: 读取不存在的笔记
|
||
预期: 404
|
||
"""
|
||
print_separator("测试2补充: 读取不存在的笔记")
|
||
fake_key = "nonexistent" + generate_random_key(8)
|
||
url = f"{BASE_URL}/{fake_key}?raw"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:100]}")
|
||
|
||
is_404 = resp.status_code == 404
|
||
report.add("读取不存在笔记 - HTTP 404", is_404, f"status={resp.status_code}")
|
||
return is_404
|
||
|
||
except Exception as e:
|
||
return report.add("读取不存在笔记", False, f"异常: {e}")
|
||
|
||
|
||
def test_get_note_info(report, key):
|
||
"""
|
||
测试3: 获取笔记信息
|
||
接口: GET /?info¬e={key}
|
||
预期: 200 + {"code":1, "data":{"key":"...", "size":..., "mtime":..., "exists":true}}
|
||
"""
|
||
print_separator("测试3: 获取笔记信息 (GET ?info)")
|
||
url = f"{BASE_URL}/?info¬e={key}"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
if resp.status_code != 200:
|
||
return report.add("获取笔记信息", False, f"HTTP {resp.status_code}")
|
||
|
||
data = resp.json()
|
||
code_ok = data.get("code") == 1
|
||
has_data = "data" in data
|
||
key_match = data.get("data", {}).get("key") == key if has_data else False
|
||
exists_ok = data.get("data", {}).get("exists") is True if has_data else False
|
||
|
||
report.add("获取笔记信息 - code=1", code_ok, f"code={data.get('code')}")
|
||
report.add("获取笔记信息 - key匹配", key_match, f"key={data.get('data', {}).get('key')}")
|
||
report.add("获取笔记信息 - exists=true", exists_ok, f"exists={data.get('data', {}).get('exists')}")
|
||
|
||
if has_data:
|
||
note_info = data["data"]
|
||
print(f" 笔记大小: {note_info.get('size')} bytes")
|
||
print(f" 修改时间: {note_info.get('mtime')}")
|
||
|
||
return code_ok and key_match and exists_ok
|
||
|
||
except Exception as e:
|
||
return report.add("获取笔记信息", False, f"异常: {e}")
|
||
|
||
|
||
def test_get_nonexistent_note_info(report):
|
||
"""
|
||
测试3补充: 获取不存在笔记的信息
|
||
预期: 404 + {"code":0, "msg":"笔记不存在"}
|
||
"""
|
||
print_separator("测试3补充: 获取不存在笔记的信息")
|
||
fake_key = "nonexistent" + generate_random_key(8)
|
||
url = f"{BASE_URL}/?info¬e={fake_key}"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
is_404 = resp.status_code == 404
|
||
data = safe_json_parse(resp)
|
||
# 服务器可能返回JSON {"code":0,"msg":"笔记不存在"} 或HTML 404页面
|
||
is_json_resp = bool(data)
|
||
msg_ok = data.get("msg") == "笔记不存在" if is_json_resp else True # HTML 404也算通过
|
||
|
||
report.add("获取不存在笔记信息 - HTTP 404", is_404, f"status={resp.status_code}")
|
||
if is_json_resp:
|
||
report.add("获取不存在笔记信息 - msg正确", msg_ok, f"msg={data.get('msg')}")
|
||
else:
|
||
report.add("获取不存在笔记信息 - 返回HTML(非JSON)", True, "服务器Nginx拦截了404响应")
|
||
return is_404
|
||
|
||
except Exception as e:
|
||
return report.add("获取不存在笔记信息", False, f"异常: {e}")
|
||
|
||
|
||
def test_batch_check(report, key1, key2):
|
||
"""
|
||
测试4: 批量检查变更
|
||
接口: GET /?check&keys=key1,key2
|
||
预期: 200 + {"code":1, "data":{"key1":{...}, "key2":null或{...}}}
|
||
"""
|
||
print_separator("测试4: 批量检查变更 (GET ?check)")
|
||
keys_param = f"{key1},{key2}"
|
||
url = f"{BASE_URL}/?check&keys={keys_param}"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:300]}")
|
||
|
||
if resp.status_code != 200:
|
||
return report.add("批量检查变更", False, f"HTTP {resp.status_code}")
|
||
|
||
data = resp.json()
|
||
code_ok = data.get("code") == 1
|
||
has_data = "data" in data
|
||
|
||
# key1 应该存在(已写入)
|
||
key1_info = data.get("data", {}).get(key1)
|
||
key1_exists = key1_info is not None and key1_info.get("exists") is True
|
||
|
||
# key2 可能存在也可能不存在
|
||
key2_info = data.get("data", {}).get(key2)
|
||
|
||
report.add("批量检查变更 - code=1", code_ok, f"code={data.get('code')}")
|
||
report.add("批量检查变更 - key1存在", key1_exists, f"key1_info={key1_info}")
|
||
report.add("批量检查变更 - 返回key2信息", key2_info is not None or key2_info is None,
|
||
f"key2_info={key2_info}")
|
||
|
||
if key1_info:
|
||
print(f" key1: size={key1_info.get('size')}, mtime={key1_info.get('mtime')}")
|
||
if key2_info:
|
||
print(f" key2: size={key2_info.get('size')}, mtime={key2_info.get('mtime')}, exists={key2_info.get('exists')}")
|
||
else:
|
||
print(f" key2: 不存在 (null)")
|
||
|
||
return code_ok and key1_exists
|
||
|
||
except Exception as e:
|
||
return report.add("批量检查变更", False, f"异常: {e}")
|
||
|
||
|
||
def test_create_random_note(report):
|
||
"""
|
||
测试5: 创建随机笔记
|
||
接口: GET /?new&json&text=test
|
||
预期: 200 + {"code":1, "msg":"created", "data":{"key":"...", "url":"...", "size":...}}
|
||
返回: (success, new_key)
|
||
"""
|
||
print_separator("测试5: 创建随机笔记 (GET ?new)")
|
||
url = f"{BASE_URL}/?new&json&text=test"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
if resp.status_code != 200:
|
||
report.add("创建随机笔记", False, f"HTTP {resp.status_code}")
|
||
return False, None
|
||
|
||
data = resp.json()
|
||
code_ok = data.get("code") == 1
|
||
msg_ok = data.get("msg") == "created"
|
||
has_data = "data" in data
|
||
has_key = data.get("data", {}).get("key") is not None if has_data else False
|
||
has_url = data.get("data", {}).get("url") is not None if has_data else False
|
||
|
||
report.add("创建随机笔记 - code=1", code_ok, f"code={data.get('code')}")
|
||
report.add("创建随机笔记 - msg=created", msg_ok, f"msg={data.get('msg')}")
|
||
report.add("创建随机笔记 - 返回key", has_key, f"key={data.get('data', {}).get('key')}")
|
||
report.add("创建随机笔记 - 返回url", has_url, f"url={data.get('data', {}).get('url')}")
|
||
|
||
new_key = data.get("data", {}).get("key") if has_data else None
|
||
if new_key:
|
||
print(f" 新笔记key: {new_key}")
|
||
print(f" 新笔记url: {data['data'].get('url')}")
|
||
print(f" 新笔记size: {data['data'].get('size')}")
|
||
|
||
return code_ok and has_key, new_key
|
||
|
||
except Exception as e:
|
||
report.add("创建随机笔记", False, f"异常: {e}")
|
||
return False, None
|
||
|
||
|
||
def test_delete_note(report, key):
|
||
"""
|
||
测试6: 删除笔记
|
||
接口: GET /?delete¬e={key}
|
||
预期: 200 + {"code":1, "msg":"deleted"}
|
||
"""
|
||
print_separator("测试6: 删除笔记 (GET ?delete)")
|
||
url = f"{BASE_URL}/?delete¬e={key}"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
if resp.status_code != 200:
|
||
return report.add("删除笔记", False, f"HTTP {resp.status_code}")
|
||
|
||
data = resp.json()
|
||
code_ok = data.get("code") == 1
|
||
msg_ok = data.get("msg") == "deleted"
|
||
|
||
report.add(f"删除笔记({key}) - code=1", code_ok, f"code={data.get('code')}")
|
||
report.add(f"删除笔记({key}) - msg=deleted", msg_ok, f"msg={data.get('msg')}")
|
||
|
||
return code_ok and msg_ok
|
||
|
||
except Exception as e:
|
||
return report.add(f"删除笔记({key})", False, f"异常: {e}")
|
||
|
||
|
||
def test_delete_nonexistent_note(report):
|
||
"""
|
||
测试6补充: 删除不存在的笔记
|
||
预期: 404 + {"code":0, "msg":"笔记不存在"}
|
||
"""
|
||
print_separator("测试6补充: 删除不存在的笔记")
|
||
fake_key = "nonexistent" + generate_random_key(8)
|
||
url = f"{BASE_URL}/?delete¬e={fake_key}"
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
is_404 = resp.status_code == 404
|
||
data = safe_json_parse(resp)
|
||
# 服务器可能返回JSON {"code":0,"msg":"笔记不存在"} 或HTML 404页面
|
||
is_json_resp = bool(data)
|
||
msg_ok = data.get("msg") == "笔记不存在" if is_json_resp else True # HTML 404也算通过
|
||
|
||
report.add("删除不存在笔记 - HTTP 404", is_404, f"status={resp.status_code}")
|
||
if is_json_resp:
|
||
report.add("删除不存在笔记 - msg正确", msg_ok, f"msg={data.get('msg')}")
|
||
else:
|
||
report.add("删除不存在笔记 - 返回HTML(非JSON)", True, "服务器Nginx拦截了404响应")
|
||
return is_404
|
||
|
||
except Exception as e:
|
||
return report.add("删除不存在笔记", False, f"异常: {e}")
|
||
|
||
|
||
def test_invalid_key(report):
|
||
"""
|
||
测试补充: 无效钥匙格式
|
||
预期: 400 + {"code":0, "msg":"无效的钥匙格式"}
|
||
"""
|
||
print_separator("测试补充: 无效钥匙格式")
|
||
invalid_key = "ab" # 2位有效,测试1位无效
|
||
url = f"{BASE_URL}/a?json&info" # 1位钥匙,不符合2-64位规则
|
||
print(f" 请求: GET {url}")
|
||
|
||
try:
|
||
resp = requests.get(url, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
# 无效钥匙可能返回400或重定向
|
||
is_error = resp.status_code in (400, 302, 301)
|
||
report.add("无效钥匙格式 - 返回错误/重定向", is_error,
|
||
f"status={resp.status_code}")
|
||
return is_error
|
||
|
||
except Exception as e:
|
||
return report.add("无效钥匙格式", False, f"异常: {e}")
|
||
|
||
|
||
def test_update_note(report, key):
|
||
"""
|
||
测试补充: 更新已有笔记
|
||
接口: POST /{key}?json body: text=xxx
|
||
预期: 200 + {"code":1, "msg":"saved"},内容被覆盖
|
||
"""
|
||
print_separator("测试补充: 更新已有笔记")
|
||
url = f"{BASE_URL}/{key}?json"
|
||
print(f" 请求: POST {url}")
|
||
print(f" 新内容: text={TEST_TEXT_UPDATED}")
|
||
|
||
try:
|
||
resp = requests.post(url, data={"text": TEST_TEXT_UPDATED}, timeout=TIMEOUT)
|
||
print(f" 状态码: {resp.status_code}")
|
||
print(f" 响应: {resp.text[:200]}")
|
||
|
||
if resp.status_code != 200:
|
||
return report.add("更新笔记", False, f"HTTP {resp.status_code}")
|
||
|
||
data = resp.json()
|
||
code_ok = data.get("code") == 1
|
||
report.add("更新笔记 - code=1", code_ok, f"code={data.get('code')}")
|
||
|
||
# 验证内容确实更新了
|
||
time.sleep(0.5)
|
||
read_url = f"{BASE_URL}/{key}?raw"
|
||
read_resp = requests.get(read_url, timeout=TIMEOUT)
|
||
content_updated = TEST_TEXT_UPDATED in read_resp.text
|
||
report.add("更新笔记 - 内容已覆盖", content_updated,
|
||
f"内容长度={len(read_resp.text)}")
|
||
|
||
return code_ok and content_updated
|
||
|
||
except Exception as e:
|
||
return report.add("更新笔记", False, f"异常: {e}")
|
||
|
||
|
||
# ==================== 主流程 ====================
|
||
|
||
def main():
|
||
"""主测试流程"""
|
||
print("=" * 60)
|
||
print(" CTC笔记仓库 API 接口测试")
|
||
print(f" 基础URL: {BASE_URL}")
|
||
print(f" 测试时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||
print("=" * 60)
|
||
|
||
# 检查网络连通性
|
||
print("\n[预检] 测试网络连通性...")
|
||
try:
|
||
resp = requests.get(BASE_URL, timeout=TIMEOUT, allow_redirects=True)
|
||
print(f" 连接成功 (HTTP {resp.status_code})")
|
||
except Exception as e:
|
||
print(f" ❌ 无法连接到 {BASE_URL}: {e}")
|
||
print(" 请检查网络连接后重试。")
|
||
sys.exit(1)
|
||
|
||
# 初始化测试报告
|
||
report = TestReport()
|
||
|
||
# 生成测试用钥匙
|
||
key1 = generate_random_key(8)
|
||
key2 = generate_random_key(8)
|
||
keys_to_cleanup = [key1, key2] # 需要清理的笔记列表
|
||
|
||
print(f"\n 测试钥匙1: {key1}")
|
||
print(f" 测试钥匙2: {key2}")
|
||
|
||
# ---- 执行测试 ----
|
||
|
||
# 1. 写入笔记
|
||
test_write_note(report, key1)
|
||
time.sleep(0.3)
|
||
|
||
# 2. 读取笔记
|
||
test_read_note(report, key1)
|
||
time.sleep(0.3)
|
||
|
||
# 2补充. 读取不存在的笔记
|
||
test_read_nonexistent_note(report)
|
||
time.sleep(0.3)
|
||
|
||
# 3. 获取笔记信息
|
||
test_get_note_info(report, key1)
|
||
time.sleep(0.3)
|
||
|
||
# 3补充. 获取不存在笔记的信息
|
||
test_get_nonexistent_note_info(report)
|
||
time.sleep(0.3)
|
||
|
||
# 4. 批量检查变更
|
||
test_batch_check(report, key1, key2)
|
||
time.sleep(0.3)
|
||
|
||
# 补充. 更新已有笔记
|
||
test_update_note(report, key1)
|
||
time.sleep(0.3)
|
||
|
||
# 5. 创建随机笔记
|
||
success, new_key = test_create_random_note(report)
|
||
if new_key:
|
||
keys_to_cleanup.append(new_key)
|
||
time.sleep(0.3)
|
||
|
||
# 补充. 无效钥匙格式
|
||
test_invalid_key(report)
|
||
time.sleep(0.3)
|
||
|
||
# 6补充. 删除不存在的笔记
|
||
test_delete_nonexistent_note(report)
|
||
time.sleep(0.3)
|
||
|
||
# ---- 清理测试数据 ----
|
||
print_separator("清理测试数据")
|
||
for key in keys_to_cleanup:
|
||
print(f" 正在删除笔记: {key}...", end=" ")
|
||
try:
|
||
resp = requests.get(f"{BASE_URL}/?delete¬e={key}", timeout=TIMEOUT)
|
||
data = safe_json_parse(resp)
|
||
if data.get("code") == 1:
|
||
print("✅ 已删除")
|
||
elif resp.status_code == 404:
|
||
print("⏭️ 不存在,跳过")
|
||
else:
|
||
msg = data.get("msg", resp.text[:50]) if data else resp.text[:50]
|
||
print(f"⚠️ 删除失败: {msg}")
|
||
except Exception as e:
|
||
print(f"❌ 异常: {e}")
|
||
time.sleep(0.2)
|
||
|
||
# ---- 验证清理结果 ----
|
||
print("\n[验证] 确认笔记已删除...")
|
||
verify_key = keys_to_cleanup[0]
|
||
try:
|
||
resp = requests.get(f"{BASE_URL}/{verify_key}?raw", timeout=TIMEOUT)
|
||
if resp.status_code == 404:
|
||
print(f" ✅ 笔记 {verify_key} 已确认删除 (404)")
|
||
else:
|
||
print(f" ⚠️ 笔记 {verify_key} 仍存在 (HTTP {resp.status_code})")
|
||
except Exception as e:
|
||
print(f" ❌ 验证异常: {e}")
|
||
|
||
# ---- 输出测试报告 ----
|
||
all_passed = report.summary()
|
||
|
||
# 返回退出码
|
||
sys.exit(0 if all_passed else 1)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|