Files
zszq-trs/YLErpWeb/fe-tests/HISTORICAL_RECONCILIATION.md
T

73 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 历史对账 + 基准差分测试骨架
## 一句话结论
**这套骨架在测试运行时不需要任何数据库连接。** 唯一触碰数据库的地方是
`tools/exportHistoricalSwapEvents.js`——一个**开发期一次性导出脚本**(把真实
`swap_event.data` 灌进 fixture),它**文件名非 `*.test.js`jest 不会执行它**
因此 CI 跑 `npm test` 时零 DB 依赖。
## 文件清单
| 文件 | 运行时是否要 DB | 说明 |
|------|----------------|------|
| `historicalReconciliation.test.js` | **否** | 离线对账:独立规格 vs fixture 中记录的落库值 |
| `fixtures/historical_swap_events.json` | **否** | 历史数据夹具(当前为手搓代表性样本,可由导出脚本替换为真实数据) |
| `swapCalc.test.js`(既有) | **否** | `swapCalc.js` 参考实现 vs C# 金标准 `FC_001~009` 差分 |
| `tools/exportHistoricalSwapEvents.js` | **是(仅此一处,开发期)** | 一次性导出真实历史,不属于测试路径 |
## 设计原则(回应"重构怕引入新 Bug"的顾虑)
1. **先冻后改**:用特征测试把"当前(可能含历史 bug 的)行为"钉死。任何重构只要改变了
金额产出,测试立即变红,**逼你查根因,绝不自动 re-baseline**(避免 `01d7f0c5` 式静默掩盖)。
2. **已知差异显式冻结**`swapLongShort.js``SwapMarginAmount` 用裸 `InterestPrincipal`
(无符号),而 `unwindSwapTrade.js``InterestDirection` 求符号——这是真实的代码不一致。
它在 fixture 里以 `knownDiscrepancies.SwapMarginAmount` 记录"差异量",测试只在该**差异量变化**
时报红,既不掩盖也不误报。
3. **独立规格不信任任何既有实现**`referenceOracle` 是按 `unwindSwapTrade.js:329` 独立重写的
纯函数,作为"应然"基准。若生产代码与独立规格分叉,说明要么生产错了、要么规格写错了——必须人工裁决。
## 如何扩展到"4 个生产 calcCloseAmount 的差分"
当前骨架用的是**独立重写的规格**,并未直接驱动那 4 个组件里的 `calcCloseAmount`
原因是这 4 个文件在模块顶层就访问 `window.otcformat` / `model` / `swapPricePrecision`
等全局(见 `unwindSwapTrade.js:1-2`),在 jest 的 `node` 环境下直接 `require` 会在加载期抛错。
要把它们纳入差分,**唯一的代码改动**是"提取纯函数"(行为不变,非统一):
```js
// 在组件文件里,把 calcCloseAmount 的金额聚合核心抽成导出纯函数
function calcUnwindCloseAmountCore(deal, floatPosition, interestList, marginList) {
// ...原 :329-367 的金额聚合逻辑搬过来,去掉 this / formatSwapAmount 展示归一...
}
// 原方法改为 2 行包装,保持行为完全一致:
calcCloseAmount() {
const r = calcUnwindCloseAmountCore(this.deal, this.floatPosition, this.interestList, this.marginList);
Object.assign(this.deal, r);
}
module.exports = { calcUnwindCloseAmountCore }; // 仅新增导出,不改逻辑
```
提取后 jest 即可 `require` 并差分,且**不连 DB、不碰业务逻辑**。这一步务必配合一条
"提取前后产出一致"的快照测试,确保提取本身没改行为。
> 注意:`swapCalc.js` 目前**未接入生产**(其 `calcUnwind/calcIncome` 注释明写"未接入"),
> 且它**不计算 `SwapMarginAmount`**(利息腿 `InterestPrincipal` 那一项),因此不能直接拿它
> 替换 4 个生产函数。它目前只作为"参考金标准"被 `swapCalc.test.js` 的 `FC_*` 用例校验。
## 运行
```bash
cd YLErpWeb/fe-tests
npm i # 安装 jest / mysql2(可选,仅导出脚本用)
npx jest historicalReconciliation.test.js
```
要注入真实历史(可选,需 DB):
```bash
MYSQL_HOST=... MYSQL_USER=... MYSQL_PASS=... MYSQL_DB=... \
node tools/exportHistoricalSwapEvents.js --from 2026-01-01 --limit 200
npx jest historicalReconciliation.test.js # 此时跑的是真实历史对账
```