2026-02-23 16:23:53 +08:00
|
|
|
|
"""Sync 接口测试规范与实现。
|
|
|
|
|
|
|
|
|
|
|
|
【测试规范】
|
|
|
|
|
|
1. 所有 sync 测试只使用 2018-01-01 到 2018-04-01 的数据
|
|
|
|
|
|
2. 只测试接口是否能正常返回数据,不测试落库逻辑
|
|
|
|
|
|
3. 对于按股票查询的接口,只测试 000001.SZ、000002.SZ 两支股票
|
|
|
|
|
|
4. 使用真实 API 调用,确保接口可用性
|
|
|
|
|
|
|
|
|
|
|
|
【测试范围】
|
|
|
|
|
|
- get_daily: 日线数据接口(按股票)
|
|
|
|
|
|
- sync_all_stocks: 股票基础信息接口
|
|
|
|
|
|
- sync_trade_cal_cache: 交易日历接口
|
|
|
|
|
|
- sync_namechange: 名称变更接口
|
|
|
|
|
|
- sync_bak_basic: 备用股票基础信息接口
|
2026-02-01 02:29:54 +08:00
|
|
|
|
"""
|
2026-02-21 03:43:30 +08:00
|
|
|
|
|
2026-02-01 02:29:54 +08:00
|
|
|
|
import pytest
|
|
|
|
|
|
import pandas as pd
|
2026-02-23 16:23:53 +08:00
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
|
# 测试用常量
|
|
|
|
|
|
TEST_START_DATE = "20180101"
|
|
|
|
|
|
TEST_END_DATE = "20180401"
|
|
|
|
|
|
TEST_STOCK_CODES = ["000001.SZ", "000002.SZ"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestGetDaily:
|
|
|
|
|
|
"""测试日线数据 get 接口(按股票查询)."""
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_daily_single_stock(self):
|
|
|
|
|
|
"""测试 get_daily 获取单只股票数据."""
|
|
|
|
|
|
from src.data.api_wrappers.api_daily import get_daily
|
|
|
|
|
|
|
|
|
|
|
|
result = get_daily(
|
|
|
|
|
|
ts_code=TEST_STOCK_CODES[0],
|
|
|
|
|
|
start_date=TEST_START_DATE,
|
|
|
|
|
|
end_date=TEST_END_DATE,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 验证返回了数据
|
|
|
|
|
|
assert isinstance(result, pd.DataFrame), "get_daily 应返回 DataFrame"
|
|
|
|
|
|
assert not result.empty, "get_daily 应返回非空数据"
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_daily_has_required_columns(self):
|
|
|
|
|
|
"""测试 get_daily 返回的数据包含必要字段."""
|
|
|
|
|
|
from src.data.api_wrappers.api_daily import get_daily
|
|
|
|
|
|
|
|
|
|
|
|
result = get_daily(
|
|
|
|
|
|
ts_code=TEST_STOCK_CODES[0],
|
|
|
|
|
|
start_date=TEST_START_DATE,
|
|
|
|
|
|
end_date=TEST_END_DATE,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 验证必要的列存在
|
|
|
|
|
|
required_columns = ["ts_code", "trade_date", "open", "high", "low", "close"]
|
|
|
|
|
|
for col in required_columns:
|
|
|
|
|
|
assert col in result.columns, f"get_daily 返回应包含 {col} 列"
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_daily_multiple_stocks(self):
|
|
|
|
|
|
"""测试 get_daily 获取多只股票数据."""
|
|
|
|
|
|
from src.data.api_wrappers.api_daily import get_daily
|
|
|
|
|
|
|
|
|
|
|
|
results = {}
|
|
|
|
|
|
for code in TEST_STOCK_CODES:
|
|
|
|
|
|
result = get_daily(
|
|
|
|
|
|
ts_code=code,
|
|
|
|
|
|
start_date=TEST_START_DATE,
|
|
|
|
|
|
end_date=TEST_END_DATE,
|
|
|
|
|
|
)
|
|
|
|
|
|
results[code] = result
|
|
|
|
|
|
assert isinstance(result, pd.DataFrame), (
|
|
|
|
|
|
f"get_daily({code}) 应返回 DataFrame"
|
2026-02-21 03:43:30 +08:00
|
|
|
|
)
|
2026-02-23 16:23:53 +08:00
|
|
|
|
assert not result.empty, f"get_daily({code}) 应返回非空数据"
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
class TestSyncStockBasic:
|
|
|
|
|
|
"""测试股票基础信息 sync 接口."""
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
def test_sync_all_stocks_returns_data(self):
|
|
|
|
|
|
"""测试 sync_all_stocks 是否能正常返回数据."""
|
|
|
|
|
|
from src.data.api_wrappers.api_stock_basic import sync_all_stocks
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
result = sync_all_stocks()
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
# 验证返回了数据
|
|
|
|
|
|
assert isinstance(result, pd.DataFrame), "sync_all_stocks 应返回 DataFrame"
|
|
|
|
|
|
assert not result.empty, "sync_all_stocks 应返回非空数据"
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
def test_sync_all_stocks_has_required_columns(self):
|
|
|
|
|
|
"""测试 sync_all_stocks 返回的数据包含必要字段."""
|
|
|
|
|
|
from src.data.api_wrappers.api_stock_basic import sync_all_stocks
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
result = sync_all_stocks()
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
# 验证必要的列存在
|
|
|
|
|
|
required_columns = ["ts_code"]
|
|
|
|
|
|
for col in required_columns:
|
|
|
|
|
|
assert col in result.columns, f"sync_all_stocks 返回应包含 {col} 列"
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
class TestSyncTradeCal:
|
|
|
|
|
|
"""测试交易日历 sync 接口."""
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
def test_sync_trade_cal_cache_returns_data(self):
|
|
|
|
|
|
"""测试 sync_trade_cal_cache 是否能正常返回数据."""
|
|
|
|
|
|
from src.data.api_wrappers.api_trade_cal import sync_trade_cal_cache
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
result = sync_trade_cal_cache(
|
|
|
|
|
|
start_date=TEST_START_DATE,
|
|
|
|
|
|
end_date=TEST_END_DATE,
|
|
|
|
|
|
)
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
# 验证返回了数据
|
|
|
|
|
|
assert isinstance(result, pd.DataFrame), "sync_trade_cal_cache 应返回 DataFrame"
|
|
|
|
|
|
assert not result.empty, "sync_trade_cal_cache 应返回非空数据"
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
def test_sync_trade_cal_cache_has_required_columns(self):
|
|
|
|
|
|
"""测试 sync_trade_cal_cache 返回的数据包含必要字段."""
|
|
|
|
|
|
from src.data.api_wrappers.api_trade_cal import sync_trade_cal_cache
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
result = sync_trade_cal_cache(
|
|
|
|
|
|
start_date=TEST_START_DATE,
|
|
|
|
|
|
end_date=TEST_END_DATE,
|
|
|
|
|
|
)
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
# 验证必要的列存在
|
|
|
|
|
|
required_columns = ["cal_date", "is_open"]
|
|
|
|
|
|
for col in required_columns:
|
|
|
|
|
|
assert col in result.columns, f"sync_trade_cal_cache 返回应包含 {col} 列"
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
class TestSyncNamechange:
|
|
|
|
|
|
"""测试名称变更 sync 接口."""
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
def test_sync_namechange_returns_data(self):
|
|
|
|
|
|
"""测试 sync_namechange 是否能正常返回数据."""
|
|
|
|
|
|
from src.data.api_wrappers.api_namechange import sync_namechange
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
2026-02-23 16:23:53 +08:00
|
|
|
|
result = sync_namechange()
|
|
|
|
|
|
|
|
|
|
|
|
# 验证返回了数据(可能是空 DataFrame,因为是历史变更)
|
|
|
|
|
|
assert isinstance(result, pd.DataFrame), "sync_namechange 应返回 DataFrame"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestSyncBakBasic:
|
|
|
|
|
|
"""测试备用股票基础信息 sync 接口."""
|
|
|
|
|
|
|
|
|
|
|
|
def test_sync_bak_basic_returns_data(self):
|
|
|
|
|
|
"""测试 sync_bak_basic 是否能正常返回数据."""
|
|
|
|
|
|
from src.data.api_wrappers.api_bak_basic import sync_bak_basic
|
|
|
|
|
|
|
|
|
|
|
|
result = sync_bak_basic(
|
|
|
|
|
|
start_date=TEST_START_DATE,
|
|
|
|
|
|
end_date=TEST_END_DATE,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 验证返回了数据
|
|
|
|
|
|
assert isinstance(result, pd.DataFrame), "sync_bak_basic 应返回 DataFrame"
|
|
|
|
|
|
# 注意:bak_basic 可能返回空数据,这是正常的
|
2026-02-01 02:29:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-02-21 03:43:30 +08:00
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
pytest.main([__file__, "-v"])
|