新增公司资料/指数/重大事项等 13 个接口, 文档全面对齐

- 新增 fin_mda/fin_equity/fin_company/fin_belong_index/fin_major_events 5 个模块
- 覆盖: 管理层讨论、股本结构、公司介绍、所属行业、指数分类/统计/成分、并购/股权激励/诉讼/关联交易/违规/担保
- _emchoice.fetch_report 支持"数据为空"按空结果处理
- api.py 增加 _simple_endpoint 统一生成纯 stocks 参数接口, 路由达 29 个 /fin 端点
- 冒烟测试扩展至 56 用例, 全部通过
- api_manual/blueprint/SKILLS/待优化 文档与代码路径 100% 对齐
This commit is contained in:
2026-08-15 11:34:11 +08:00
parent 797369bbed
commit 2ce68b7b5d
13 changed files with 1147 additions and 11 deletions
+65 -3
View File
@@ -3,25 +3,58 @@
运行: uv run pytest tests/ -q
注意: 依赖外网可达东财接口, 网络不通时用例会失败.
"""
import inspect
import pandas as pd
import pytest
from utils.fin_balance import get_balance
from utils.fin_belong_index import get_belong_index, get_index_classif, get_index_membership
from utils.fin_capital_structure import get_capital_structure
from utils.fin_cashflow import get_cashflow
from utils.fin_company import get_company_info, get_industry
from utils.fin_dividend import get_dividend_detail, get_dividend_statics
from utils.fin_dupont import get_dupont
from utils.fin_equity import get_equity
from utils.fin_free_holders import get_free_holders
from utils.fin_growth import get_growth
from utils.fin_holder_num import get_holder_num
from utils.fin_holders import get_holders
from utils.fin_income import get_income
from utils.fin_main_business import get_main_business
from utils.fin_major_events import (
get_acquisitions,
get_equity_incentive,
get_guarantee,
get_litigation,
get_related_transaction,
get_violation,
)
from utils.fin_mda import get_mda
from utils.fin_operate import get_operate_ability
from utils.fin_profitability import get_profitability
STOCK = "603233.SH"
# 部分接口需要更多年份或其它股票才能取到数据 (否则按 1 年 + 默认股票)
CASE_OVERRIDES = {
"get_mda": {"years": 5},
"get_litigation": {"years": 3},
"get_violation": {"years": 3},
"get_equity_incentive": {"years": 5, "stock": "300750.SZ"},
"get_guarantee": {"years": 3, "stock": "300750.SZ"},
}
def _call(func, stock=STOCK):
"""按函数签名与覆盖配置调用."""
over = CASE_OVERRIDES.get(func.__name__, {})
s = over.get("stock", stock)
if "years" in inspect.signature(func).parameters:
return func([s], years=over.get("years", 1))
return func([s])
# (模块函数, 该接口应返回的关键列, 测试名)
CASES = [
pytest.param(get_main_business, "MAIN_BUSINESS_INCOME", id="main_business"),
@@ -38,13 +71,26 @@ CASES = [
pytest.param(get_free_holders, "HOLDER_NAME", id="free_holders"),
pytest.param(get_holders, "HOLDER_NAME", id="holders"),
pytest.param(get_holder_num, "HOLDER_TOTAL_NUM", id="holder_num"),
pytest.param(get_mda, "REPORT_NAME", id="mda"),
pytest.param(get_equity, "TOTAL_SHARES", id="equity"),
pytest.param(get_company_info, "ORG_NAME", id="company_info"),
pytest.param(get_industry, "INDUSTRY_NAME", id="industry"),
pytest.param(get_index_classif, "INDEX_CLASSIF", id="index_classif"),
pytest.param(get_belong_index, "INDEX_NUM", id="belong_index"),
pytest.param(get_index_membership, "INDEX_NAME_ABBR", id="index_membership"),
pytest.param(get_acquisitions, "PLAN_PROCESS", id="acquisitions"),
pytest.param(get_equity_incentive, "PLAN_PROCESS", id="equity_incentive"),
pytest.param(get_litigation, "CASE_NAME", id="litigation"),
pytest.param(get_related_transaction, "RELATED_PARTY", id="related_transaction"),
pytest.param(get_violation, "VIOLATE_TYPE", id="violation"),
pytest.param(get_guarantee, "GUAR_NAME", id="guarantee"),
]
@pytest.mark.parametrize("func,key_col", CASES)
def test_fetch_data(func, key_col):
"""拉 1 年数据, 应返回非空 DataFrame 且含关键列."""
df = func([STOCK], years=1)
"""拉数据, 应返回非空 DataFrame 且含关键列."""
df = _call(func)
assert isinstance(df, pd.DataFrame)
assert not df.empty, f"{func.__name__} 未返回数据"
assert "SECUCODE" in df.columns, f"{func.__name__} 缺少 SECUCODE 列"
@@ -54,7 +100,10 @@ def test_fetch_data(func, key_col):
@pytest.mark.parametrize("func,_key_col", CASES)
def test_empty_codes(func, _key_col):
"""空代码列表应返回空 DataFrame, 不抛异常."""
df = func([], years=1)
if "years" in inspect.signature(func).parameters:
df = func([], years=1)
else:
df = func([])
assert isinstance(df, pd.DataFrame)
assert df.empty
@@ -89,5 +138,18 @@ def test_api_routes():
"/fin/free-holders",
"/fin/holders",
"/fin/holder-num",
"/fin/mda",
"/fin/equity",
"/fin/company-info",
"/fin/industry",
"/fin/index-classif",
"/fin/belong-index",
"/fin/index-membership",
"/fin/acquisitions",
"/fin/equity-incentive",
"/fin/litigation",
"/fin/related-transaction",
"/fin/violation",
"/fin/guarantee",
]:
assert route in paths, f"缺少路由 {route}"