task2-phase1: 基础框架搭建
This commit is contained in:
parent
8b9a96118a
commit
bf4f346096
13
config/config_task2.ini
Normal file
13
config/config_task2.ini
Normal file
@ -0,0 +1,13 @@
|
||||
# 任务二配置文件:TAPD状态实时同步至腾讯智能表格
|
||||
|
||||
[TAPD]
|
||||
# TAPD项目ID
|
||||
workspace_id = 58335167
|
||||
|
||||
[SmartSheet]
|
||||
# 智能表格文档ID(任务二专用)
|
||||
docid = your_task2_doc_id
|
||||
|
||||
[Schedule]
|
||||
# 同步频率(分钟)
|
||||
sync_interval = 15
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"access_token": "SPFfB9jMxleGiJn76FQH6v5pploseAJXTCVkTVVxl1_PEmHZJiqXsNGpEyGAK4qmYe3WRxYJ57xgCQLRCHopVfeoDfP87IgxVCytCqQABGES5ndG05SVkrI-9evg8Z4kbstlsiRMmfPGGGoNUgL1kUoZc2No0FYytm8FTfulnAXfiTExzoF8OCTdEPc9mA0g8JKFhlkiS2F0agBESS_2_ewbcZvA0i44-ChTKRBdRa0",
|
||||
"fetch_time": 1767599732.4166858
|
||||
"access_token": "1vVdzrLNZahtARUianAypD-WjGnSvHzU9_p0vXE2wmawFj3WigMA-eZZ1W-t0Tki2KWIs_yYrcrTAInDngJcS-_uqupCNlgEYUjL1bMeS2GGnNM1e3spBT9XdUjF8yTvP3XXtwrlY_qS9Se2S09GQEk1VLxnou1okTjmnzdaNQJbTg013-R_uUp3E-CyNFy7t1tQHN87tr9l2GzlzGt6EshjNcJq4COuCgbs5wBA298",
|
||||
"fetch_time": 1767787715.7755494
|
||||
}
|
||||
15
logs2/api_log_2026-01-07.json
Normal file
15
logs2/api_log_2026-01-07.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"records": [],
|
||||
{
|
||||
"api_type": "test",
|
||||
"operation": "task2/setup_test",
|
||||
"timestamp": "2026-01-07 20:14:18",
|
||||
"success": true,
|
||||
"request": {
|
||||
"test": "验证脚本测试"
|
||||
},
|
||||
"response": {
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
]}
|
||||
333
src/api_test.py
333
src/api_test.py
@ -22,7 +22,13 @@ from src.config import ConfigManager
|
||||
class WeWorkAPITester:
|
||||
"""企业微信API测试类"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, auto_load_token=True):
|
||||
"""
|
||||
初始化企业微信API测试类
|
||||
|
||||
Args:
|
||||
auto_load_token: 是否自动加载token,默认为True
|
||||
"""
|
||||
self.access_token = None
|
||||
self.log_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs', 'api_test_log.json')
|
||||
self.base_url = "https://qyapi.weixin.qq.com/cgi-bin"
|
||||
@ -30,12 +36,92 @@ class WeWorkAPITester:
|
||||
# 确保日志文件存在
|
||||
self._init_log_file()
|
||||
|
||||
# 自动加载token
|
||||
if auto_load_token:
|
||||
self._auto_load_token()
|
||||
|
||||
def _init_log_file(self):
|
||||
"""初始化日志文件"""
|
||||
if not os.path.exists(self.log_file):
|
||||
with open(self.log_file, 'w', encoding='utf-8') as f:
|
||||
json.dump({"records": []}, f, ensure_ascii=False, indent=2)
|
||||
|
||||
def _auto_load_token(self):
|
||||
"""
|
||||
自动加载access_token
|
||||
|
||||
优先从缓存读取,如果缓存不存在或已过期,则尝试从API获取新token
|
||||
"""
|
||||
print("\n=== 自动加载access_token ===")
|
||||
|
||||
# 先尝试从缓存读取
|
||||
if self._load_token_from_cache_silent():
|
||||
return
|
||||
|
||||
# 缓存无效,尝试从API获取
|
||||
print(" 尝试从API获取新token...")
|
||||
try:
|
||||
from src.token_manager import TokenManager
|
||||
token_manager = TokenManager()
|
||||
self.access_token = token_manager.get_token()
|
||||
print(f" ✓ 成功获取access_token")
|
||||
print(f" Token: {self.access_token[:20]}...")
|
||||
except ValueError as e:
|
||||
print(f" ⚠ 环境变量未配置: {e}")
|
||||
print(" 请手动选择菜单选项1获取token")
|
||||
except Exception as e:
|
||||
print(f" ⚠ 自动获取token失败: {e}")
|
||||
print(" 请手动选择菜单选项1获取token")
|
||||
|
||||
def _load_token_from_cache_silent(self):
|
||||
"""
|
||||
静默从缓存读取token(不打印标题)
|
||||
|
||||
Returns:
|
||||
bool: 是否成功读取有效token
|
||||
"""
|
||||
cache_file = os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)),
|
||||
'config',
|
||||
'token_cache.json'
|
||||
)
|
||||
|
||||
try:
|
||||
if not os.path.exists(cache_file):
|
||||
print(" 缓存文件不存在")
|
||||
return False
|
||||
|
||||
with open(cache_file, 'r', encoding='utf-8') as f:
|
||||
cache_data = json.load(f)
|
||||
|
||||
access_token = cache_data.get('access_token')
|
||||
fetch_time = cache_data.get('fetch_time')
|
||||
|
||||
if not access_token:
|
||||
print(" 缓存文件中没有access_token")
|
||||
return False
|
||||
|
||||
# 检查token是否过期(7200秒 = 2小时,提前5分钟刷新)
|
||||
import time
|
||||
current_time = time.time()
|
||||
elapsed_time = current_time - fetch_time
|
||||
remaining_time = 7200 - elapsed_time
|
||||
|
||||
if remaining_time <= 300: # 剩余不足5分钟视为过期
|
||||
print(f" 缓存的token已过期或即将过期")
|
||||
return False
|
||||
|
||||
# token有效
|
||||
self.access_token = access_token
|
||||
print(f" ✓ 从缓存读取access_token成功")
|
||||
print(f" Token: {self.access_token[:20]}...")
|
||||
print(f" 剩余有效期: {int(remaining_time)}秒 ({int(remaining_time//60)}分钟)")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f" 读取缓存失败: {e}")
|
||||
return False
|
||||
|
||||
def _log_api_call(self, operation, request_data, response_data):
|
||||
"""记录API调用到JSON文件"""
|
||||
try:
|
||||
@ -481,6 +567,110 @@ class TAPDAPITester:
|
||||
except Exception as e:
|
||||
print(f"✗ 记录日志失败: {str(e)}")
|
||||
|
||||
def get_story_fields_info(self):
|
||||
"""
|
||||
获取TAPD需求的所有字段配置及候选值
|
||||
|
||||
Returns:
|
||||
dict: 字段配置信息,失败返回None
|
||||
"""
|
||||
print("\n=== 获取TAPD需求字段配置 ===")
|
||||
|
||||
# 初始化认证信息
|
||||
if not self._init_auth():
|
||||
return None
|
||||
|
||||
# 初始化workspace_id
|
||||
if not self._init_workspace_id():
|
||||
return None
|
||||
|
||||
url = f"{self.base_url}/stories/get_fields_info"
|
||||
params = {
|
||||
"workspace_id": self.workspace_id
|
||||
}
|
||||
|
||||
try:
|
||||
from requests.auth import HTTPBasicAuth
|
||||
auth = HTTPBasicAuth(self.api_user, self.api_password)
|
||||
|
||||
print(f"\n正在请求TAPD API...")
|
||||
print(f" URL: {url}")
|
||||
print(f" workspace_id: {self.workspace_id}")
|
||||
|
||||
response = requests.get(url, params=params, auth=auth, timeout=30)
|
||||
response_data = response.json()
|
||||
|
||||
# 记录API调用
|
||||
request_data = {
|
||||
"url": url,
|
||||
"method": "GET",
|
||||
"params": params,
|
||||
"auth_user": self.api_user
|
||||
}
|
||||
self._log_api_call("get_story_fields_info", request_data, response_data)
|
||||
|
||||
# 检查返回结果
|
||||
if response_data.get("status") == 1:
|
||||
data = response_data.get("data", {})
|
||||
print(f"\n✓ 成功获取需求字段配置")
|
||||
|
||||
# 显示字段统计
|
||||
if isinstance(data, dict):
|
||||
field_count = len(data)
|
||||
print(f" 共 {field_count} 个字段配置")
|
||||
|
||||
# 保存到单独的文件
|
||||
output_file = os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)),
|
||||
'logs',
|
||||
'tapd_story_fields.json'
|
||||
)
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
print(f" ✓ 字段配置已保存到: {output_file}")
|
||||
|
||||
# 显示部分字段信息
|
||||
print(f"\n需求字段列表预览:")
|
||||
print("-" * 80)
|
||||
for idx, (field_name, field_info) in enumerate(list(data.items())[:10], 1):
|
||||
field_label = field_info.get('label', '(无标签)')
|
||||
html_type = field_info.get('html_type', '(未知类型)')
|
||||
print(f" {idx}. {field_name} ({field_label}) - 类型: {html_type}")
|
||||
|
||||
# 如果有候选值,显示
|
||||
options = field_info.get('options', [])
|
||||
if options:
|
||||
if isinstance(options, dict):
|
||||
option_list = list(options.values())[:5]
|
||||
total_count = len(options)
|
||||
elif isinstance(options, list):
|
||||
option_list = options[:5]
|
||||
total_count = len(options)
|
||||
else:
|
||||
option_list = []
|
||||
total_count = 0
|
||||
|
||||
if option_list:
|
||||
print(f" 候选值: {', '.join(str(o) for o in option_list)}" +
|
||||
(f" ...等{total_count}个" if total_count > 5 else ""))
|
||||
|
||||
if field_count > 10:
|
||||
print(f" ... 还有 {field_count - 10} 个字段,详见输出文件")
|
||||
print("-" * 80)
|
||||
|
||||
return data
|
||||
else:
|
||||
print(f"\n✗ 获取失败")
|
||||
print(f" 状态码: {response_data.get('status')}")
|
||||
print(f" 错误信息: {response_data.get('info', '未知错误')}")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ 请求异常: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def get_bug_custom_fields(self):
|
||||
"""
|
||||
获取TAPD缺陷的所有字段配置及候选值
|
||||
@ -586,6 +776,121 @@ class TAPDAPITester:
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def get_story(self, story_id):
|
||||
"""
|
||||
根据需求ID获取需求详情
|
||||
|
||||
Args:
|
||||
story_id: 需求ID
|
||||
|
||||
Returns:
|
||||
dict: 需求信息,失败返回None
|
||||
"""
|
||||
print("\n=== 获取TAPD需求 ===")
|
||||
|
||||
# 初始化认证信息
|
||||
if not self._init_auth():
|
||||
return None
|
||||
|
||||
# 初始化workspace_id
|
||||
if not self._init_workspace_id():
|
||||
return None
|
||||
|
||||
# 验证story_id
|
||||
if not story_id:
|
||||
print("✗ 需求ID不能为空")
|
||||
return None
|
||||
|
||||
url = f"{self.base_url}/stories"
|
||||
params = {
|
||||
"workspace_id": self.workspace_id,
|
||||
"id": story_id
|
||||
}
|
||||
|
||||
try:
|
||||
from requests.auth import HTTPBasicAuth
|
||||
auth = HTTPBasicAuth(self.api_user, self.api_password)
|
||||
|
||||
print(f"\n正在请求TAPD API...")
|
||||
print(f" URL: {url}")
|
||||
print(f" workspace_id: {self.workspace_id}")
|
||||
print(f" story_id: {story_id}")
|
||||
|
||||
response = requests.get(url, params=params, auth=auth, timeout=30)
|
||||
response_data = response.json()
|
||||
|
||||
# 记录API调用
|
||||
request_data = {
|
||||
"url": url,
|
||||
"method": "GET",
|
||||
"params": params,
|
||||
"auth_user": self.api_user
|
||||
}
|
||||
self._log_api_call("get_story", request_data, response_data)
|
||||
|
||||
# 检查返回结果
|
||||
if response_data.get("status") == 1:
|
||||
data = response_data.get("data", [])
|
||||
|
||||
if not data:
|
||||
print(f"\n✗ 未找到需求ID为 {story_id} 的需求")
|
||||
return None
|
||||
|
||||
# TAPD返回的是列表,取第一个
|
||||
story_data = data[0] if isinstance(data, list) else data
|
||||
story_info = story_data.get("Story", {})
|
||||
|
||||
print(f"\n✓ 成功获取需求信息")
|
||||
print(f"\n需求详情:")
|
||||
print("=" * 80)
|
||||
|
||||
# 显示关键字段
|
||||
key_fields = [
|
||||
("id", "ID"),
|
||||
("name", "标题"),
|
||||
("status", "状态"),
|
||||
("priority", "优先级"),
|
||||
("owner", "处理人"),
|
||||
("creator", "创建人"),
|
||||
("created", "创建时间"),
|
||||
("modified", "最后修改时间"),
|
||||
("iteration_id", "迭代ID"),
|
||||
("description", "详细描述")
|
||||
]
|
||||
|
||||
for field_name, field_label in key_fields:
|
||||
value = story_info.get(field_name, '')
|
||||
if field_name == "description" and value:
|
||||
# 描述字段可能很长,只显示前100个字符
|
||||
if len(str(value)) > 100:
|
||||
value = str(value)[:100] + "..."
|
||||
print(f" {field_label}: {value}")
|
||||
|
||||
print("=" * 80)
|
||||
|
||||
# 保存完整数据到文件
|
||||
output_file = os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)),
|
||||
'logs',
|
||||
f'tapd_story_{story_id}.json'
|
||||
)
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(story_info, f, ensure_ascii=False, indent=2)
|
||||
print(f"\n✓ 完整需求信息已保存到: {output_file}")
|
||||
|
||||
return story_info
|
||||
else:
|
||||
print(f"\n✗ 获取失败")
|
||||
print(f" 状态码: {response_data.get('status')}")
|
||||
print(f" 错误信息: {response_data.get('info', '未知错误')}")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ 请求异常: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def upload_attachment(self, file_path, entry_type, entry_id, owner=None, overwrite=False):
|
||||
"""
|
||||
上传附件到TAPD
|
||||
@ -927,10 +1232,12 @@ def print_menu():
|
||||
print("5. 发送应用消息")
|
||||
print("\n【TAPD API】")
|
||||
print("6. 获取缺陷字段配置")
|
||||
print("7. 获取附件列表")
|
||||
print("8. 上传附件")
|
||||
print("7. 获取需求字段配置")
|
||||
print("8. 获取需求")
|
||||
print("9. 获取附件列表")
|
||||
print("10. 上传附件")
|
||||
print("\n【其他】")
|
||||
print("9. 查看日志文件")
|
||||
print("11. 查看日志文件")
|
||||
print("0. 退出")
|
||||
print("="*50)
|
||||
|
||||
@ -942,7 +1249,7 @@ def main():
|
||||
|
||||
while True:
|
||||
print_menu()
|
||||
choice = input("\n请选择操作 (0-9): ").strip()
|
||||
choice = input("\n请选择操作 (0-11): ").strip()
|
||||
|
||||
if choice == "0":
|
||||
print("\n感谢使用,再见!")
|
||||
@ -1018,6 +1325,18 @@ def main():
|
||||
tapd_tester.get_bug_custom_fields()
|
||||
|
||||
elif choice == "7":
|
||||
# 获取TAPD需求字段配置
|
||||
tapd_tester.get_story_fields_info()
|
||||
|
||||
elif choice == "8":
|
||||
# 获取TAPD需求
|
||||
story_id = input("\n请输入需求ID: ").strip()
|
||||
if not story_id:
|
||||
print("✗ 需求ID不能为空")
|
||||
continue
|
||||
tapd_tester.get_story(story_id)
|
||||
|
||||
elif choice == "9":
|
||||
# 获取TAPD附件列表
|
||||
print("\n=== 获取附件列表 ===")
|
||||
print("是否需要添加筛选条件?")
|
||||
@ -1055,7 +1374,7 @@ def main():
|
||||
limit=limit
|
||||
)
|
||||
|
||||
elif choice == "8":
|
||||
elif choice == "10":
|
||||
# 上传附件到TAPD
|
||||
print("\n=== 上传附件 ===")
|
||||
file_path = input("请输入文件路径: ").strip()
|
||||
@ -1099,7 +1418,7 @@ def main():
|
||||
overwrite=overwrite
|
||||
)
|
||||
|
||||
elif choice == "9":
|
||||
elif choice == "11":
|
||||
print("\n=== 查看日志文件 ===")
|
||||
try:
|
||||
with open(wework_tester.log_file, 'r', encoding='utf-8') as f:
|
||||
|
||||
3
src2/__init__.py
Normal file
3
src2/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
"""
|
||||
任务二:TAPD状态实时同步至腾讯智能表格
|
||||
"""
|
||||
119
src2/config.py
Normal file
119
src2/config.py
Normal file
@ -0,0 +1,119 @@
|
||||
"""
|
||||
任务二配置管理模块
|
||||
复用任务一的ConfigManager,读取任务二专用配置文件
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 将项目根目录添加到 Python 路径,以便导入 src 模块
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from src.config import ConfigManager as BaseConfigManager
|
||||
|
||||
|
||||
class Task2ConfigManager(BaseConfigManager):
|
||||
"""任务二配置管理器,继承自任务一的ConfigManager"""
|
||||
|
||||
def __init__(self, config_path=None):
|
||||
"""
|
||||
初始化任务二配置管理器
|
||||
|
||||
Args:
|
||||
config_path: 配置文件路径,如果为None则使用任务二默认路径
|
||||
"""
|
||||
if config_path is None:
|
||||
# 默认路径:项目根目录/config/config_task2.ini
|
||||
config_path = project_root / "config" / "config_task2.ini"
|
||||
|
||||
super().__init__(config_path)
|
||||
|
||||
def get_tapd_config(self):
|
||||
"""
|
||||
获取TAPD配置(任务二版本,不需要reporter)
|
||||
|
||||
Returns:
|
||||
dict: 包含workspace_id的字典
|
||||
"""
|
||||
if not self.config.has_section('TAPD'):
|
||||
raise ValueError("配置文件缺少[TAPD]节")
|
||||
|
||||
if not self.config.has_option('TAPD', 'workspace_id'):
|
||||
raise ValueError("配置文件[TAPD]节缺少workspace_id配置项")
|
||||
|
||||
workspace_id = self.config.get('TAPD', 'workspace_id').strip()
|
||||
if not workspace_id:
|
||||
raise ValueError("workspace_id配置项不能为空")
|
||||
|
||||
return {
|
||||
'workspace_id': workspace_id
|
||||
}
|
||||
|
||||
def get_schedule_config(self):
|
||||
"""
|
||||
获取调度配置(任务二版本,只需要sync_interval)
|
||||
|
||||
Returns:
|
||||
dict: 包含sync_interval的字典
|
||||
"""
|
||||
default_sync_interval = 15
|
||||
|
||||
if not self.config.has_section('Schedule'):
|
||||
return {'sync_interval': default_sync_interval}
|
||||
|
||||
if not self.config.has_option('Schedule', 'sync_interval'):
|
||||
return {'sync_interval': default_sync_interval}
|
||||
|
||||
sync_interval_str = self.config.get('Schedule', 'sync_interval').strip()
|
||||
try:
|
||||
sync_interval = int(sync_interval_str)
|
||||
except ValueError:
|
||||
raise ValueError(f"sync_interval必须为整数,当前值: {sync_interval_str}")
|
||||
|
||||
if sync_interval <= 0:
|
||||
raise ValueError(f"sync_interval必须为正整数,当前值: {sync_interval}")
|
||||
|
||||
return {'sync_interval': sync_interval}
|
||||
|
||||
def get_all_config(self):
|
||||
"""获取所有配置"""
|
||||
return {
|
||||
'tapd': self.get_tapd_config(),
|
||||
'smartsheet': self.get_smartsheet_config(),
|
||||
'schedule': self.get_schedule_config()
|
||||
}
|
||||
|
||||
def print_config(self):
|
||||
"""打印当前配置信息"""
|
||||
print("\n=== 任务二配置信息 ===")
|
||||
try:
|
||||
tapd_config = self.get_tapd_config()
|
||||
print(f"[TAPD]")
|
||||
print(f" workspace_id: {tapd_config['workspace_id']}")
|
||||
except ValueError as e:
|
||||
print(f"[TAPD] 配置错误: {e}")
|
||||
|
||||
try:
|
||||
smartsheet_config = self.get_smartsheet_config()
|
||||
print(f"[SmartSheet]")
|
||||
print(f" docid: {smartsheet_config['docid']}")
|
||||
except ValueError as e:
|
||||
print(f"[SmartSheet] 配置错误: {e}")
|
||||
|
||||
try:
|
||||
schedule_config = self.get_schedule_config()
|
||||
print(f"[Schedule]")
|
||||
print(f" sync_interval: {schedule_config['sync_interval']} 分钟")
|
||||
except ValueError as e:
|
||||
print(f"[Schedule] 配置错误: {e}")
|
||||
|
||||
print("======================\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
config = Task2ConfigManager()
|
||||
config.print_config()
|
||||
except Exception as e:
|
||||
print(f"错误: {e}")
|
||||
56
src2/logger.py
Normal file
56
src2/logger.py
Normal file
@ -0,0 +1,56 @@
|
||||
"""
|
||||
任务二日志模块
|
||||
创建独立的 APILogger 实例,日志写入 logs2/ 目录
|
||||
|
||||
设计说明:
|
||||
- 不修改 src/api_logger.py 的 get_logger() 全局单例
|
||||
- 任务二使用独立的 logger 实例,避免与任务一冲突
|
||||
- 两个任务可以同时运行,日志互不干扰
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 将项目根目录添加到 Python 路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from src.api_logger import APILogger
|
||||
|
||||
# 任务二日志目录
|
||||
TASK2_LOG_DIR = project_root / "logs2"
|
||||
|
||||
# 任务二专用的 logger 实例(模块级单例)
|
||||
_task2_logger = None
|
||||
|
||||
|
||||
def get_task2_logger() -> APILogger:
|
||||
"""
|
||||
获取任务二专用的日志记录器
|
||||
|
||||
Returns:
|
||||
APILogger: 任务二专用的日志记录器实例
|
||||
"""
|
||||
global _task2_logger
|
||||
if _task2_logger is None:
|
||||
_task2_logger = APILogger(log_dir=str(TASK2_LOG_DIR))
|
||||
return _task2_logger
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=== 任务二日志模块测试 ===\n")
|
||||
|
||||
logger = get_task2_logger()
|
||||
|
||||
# 测试记录一条日志
|
||||
logger.log_api_call(
|
||||
api_type="test",
|
||||
operation="task2/test_log",
|
||||
request_data={"test": "任务二日志测试"},
|
||||
response_data={"status": "ok"},
|
||||
success=True
|
||||
)
|
||||
|
||||
print(f"日志目录: {TASK2_LOG_DIR}")
|
||||
print(f"日志文件: {logger._get_today_log_file()}")
|
||||
print("\n测试完成,请检查 logs2/ 目录")
|
||||
220
src2/test_setup.py
Normal file
220
src2/test_setup.py
Normal file
@ -0,0 +1,220 @@
|
||||
"""
|
||||
任务二第一阶段验证脚本
|
||||
验证基础框架搭建是否正确
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# 将项目根目录添加到 Python 路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
|
||||
def test_directory_structure():
|
||||
"""测试1: 验证目录结构"""
|
||||
print("=" * 50)
|
||||
print("测试1: 验证目录结构")
|
||||
print("=" * 50)
|
||||
|
||||
src2_dir = project_root / "src2"
|
||||
logs2_dir = project_root / "logs2"
|
||||
config_file = project_root / "config" / "config_task2.ini"
|
||||
|
||||
results = []
|
||||
|
||||
# 检查 src2 目录
|
||||
if src2_dir.exists() and src2_dir.is_dir():
|
||||
print(f" [OK] src2/ 目录存在")
|
||||
results.append(True)
|
||||
else:
|
||||
print(f" [FAIL] src2/ 目录不存在")
|
||||
results.append(False)
|
||||
|
||||
# 检查 logs2 目录
|
||||
if logs2_dir.exists() and logs2_dir.is_dir():
|
||||
print(f" [OK] logs2/ 目录存在")
|
||||
results.append(True)
|
||||
else:
|
||||
print(f" [FAIL] logs2/ 目录不存在")
|
||||
results.append(False)
|
||||
|
||||
# 检查配置文件
|
||||
if config_file.exists():
|
||||
print(f" [OK] config/config_task2.ini 存在")
|
||||
results.append(True)
|
||||
else:
|
||||
print(f" [FAIL] config/config_task2.ini 不存在")
|
||||
results.append(False)
|
||||
|
||||
return all(results)
|
||||
|
||||
|
||||
def test_config_read():
|
||||
"""测试2: 验证配置文件读取"""
|
||||
print("\n" + "=" * 50)
|
||||
print("测试2: 验证配置文件读取")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
from src2.config import Task2ConfigManager
|
||||
config = Task2ConfigManager()
|
||||
|
||||
# 读取TAPD配置
|
||||
tapd_config = config.get_tapd_config()
|
||||
print(f" [OK] TAPD配置读取成功")
|
||||
print(f" workspace_id: {tapd_config['workspace_id']}")
|
||||
|
||||
# 读取SmartSheet配置
|
||||
smartsheet_config = config.get_smartsheet_config()
|
||||
print(f" [OK] SmartSheet配置读取成功")
|
||||
print(f" docid: {smartsheet_config['docid']}")
|
||||
|
||||
# 读取Schedule配置
|
||||
schedule_config = config.get_schedule_config()
|
||||
print(f" [OK] Schedule配置读取成功")
|
||||
print(f" sync_interval: {schedule_config['sync_interval']} 分钟")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" [FAIL] 配置读取失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_logger():
|
||||
"""测试3: 验证日志写入"""
|
||||
print("\n" + "=" * 50)
|
||||
print("测试3: 验证日志写入到 logs2/")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
from src2.logger import get_task2_logger, TASK2_LOG_DIR
|
||||
|
||||
logger = get_task2_logger()
|
||||
|
||||
# 写入测试日志
|
||||
logger.log_api_call(
|
||||
api_type="test",
|
||||
operation="task2/setup_test",
|
||||
request_data={"test": "验证脚本测试"},
|
||||
response_data={"status": "success"},
|
||||
success=True
|
||||
)
|
||||
|
||||
# 检查日志文件是否创建
|
||||
log_file = logger._get_today_log_file()
|
||||
if log_file.exists():
|
||||
print(f" [OK] 日志写入成功")
|
||||
print(f" 日志目录: {TASK2_LOG_DIR}")
|
||||
print(f" 日志文件: {log_file.name}")
|
||||
return True
|
||||
else:
|
||||
print(f" [FAIL] 日志文件未创建")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f" [FAIL] 日志测试失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_token_manager():
|
||||
"""测试4: 验证Token管理器复用"""
|
||||
print("\n" + "=" * 50)
|
||||
print("测试4: 验证Token管理器复用")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
from src.token_manager import TokenManager
|
||||
|
||||
# 创建TokenManager实例(使用默认缓存路径)
|
||||
token_manager = TokenManager()
|
||||
print(f" [OK] TokenManager导入成功")
|
||||
print(f" 缓存文件: {token_manager.cache_file_path}")
|
||||
|
||||
# 尝试获取token
|
||||
token = token_manager.get_token()
|
||||
print(f" [OK] Token获取成功")
|
||||
print(f" Token前20字符: {token[:20]}...")
|
||||
|
||||
return True
|
||||
except ValueError as e:
|
||||
print(f" [WARN] 环境变量未设置: {e}")
|
||||
print(f" 这不影响框架搭建,后续运行时需要设置")
|
||||
return True # 环境变量未设置不算失败
|
||||
except Exception as e:
|
||||
print(f" [FAIL] Token测试失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_smartsheet_api():
|
||||
"""测试5: 验证SmartSheetAPI复用"""
|
||||
print("\n" + "=" * 50)
|
||||
print("测试5: 验证SmartSheetAPI复用")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
from src.smartsheet import SmartSheetAPI
|
||||
from src.token_manager import TokenManager
|
||||
from src2.config import Task2ConfigManager
|
||||
|
||||
print(f" [OK] SmartSheetAPI导入成功")
|
||||
|
||||
# 获取配置
|
||||
config = Task2ConfigManager()
|
||||
docid = config.get_smartsheet_config()['docid']
|
||||
|
||||
# 获取token
|
||||
token_manager = TokenManager()
|
||||
token = token_manager.get_token()
|
||||
|
||||
# 创建SmartSheetAPI实例
|
||||
api = SmartSheetAPI(token, docid)
|
||||
print(f" [OK] SmartSheetAPI实例创建成功")
|
||||
print(f" docid: {docid}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" [FAIL] SmartSheetAPI测试失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""运行所有测试"""
|
||||
print("\n" + "=" * 50)
|
||||
print("任务二第一阶段验证")
|
||||
print("=" * 50)
|
||||
|
||||
results = {
|
||||
"目录结构": test_directory_structure(),
|
||||
"配置读取": test_config_read(),
|
||||
"日志写入": test_logger(),
|
||||
"Token管理": test_token_manager(),
|
||||
"SmartSheetAPI": test_smartsheet_api()
|
||||
}
|
||||
|
||||
# 汇总结果
|
||||
print("\n" + "=" * 50)
|
||||
print("验证结果汇总")
|
||||
print("=" * 50)
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
for name, result in results.items():
|
||||
status = "[OK]" if result else "[FAIL]"
|
||||
print(f" {status} {name}")
|
||||
if result:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\n总计: {passed} 通过, {failed} 失败")
|
||||
|
||||
if failed == 0:
|
||||
print("\n第一阶段验收通过!")
|
||||
else:
|
||||
print("\n请检查失败项并修复")
|
||||
|
||||
return failed == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
x
Reference in New Issue
Block a user