Discover request surface — taste-aware, rotating, snoozable, tag-targeted (milestone #268) #116
@@ -399,23 +399,57 @@ func TestSuggestArtists_UntaggedCandidateSurvivesAlongsideTagged(t *testing.T) {
|
||||
seedCandidateTag(t, pool, "match", "shoegaze", 1.0)
|
||||
// "loud" is deliberately left with NO cached tags at all.
|
||||
|
||||
out, err := SuggestArtists(context.Background(), pool, user.ID, 30, 12, 1.0)
|
||||
// Compared against the same request with the term disabled, rather than
|
||||
// against a literal. The pool score is signal-weighted by the seed query
|
||||
// (ln(1+signal) x similarity), so hardcoding a number here would assert
|
||||
// against the seeding maths — a different layer — and break whenever that
|
||||
// changes. The property under test is only that the blend leaves an
|
||||
// untagged candidate alone.
|
||||
blended, err := SuggestArtists(context.Background(), pool, user.ID, 30, 12, 1.0)
|
||||
if err != nil {
|
||||
t.Fatalf("SuggestArtists: %v", err)
|
||||
t.Fatalf("SuggestArtists(blended): %v", err)
|
||||
}
|
||||
if len(out) != 2 {
|
||||
t.Fatalf("len = %d, want 2 — the untagged candidate must still appear", len(out))
|
||||
baseline, err := SuggestArtists(context.Background(), pool, user.ID, 30, 12, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("SuggestArtists(baseline): %v", err)
|
||||
}
|
||||
var loud *ArtistSuggestion
|
||||
for i := range out {
|
||||
if out[i].MBID == "loud" {
|
||||
loud = &out[i]
|
||||
if len(blended) != 2 {
|
||||
t.Fatalf("len = %d, want 2 — the untagged candidate must still appear", len(blended))
|
||||
}
|
||||
|
||||
scoreOf := func(out []ArtistSuggestion, mbid string) (float64, bool) {
|
||||
for _, s := range out {
|
||||
if s.MBID == mbid {
|
||||
return s.Score, true
|
||||
}
|
||||
}
|
||||
if loud == nil {
|
||||
t.Fatal("untagged candidate vanished from the deck")
|
||||
return 0, false
|
||||
}
|
||||
if loud.Score != 0.9 {
|
||||
t.Errorf("untagged score = %v, want 0.9 unchanged", loud.Score)
|
||||
want, ok := scoreOf(baseline, "loud")
|
||||
if !ok {
|
||||
t.Fatal("untagged candidate missing from the baseline deck")
|
||||
}
|
||||
got, ok := scoreOf(blended, "loud")
|
||||
if !ok {
|
||||
t.Fatal("untagged candidate vanished once the tag term was enabled")
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("untagged score = %v, want %v (identical to the term-disabled run)", got, want)
|
||||
}
|
||||
// Sanity: the tagged candidate DID move, so the comparison above is
|
||||
// meaningful rather than both runs being trivially identical.
|
||||
if tagged, _ := scoreOf(blended, "match"); tagged == mustScore(t, baseline, "match") {
|
||||
t.Error("the tagged candidate's score did not change — the term did nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func mustScore(t *testing.T, out []ArtistSuggestion, mbid string) float64 {
|
||||
t.Helper()
|
||||
for _, s := range out {
|
||||
if s.MBID == mbid {
|
||||
return s.Score
|
||||
}
|
||||
}
|
||||
t.Fatalf("no candidate %q in %v", mbid, out)
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user