98 lines
3.7 KiB
Python
98 lines
3.7 KiB
Python
"""KIN09CSV 修复测试。
|
||
|
||
覆盖:
|
||
- Fix A: PARM 场景配置(missing_mode / reordered_parm / missing_ym / empty_daily)
|
||
- Fix B: seed_extra_rows 大结果集注入(表头重出分支可达)
|
||
"""
|
||
|
||
import os
|
||
import sqlite3
|
||
import sys
|
||
import tempfile
|
||
from pathlib import Path
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||
|
||
import pytest
|
||
|
||
from orchestrator_db import GixsqlOrchestrator
|
||
|
||
|
||
def _make_orch():
|
||
orch = object.__new__(GixsqlOrchestrator)
|
||
table = type('T', (), {
|
||
'name': 'DAILY_RECORDS',
|
||
'columns': [
|
||
type('C', (), {'name': 'EMP_ID', 'primary_key': True}),
|
||
type('C', (), {'name': 'TARGET_DATE', 'primary_key': True}),
|
||
type('C', (), {'name': 'TIME_IN', 'primary_key': False}),
|
||
type('C', (), {'name': 'UPDATED_AT', 'primary_key': False}),
|
||
],
|
||
})()
|
||
orch.schema = type('S', (), {'db_tables': [table]})()
|
||
return orch
|
||
|
||
|
||
def _make_db(path: Path):
|
||
conn = sqlite3.connect(str(path))
|
||
conn.execute('CREATE TABLE [DAILY_RECORDS] ('
|
||
'[EMP_ID] CHAR(8), [TARGET_DATE] CHAR(8), '
|
||
'[TIME_IN] CHAR(4), [UPDATED_AT] TIMESTAMP, '
|
||
'PRIMARY KEY ([EMP_ID], [TARGET_DATE]))')
|
||
conn.execute("INSERT INTO [DAILY_RECORDS] VALUES ('Y0000001', '20260701', '0900', '2026-07-01')")
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
|
||
def test_seed_extra_rows_injects_rows():
|
||
"""seed_extra_rows 应从 seed 行推导月份并注入唯一 (EMP, 日期) 行。"""
|
||
orch = _make_orch()
|
||
tmp = Path(tempfile.mkdtemp())
|
||
db = tmp / 'kin.db'
|
||
_make_db(db)
|
||
scenario = type('S', (), {'seed_extra_rows': {'DAILY_RECORDS': 10}})()
|
||
orch._inject_extra_seed_rows(db, scenario)
|
||
|
||
conn = sqlite3.connect(str(db))
|
||
rows = conn.execute('SELECT EMP_ID, TARGET_DATE FROM [DAILY_RECORDS]').fetchall()
|
||
conn.close()
|
||
emps = {r[0] for r in rows}
|
||
assert len(rows) >= 11, f'应注入 10 条额外行, 实际 {len(rows)}'
|
||
assert 'SEED0001' in emps and 'SEED0010' in emps, f'应含 SEED 行, 实际 {emps}'
|
||
# 注入行日期应在查询月份内
|
||
seed_dates = {r[1] for r in rows if r[0].startswith('SEED')}
|
||
assert seed_dates == {'20260701'}, f'注入日期应为 20260701, 实际 {seed_dates}'
|
||
|
||
|
||
def test_seed_extra_rows_noop_when_not_configured():
|
||
"""seed_extra_rows 未配置时不应注入。"""
|
||
orch = _make_orch()
|
||
tmp = Path(tempfile.mkdtemp())
|
||
db = tmp / 'kin.db'
|
||
_make_db(db)
|
||
scenario = type('S', (), {'seed_extra_rows': {}})()
|
||
orch._inject_extra_seed_rows(db, scenario)
|
||
conn = sqlite3.connect(str(db))
|
||
n = conn.execute('SELECT COUNT(*) FROM [DAILY_RECORDS]').fetchone()[0]
|
||
conn.close()
|
||
assert n == 1, f'不应注入额外行, 实际 {n}'
|
||
|
||
|
||
def test_kin09csv_scenarios_parse():
|
||
"""KIN09CSV.yaml 场景(含 seed_extra_rows)应正确解析。"""
|
||
from config.program_schema import load_schema
|
||
schema = load_schema('KIN09CSV', [str(Path(__file__).parent.parent / 'config' / 'programs')])
|
||
by_id = {r.id: r for r in schema.runs}
|
||
assert 'missing_mode' in by_id, f'应含 missing_mode 场景: {list(by_id)}'
|
||
assert 'reordered_parm' in by_id
|
||
assert 'missing_ym' in by_id
|
||
assert 'empty_daily' in by_id
|
||
assert by_id['missing_mode'].command_line == 'YEARMONTH=202607'
|
||
assert by_id['reordered_parm'].command_line == 'MODE=FULL,YEARMONTH=202607'
|
||
assert by_id['missing_ym'].command_line == 'MODE=FULL'
|
||
assert by_id['empty_daily'].drop_tables == ['DAILY_RECORDS'], \
|
||
f'empty_daily 应 drop DAILY_RECORDS, 实际 {by_id["empty_daily"].drop_tables}'
|
||
full = by_id['FULL']
|
||
assert full.seed_extra_rows.get('DAILY_RECORDS') == 100, \
|
||
f'FULL 场景 seed_extra_rows 应为 100, 实际 {full.seed_extra_rows}'
|