|
|
@@ -83,48 +83,54 @@ func recommendCompare(c Case, lg, tg *SideResult) ([]Diff, []Assertion) {
|
|
|
lrc, trc := lg.After.RecommenderCampus, tg.After.RecommenderCampus
|
|
|
lb, tb := lg.Before.Recommender, tg.Before.Recommender
|
|
|
lbc, tbc := lg.Before.RecommenderCampus, tg.Before.RecommenderCampus
|
|
|
+ // Before 的**形态**也要打出来:Δ 只在"Before == 声明的基线"时才有意义。
|
|
|
+ // `Δ=0` 有两种相反含义:「没改」与「本来就是那个值」,而后者等于这条 case 没测到东西。
|
|
|
+ // 本 case 声明的基线是 Absent ⇒ Before 必须**没有行**(这一条另由 run.go 的前置断言钉住)。
|
|
|
+ beforeShape := fmt.Sprintf("Before:legacy 全局行=%v 校区行=%v | target 全局行=%v 校区行=%v",
|
|
|
+ lg.Before.HasRecommender, lg.Before.HasRecommenderCampus,
|
|
|
+ tg.Before.HasRecommender, tg.Before.HasRecommenderCampus)
|
|
|
|
|
|
- add("W4-B·推荐人 全局 Δbalance", fmt.Sprintf("%+d", lr.Balance-lb.Balance),
|
|
|
- fmt.Sprintf("%+d", tr.Balance-tb.Balance), lr.Balance-lb.Balance == tr.Balance-tb.Balance,
|
|
|
+ add("W4-B·推荐人 全局 Δbalance", fmt.Sprintf("%+d", delta(lb.Balance, lr.Balance)),
|
|
|
+ fmt.Sprintf("%+d", delta(tb.Balance, tr.Balance)), delta(lb.Balance, lr.Balance) == delta(tb.Balance, tr.Balance),
|
|
|
"两侧都应 +m(全局列有 DEFAULT 0.000)")
|
|
|
asserts = append(asserts, Assertion{Kind: AssertionBusiness,
|
|
|
Name: "W4-B① 全局 `balance`:**两侧都 +m**(`t_user_expense.balance` 有 `DEFAULT 0.000`,建行后有值)",
|
|
|
- Pass: lr.Balance-lb.Balance == want && tr.Balance-tb.Balance == want,
|
|
|
- Detail: fmt.Sprintf("legacy %+d(期望 %+d)| target %+d(期望 %+d)| m=%d。"+
|
|
|
+ Pass: delta(lb.Balance, lr.Balance) == want && delta(tb.Balance, tr.Balance) == want,
|
|
|
+ Detail: beforeShape + fmt.Sprintf(" | legacy %+d(期望 %+d)| target %+d(期望 %+d)| m=%d。"+
|
|
|
"这一条是**唯一两侧一致**的那句 —— 也是为什么只看全局会漏掉整个缺陷",
|
|
|
- lr.Balance-lb.Balance, want, tr.Balance-tb.Balance, want, want),
|
|
|
+ delta(lb.Balance, lr.Balance), want, delta(tb.Balance, tr.Balance), want, want),
|
|
|
})
|
|
|
|
|
|
- add("W4-B·推荐人 校区 Δbalance", fmt.Sprintf("%+d(NULL=%v)", lrc.Balance-lbc.Balance, lrc.Nulls.Balance),
|
|
|
- fmt.Sprintf("%+d(NULL=%v)", trc.Balance-tbc.Balance, trc.Nulls.Balance),
|
|
|
+ add("W4-B·推荐人 校区 Δbalance", fmt.Sprintf("%+d(NULL=%v)", delta(lbc.Balance, lrc.Balance), lrc.Nulls.Balance),
|
|
|
+ fmt.Sprintf("%+d(NULL=%v)", delta(tbc.Balance, trc.Balance), trc.Nulls.Balance),
|
|
|
c.IntentionalStrict, "legacy 建行只写 3 列 ⇒ 该列无 DEFAULT ⇒ NULL")
|
|
|
asserts = append(asserts, Assertion{Kind: AssertionBusiness,
|
|
|
Name: "W4-B② 校区 `balance`:legacy **仍是 NULL(没到账)** / target **+m 且有值**",
|
|
|
- Pass: lrc.Nulls.Balance && lrc.Balance-lbc.Balance == 0 && !trc.Nulls.Balance && trc.Balance-tbc.Balance == want,
|
|
|
- Detail: fmt.Sprintf("legacy Δ=%+d NULL=%v | target Δ=%+d NULL=%v | m=%d。"+
|
|
|
+ Pass: lrc.Nulls.Balance && delta(lbc.Balance, lrc.Balance) == 0 && !trc.Nulls.Balance && delta(tbc.Balance, trc.Balance) == want,
|
|
|
+ Detail: beforeShape + fmt.Sprintf(" | legacy Δ=%+d NULL=%v | target Δ=%+d NULL=%v | m=%d。"+
|
|
|
"legacy 侧 `SET balance=balance+m` 在 NULL 上运算仍是 NULL ⇒ **校区一分没记**",
|
|
|
- lrc.Balance-lbc.Balance, lrc.Nulls.Balance, trc.Balance-tbc.Balance, trc.Nulls.Balance, want),
|
|
|
+ delta(lbc.Balance, lrc.Balance), lrc.Nulls.Balance, delta(tbc.Balance, trc.Balance), trc.Nulls.Balance, want),
|
|
|
})
|
|
|
|
|
|
add("W4-B·推荐人 Δrecommended(全局/校区)",
|
|
|
- fmt.Sprintf("%+d/%+d (NULL %v/%v)", lr.Recommended-lb.Recommended, lrc.Recommended-lbc.Recommended,
|
|
|
+ fmt.Sprintf("%+d/%+d (NULL %v/%v)", delta(lb.Recommended, lr.Recommended), delta(lbc.Recommended, lrc.Recommended),
|
|
|
lr.Nulls.Recommended, lrc.Nulls.Recommended),
|
|
|
- fmt.Sprintf("%+d/%+d (NULL %v/%v)", tr.Recommended-tb.Recommended, trc.Recommended-tbc.Recommended,
|
|
|
+ fmt.Sprintf("%+d/%+d (NULL %v/%v)", delta(tb.Recommended, tr.Recommended), delta(tbc.Recommended, trc.Recommended),
|
|
|
tr.Nulls.Recommended, trc.Nulls.Recommended),
|
|
|
c.IntentionalStrict, "两张表这一列都无 DEFAULT")
|
|
|
asserts = append(asserts, Assertion{Kind: AssertionBusiness,
|
|
|
Name: "W4-B③ `total_recommended_amount`:legacy **全局与校区都是 NULL(两边都没记)** / target 两处都 +m",
|
|
|
Pass: lr.Nulls.Recommended && lrc.Nulls.Recommended &&
|
|
|
- lr.Recommended-lb.Recommended == 0 && lrc.Recommended-lbc.Recommended == 0 &&
|
|
|
+ delta(lb.Recommended, lr.Recommended) == 0 && delta(lbc.Recommended, lrc.Recommended) == 0 &&
|
|
|
!tr.Nulls.Recommended && !trc.Nulls.Recommended &&
|
|
|
- tr.Recommended-tb.Recommended == want && trc.Recommended-tbc.Recommended == want,
|
|
|
- Detail: fmt.Sprintf("legacy 全局 %+d NULL=%v、校区 %+d NULL=%v | target 全局 %+d NULL=%v、校区 %+d NULL=%v。"+
|
|
|
+ delta(tb.Recommended, tr.Recommended) == want && delta(tbc.Recommended, trc.Recommended) == want,
|
|
|
+ Detail: beforeShape + fmt.Sprintf(" | legacy 全局 %+d NULL=%v、校区 %+d NULL=%v | target 全局 %+d NULL=%v、校区 %+d NULL=%v。"+
|
|
|
"⚠ **NULL 不是 0**:它表示「累计推荐金额从未被写成功过」,与「推荐金额确实是 0」在账上完全不同;"+
|
|
|
"按 Q1 口径 target 应为 0.00 的地方这里是 +m —— 这就是缺陷本身",
|
|
|
- lr.Recommended-lb.Recommended, lr.Nulls.Recommended,
|
|
|
- lrc.Recommended-lbc.Recommended, lrc.Nulls.Recommended,
|
|
|
- tr.Recommended-tb.Recommended, tr.Nulls.Recommended,
|
|
|
- trc.Recommended-tbc.Recommended, trc.Nulls.Recommended),
|
|
|
+ delta(lb.Recommended, lr.Recommended), lr.Nulls.Recommended,
|
|
|
+ delta(lbc.Recommended, lrc.Recommended), lrc.Nulls.Recommended,
|
|
|
+ delta(tb.Recommended, tr.Recommended), tr.Nulls.Recommended,
|
|
|
+ delta(tbc.Recommended, trc.Recommended), trc.Nulls.Recommended),
|
|
|
})
|
|
|
}
|
|
|
|
|
|
@@ -259,3 +265,20 @@ func signedStatus(s *SideResult, activityID int64) int32 {
|
|
|
}
|
|
|
return -1
|
|
|
}
|
|
|
+
|
|
|
+// delta 返回 `after − before`(单位:分)。
|
|
|
+//
|
|
|
+// 为什么要有这个函数,而不是各处直接写 `a - b`:
|
|
|
+// 批 3d 真踩过一次 —— 手写时把被减数与减数写成了**同一个快照**
|
|
|
+// (`trc.Recommended - trc.Recommended`),恒等于 0,打印成 `+0`,
|
|
|
+// 看起来就像"目标实现没给这一列加钱",我据此报了一个 P0 级的 TARGET-DEFECT 嫌疑。
|
|
|
+// 实际实现是对的,错的是断言。见 §18.3 第 9 条。
|
|
|
+//
|
|
|
+// 用函数的价值不在计算,在**参数有名字**:调用处必须写 `delta(before, after)`,
|
|
|
+// 名字逼着人回答"这两个是不同来源吗";而 `a - b` 什么都不问。
|
|
|
+//
|
|
|
+// ⚠ 它挡不住"两个参数传了同一个变量",所以还要配合两条:
|
|
|
+//
|
|
|
+// ① 单测 `TestDeltaOrderAndSelfSubtraction`(传同一个值必须得 0,且必须有别处断言非 0);
|
|
|
+// ② 任何基于 Δ 的断言,同时断言 **Before 就是声明的基线**(§18.3 第 10 条)。
|
|
|
+func delta(before, after int64) int64 { return after - before }
|