diff --git a/db/company_scope_test.go b/db/company_scope_test.go index 713938e..31fcbc3 100644 --- a/db/company_scope_test.go +++ b/db/company_scope_test.go @@ -233,7 +233,15 @@ func TestCompanyICPAttribution(t *testing.T) { if err != nil { t.Skipf("postgres unavailable (%v) — skipping", err) } - defer d.Close() + // 关连接必须走 t.Cleanup 且**注册在清理之前**:t.Cleanup 是后进先出, + // 先注册关闭 → 关闭最后执行,下面的数据清理才连得上库。 + // 原先这里是 `defer d.Close()`:defer 在函数返回时先跑,t.Cleanup 在那之后 + // 才执行,于是清理语句全落在**已关闭的连接**上、错误又被 `_, _ =` 丢弃, + // 资产与公司就永久残留在库里。残留本身不会立刻报错,但本用例用 + // `MAX(companies.id)+1` 当假 TaskID 给资产打标(见下方 suffix), + // 一旦这个数字与别的用例的任务 id 撞上,那个用例按「恰好 N 个资产」的断言 + // 就会莫名失败——排查成本极高。 + t.Cleanup(func() { d.Close() }) var suffix int64 if err := d.QueryRow(`SELECT COALESCE(MAX(id),0)+1 FROM companies`).Scan(&suffix); err != nil { @@ -246,8 +254,13 @@ func TestCompanyICPAttribution(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { - _, _ = d.Exec(`DELETE FROM assets WHERE task_ids @> ARRAY[$1]::bigint[]`, suffix) - _, _ = d.Exec(`DELETE FROM companies WHERE id=$1`, companyID) + // 不吞错误:清理失败会污染后续用例,必须让它在本次运行里显形。 + if _, err := d.Exec(`DELETE FROM assets WHERE task_ids @> ARRAY[$1]::bigint[]`, suffix); err != nil { + t.Errorf("清理测试资产失败: %v", err) + } + if _, err := d.Exec(`DELETE FROM companies WHERE id=$1`, companyID); err != nil { + t.Errorf("清理测试公司失败: %v", err) + } }) // A keyword can guide an Agent, but must never claim an asset by its name.