test(goauto): pin SYB filter behaviour against real variationSku samples #269
The samples are the ones the production database actually holds: 档口 codes like "新寮-雅伊阁大码女装#301" and "DD#004" must be filtered, while own codes like "PDD0582", "my238", "1" and "引流款" must not, and an empty variationSku is a product without a supplier code rather than a 档口 item. The test also asserts the two structural rules record different hit counts. That is the property the previous aggregate-per-kind write could not hold, and the disable-confirmation dialog depends on it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package sybproductfilter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 用线上真实取到的 variationSku 样本,验证过滤判定与每条规则各自计数。
|
||||
func TestRealWorldSamplesPerRuleCounting(t *testing.T) {
|
||||
db := testDB(t)
|
||||
ctx := context.Background()
|
||||
set, err := LoadEnabled(ctx, db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
samples := []struct {
|
||||
v string
|
||||
wantKind string // "" = 不过滤
|
||||
}{
|
||||
{"新寮-雅伊阁大码女装#301", "char"},
|
||||
{"广达-爆款大码女装#9018", "char"},
|
||||
{"DD#004", "char"},
|
||||
{"300斤牛奶絲圓領#A057", "char"},
|
||||
{"上寮-琪琪尚雅网批#2604##(&15)", "char"},
|
||||
{"PDD0582", ""},
|
||||
{"my238", ""},
|
||||
{"le171", ""},
|
||||
{"1", ""},
|
||||
{"引流款", ""},
|
||||
{"", ""},
|
||||
}
|
||||
hits := HitCounter{}
|
||||
var charN, kwN, keptN int
|
||||
for _, s := range samples {
|
||||
rule := set.Match(s.v)
|
||||
if s.wantKind == "" {
|
||||
if rule != nil {
|
||||
t.Fatalf("%q 不应被过滤,却命中了 %q", s.v, rule.Keyword)
|
||||
}
|
||||
keptN++
|
||||
continue
|
||||
}
|
||||
if rule == nil || rule.Kind != s.wantKind {
|
||||
t.Fatalf("%q 应命中 %s 规则,实际 %v", s.v, s.wantKind, rule)
|
||||
}
|
||||
hits.Add(rule)
|
||||
if rule.Kind == "char" {
|
||||
charN++
|
||||
} else {
|
||||
kwN++
|
||||
}
|
||||
}
|
||||
if charN != 5 || kwN != 0 || keptN != 6 {
|
||||
t.Fatalf("统计不符:char=%d keyword=%d kept=%d", charN, kwN, keptN)
|
||||
}
|
||||
if err := UpdateHits(ctx, db, set, hits, time.Now().UTC()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
after, err := LoadEnabled(ctx, db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := map[string]int{}
|
||||
for _, x := range after.Chars {
|
||||
if x.LastHitCount == nil {
|
||||
t.Fatalf("规则 %q 必须被写入命中数", x.Keyword)
|
||||
}
|
||||
got[x.Keyword] = *x.LastHitCount
|
||||
}
|
||||
// "#" 命中 4 条(301/9018/DD#004/A057 ... 其中带 - 的先被 "-" 规则接走)
|
||||
if got["-"]+got["#"] != 5 {
|
||||
t.Fatalf("两条结构规则命中数之和应为 5,实际 - =%d # =%d", got["-"], got["#"])
|
||||
}
|
||||
if got["-"] == got["#"] {
|
||||
t.Fatalf("两条规则不应记成同一个数(这正是 #269 修的 bug): - =%d # =%d", got["-"], got["#"])
|
||||
}
|
||||
for _, x := range after.Keywords {
|
||||
if x.LastHitCount == nil || *x.LastHitCount != 0 {
|
||||
t.Fatalf("未命中的关键词 %q 应记 0,实际 %v", x.Keyword, x.LastHitCount)
|
||||
}
|
||||
}
|
||||
t.Logf("结构规则命中:- =%d # =%d", got["-"], got["#"])
|
||||
}
|
||||
Reference in New Issue
Block a user