73 lines
3.9 KiB
Markdown
73 lines
3.9 KiB
Markdown
# 历史对账 + 基准差分测试骨架
|
||
|
||
## 一句话结论
|
||
|
||
**这套骨架在测试运行时不需要任何数据库连接。** 唯一触碰数据库的地方是
|
||
`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 # 此时跑的是真实历史对账
|
||
```
|