approve: world_sync 模块开发(W-05 同步管理)
This commit is contained in:
parent
de31d36a87
commit
873a83ab44
@ -10,6 +10,9 @@ sd_test_cases / sd_test_plans / sd_test_results 三张测试域表,修复
|
|||||||
「list_cases 返回字段全空、scense 库无 sd_test_cases 表」的环境根因,
|
「list_cases 返回字段全空、scense 库无 sd_test_cases 表」的环境根因,
|
||||||
环境重建/换库后自动自愈,无需手工建表。
|
环境重建/换库后自动自愈,无需手工建表。
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from ahserver.webapp import webapp
|
from ahserver.webapp import webapp
|
||||||
from ahserver.serverenv import ServerEnv
|
from ahserver.serverenv import ServerEnv
|
||||||
|
|
||||||
@ -19,6 +22,19 @@ from appbase.init import load_appbase
|
|||||||
from rbac.init import load_rbac
|
from rbac.init import load_rbac
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_scripts_path():
|
||||||
|
"""保证 scripts 包可导入:显式把模块根目录加入 sys.path。
|
||||||
|
|
||||||
|
无论 webapp 以何种方式启动(python app/scense.py / uwsgi / build.sh 注入的
|
||||||
|
PYTHONPATH 缺失时),`from scripts.init_test_db import ensure_test_db`
|
||||||
|
都能解析到 modules/scense/scripts/init_test_db.py,否则建表逻辑被
|
||||||
|
ImportError 吞掉、Bug 环境根因无法自愈。
|
||||||
|
"""
|
||||||
|
module_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
if module_root not in sys.path:
|
||||||
|
sys.path.insert(0, module_root)
|
||||||
|
|
||||||
|
|
||||||
def get_module_dbname(m):
|
def get_module_dbname(m):
|
||||||
"""模块 → 库名映射。单库应用:全部模块返回同一主库 scense。
|
"""模块 → 库名映射。单库应用:全部模块返回同一主库 scense。
|
||||||
|
|
||||||
@ -49,6 +65,7 @@ def init():
|
|||||||
# ── Bug 修复:测试用例域库表幂等自愈(环境根因)──
|
# ── Bug 修复:测试用例域库表幂等自愈(环境根因)──
|
||||||
# 确保 sd_test_cases / sd_test_plans / sd_test_results 存在,
|
# 确保 sd_test_cases / sd_test_plans / sd_test_results 存在,
|
||||||
# list_cases 不再因缺表返回字段全空。
|
# list_cases 不再因缺表返回字段全空。
|
||||||
|
_ensure_scripts_path()
|
||||||
from scripts.init_test_db import ensure_test_db
|
from scripts.init_test_db import ensure_test_db
|
||||||
try:
|
try:
|
||||||
ensure_test_db()
|
ensure_test_db()
|
||||||
|
|||||||
@ -21,6 +21,7 @@ _DDL_STATEMENTS = [
|
|||||||
CREATE TABLE IF NOT EXISTS `sd_test_cases` (
|
CREATE TABLE IF NOT EXISTS `sd_test_cases` (
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
`case_id` VARCHAR(64) NOT NULL COMMENT '用例编码(业务唯一,如 TC-0001)',
|
`case_id` VARCHAR(64) NOT NULL COMMENT '用例编码(业务唯一,如 TC-0001)',
|
||||||
|
`case_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '用例名称(list_cases 读取字段,兼容 case_name 命名)',
|
||||||
`title` VARCHAR(255) NOT NULL COMMENT '用例标题',
|
`title` VARCHAR(255) NOT NULL COMMENT '用例标题',
|
||||||
`description` TEXT NULL COMMENT '用例描述',
|
`description` TEXT NULL COMMENT '用例描述',
|
||||||
`module` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '所属模块',
|
`module` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '所属模块',
|
||||||
@ -85,7 +86,15 @@ _DDL_STATEMENTS = [
|
|||||||
|
|
||||||
|
|
||||||
def _dbname():
|
def _dbname():
|
||||||
"""取主库名:优先 ServerEnv(应用内),独立运行回退 .env MYSQL_DATABASE。"""
|
"""取主库名(多级兜底,不硬编码)。
|
||||||
|
|
||||||
|
优先级:
|
||||||
|
1) ServerEnv params['dbname'](应用运行期,appbase 写入)
|
||||||
|
2) conf/config.json 的 module_dbname 映射(独立部署脚本场景)
|
||||||
|
3) 环境变量 MYSQL_DATABASE
|
||||||
|
4) 默认 'scense'(单库应用约定)
|
||||||
|
"""
|
||||||
|
# 1) ServerEnv(应用内)
|
||||||
try:
|
try:
|
||||||
from ahserver.serverenv import ServerEnv
|
from ahserver.serverenv import ServerEnv
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
@ -93,7 +102,25 @@ def _dbname():
|
|||||||
return env.params.get('dbname')
|
return env.params.get('dbname')
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return os.environ.get('MYSQL_DATABASE', 'scense')
|
# 2) conf/config.json module_dbname 映射
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
cfg_path = Path(__file__).resolve().parent.parent / 'conf' / 'config.json'
|
||||||
|
if cfg_path.exists():
|
||||||
|
cfg = json.loads(cfg_path.read_text(encoding='utf-8'))
|
||||||
|
mapping = cfg.get('module_dbname') or {}
|
||||||
|
if isinstance(mapping, dict) and mapping.get('scense'):
|
||||||
|
return mapping['scense']
|
||||||
|
if cfg.get('dbname'):
|
||||||
|
return cfg['dbname']
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# 3) 环境变量
|
||||||
|
if os.environ.get('MYSQL_DATABASE'):
|
||||||
|
return os.environ['MYSQL_DATABASE']
|
||||||
|
# 4) 默认
|
||||||
|
return 'scense'
|
||||||
|
|
||||||
|
|
||||||
def ensure_test_db():
|
def ensure_test_db():
|
||||||
|
|||||||
@ -1,35 +1,28 @@
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- 元景项目-初始迭代 scense 库测试用例域建表 DDL
|
-- sd_test_cases 测试用例表 DDL(list_cases 数据来源)
|
||||||
-- 修复 Bug [e2Lck6zIRCXB5g7_HPZn0]
|
-- Bug [e2Lck6zIRCXB5g7_HPZn0] 修复:环境根因自愈建表
|
||||||
-- 环境根因:sd_test_cases 用例库不可达(list_cases 返回字段全空),
|
-- 与 scripts/init_test_db.py 中 _DDL_STATEMENTS 保持一致(幂等 IF NOT EXISTS)
|
||||||
-- scense 库无该表。本 DDL 幂等创建测试用例域 3 张表:
|
|
||||||
-- sd_test_cases 测试用例表(list_cases 数据来源)
|
|
||||||
-- sd_test_plans 测试计划表(plan=ajD47uZZH4yK7P5vh-Md3 归属)
|
|
||||||
-- sd_test_results 测试执行结果表
|
|
||||||
-- 同类问题一并覆盖,防止只修一张表、环境重建后再次不可达。
|
|
||||||
-- 执行方式:部署时由 scripts/init_test_db.py 自动执行(CREATE TABLE IF NOT EXISTS,幂等);
|
|
||||||
-- 也可手工执行本文件(mysql -u scense -p scense < sd_test_cases.sql)。
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|
||||||
-- ---------- sd_test_cases 测试用例表 ----------
|
|
||||||
CREATE TABLE IF NOT EXISTS `sd_test_cases` (
|
CREATE TABLE IF NOT EXISTS `sd_test_cases` (
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
`case_id` VARCHAR(64) NOT NULL COMMENT '用例编码(业务唯一,如 TC-0001)',
|
`case_id` VARCHAR(64) NOT NULL COMMENT '用例编码(业务唯一,如 TC-0001)',
|
||||||
`title` VARCHAR(255) NOT NULL COMMENT '用例标题',
|
`case_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '用例名称(list_cases 读取字段,兼容 case_name 命名)',
|
||||||
`description` TEXT NULL COMMENT '用例描述',
|
`title` VARCHAR(255) NOT NULL COMMENT '用例标题',
|
||||||
`module` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '所属模块(world/scene/entity/script_engine/world_snapshot/world_sync)',
|
`description` TEXT NULL COMMENT '用例描述',
|
||||||
`plan_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '所属测试计划ID(sd_test_plans.plan_id)',
|
`module` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '所属模块',
|
||||||
`priority` VARCHAR(16) NOT NULL DEFAULT 'P2' COMMENT '优先级:P0=最高/P1=高/P2=中/P3=低',
|
`plan_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '所属测试计划ID',
|
||||||
`preconditions` TEXT NULL COMMENT '前置条件',
|
`priority` VARCHAR(16) NOT NULL DEFAULT 'P2' COMMENT '优先级:P0/P1/P2/P3',
|
||||||
`steps` TEXT NULL COMMENT '测试步骤(多行文本)',
|
`preconditions` TEXT NULL COMMENT '前置条件',
|
||||||
`expected_result` TEXT NULL COMMENT '预期结果',
|
`steps` TEXT NULL COMMENT '测试步骤',
|
||||||
`actual_result` TEXT NULL COMMENT '实际结果(执行后回填)',
|
`expected_result` TEXT NULL COMMENT '预期结果',
|
||||||
`status` VARCHAR(16) NOT NULL DEFAULT 'draft' COMMENT '用例状态:draft/active/closed(字典 sd_test_case_status)',
|
`actual_result` TEXT NULL COMMENT '实际结果',
|
||||||
`execute_status` VARCHAR(16) NOT NULL DEFAULT 'not_run' COMMENT '执行状态:not_run/pass/fail/blocked(字典 sd_test_exec_status)',
|
`status` VARCHAR(16) NOT NULL DEFAULT 'draft' COMMENT '用例状态:draft/active/closed',
|
||||||
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人',
|
`execute_status` VARCHAR(16) NOT NULL DEFAULT 'not_run' COMMENT '执行状态:not_run/pass/fail/blocked',
|
||||||
`updated_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '更新人',
|
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
`updated_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `uk_case_id` (`case_id`),
|
UNIQUE KEY `uk_case_id` (`case_id`),
|
||||||
KEY `idx_plan_id` (`plan_id`),
|
KEY `idx_plan_id` (`plan_id`),
|
||||||
@ -37,44 +30,3 @@ CREATE TABLE IF NOT EXISTS `sd_test_cases` (
|
|||||||
KEY `idx_status` (`status`),
|
KEY `idx_status` (`status`),
|
||||||
KEY `idx_execute_status` (`execute_status`)
|
KEY `idx_execute_status` (`execute_status`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='测试用例表(list_cases 数据来源)';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='测试用例表(list_cases 数据来源)';
|
||||||
|
|
||||||
-- ---------- sd_test_plans 测试计划表 ----------
|
|
||||||
CREATE TABLE IF NOT EXISTS `sd_test_plans` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|
||||||
`plan_id` VARCHAR(64) NOT NULL COMMENT '测试计划ID(如 ajD47uZZH4yK7P5vh-Md3)',
|
|
||||||
`plan_name` VARCHAR(255) NOT NULL COMMENT '计划名称',
|
|
||||||
`iteration_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '所属迭代ID',
|
|
||||||
`description` TEXT NULL COMMENT '计划描述',
|
|
||||||
`status` VARCHAR(16) NOT NULL DEFAULT 'draft' COMMENT '计划状态:draft/approved/in_progress/done(字典 sd_test_plan_status)',
|
|
||||||
`created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人',
|
|
||||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_plan_id` (`plan_id`),
|
|
||||||
KEY `idx_iteration_id` (`iteration_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='测试计划表';
|
|
||||||
|
|
||||||
-- ---------- sd_test_results 测试执行结果表 ----------
|
|
||||||
CREATE TABLE IF NOT EXISTS `sd_test_results` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|
||||||
`result_id` VARCHAR(64) NOT NULL COMMENT '执行结果ID(业务唯一)',
|
|
||||||
`case_id` VARCHAR(64) NOT NULL COMMENT '用例编码(关联 sd_test_cases.case_id)',
|
|
||||||
`plan_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '所属测试计划ID',
|
|
||||||
`run_status` VARCHAR(16) NOT NULL DEFAULT 'not_run' COMMENT '执行结果:pass/fail/blocked/skipped(字典 sd_test_run_status)',
|
|
||||||
`actual_result` TEXT NULL COMMENT '实际结果描述',
|
|
||||||
`bug_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '失败联动产生的Bug ID(若有)',
|
|
||||||
`executed_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '执行人',
|
|
||||||
`executed_at` DATETIME NULL COMMENT '执行时间',
|
|
||||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_result_id` (`result_id`),
|
|
||||||
KEY `idx_case_id` (`case_id`),
|
|
||||||
KEY `idx_plan_id` (`plan_id`),
|
|
||||||
KEY `idx_run_status` (`run_status`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='测试执行结果表';
|
|
||||||
|
|
||||||
-- ---------- 字典:用例状态 ----------
|
|
||||||
INSERT IGNORE INTO `sd_dict` (`dict_code`, `dict_name`, `item_code`, `item_name`, `sort_no`, `enabled`) VALUES
|
|
||||||
('sd_test_case_status', '测试用例状态', 'draft', '草稿', 1, 1),
|
|
||||||
('sd_test_case_status', '测试用例状态', 'active', '启用', 2, 1),
|
|
||||||
('sd_test_case_status', '测试用例状态', 'closed', '关闭', 3, 1);
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user