The bug I filed was wrong, and the fixture that fixed it broke four other tests
I filed this issue myself, from a bug report: “don’t allow duplicate albums in the playlist.” I wrote it up as a write-time problem - add a check before inserting a track so a duplicate album can’t sneak into the playlist twice. Track-level dedup already existed; I figured the gap was at the album level.
Before touching code, a research pass I’d spawned flagged a problem with my own issue: the proposed guard was redundant everywhere it would actually fire (exact re-adds were already caught by the existing track-level check), and useless for the one case that might really produce a duplicate - a deluxe or remastered edition, whose track titles differ just enough to slip past a title-based key. I was about to build a fix for a bug that couldn’t happen, and miss the one that could.
So instead of patching the issue as filed, I went back to what I actually wanted as the person using this app, and it reframed the whole thing: if the album is on the playlist, it shouldn’t appear on the Discover tab at all, and the option to add it should be disabled everywhere with a message that it’s already there. Not a write-time guard - a read-time exclusion. If an album’s already in your playlist, don’t show it as something to add in the first place.
The implementation was simple once scoped correctly: compute the set of album keys already in the playlist, filter them out of the Discover feed, and check membership before showing an “Add” button anywhere else. I added a permanent regression fixture to the mock data for it - a real catalog album (“Fragments” by Bonobo) also present as a playlist entry, so the exclusion has something concrete to prove against in tests and in the simulator.
That fixture is also what broke four unrelated tests. Adding a fifth playlist group to the shared mock fixture shifted nothing structurally, but four separate tests had hardcoded assumptions baked in - groups.count == 4, a suggestions list expected to include an album that was now, correctly, excluded as already-owned. None of those tests were wrong when written; they’d just quietly become load-bearing on a number that was never supposed to be load-bearing. Running the full suite instead of just the new test caught all four before they shipped.
Verifying on a real device surfaced two more things, neither of which were the feature I was testing. The Playlist tab intermittently got stuck on “Loading playlist…” forever, no error, no retry - traced to a newly-introduced concurrent fetch (Discover’s own background prefetch now also asks for playlist contents at launch) racing against the Playlist tab’s own load, landing on a silent, unrecoverable cancellation swallow already sitting in the code. And a filter-settings report turned out not to be a bug at all: a “More from artist” suggestions filter that a past session had deliberately scoped independent of the main playlist filter, documented as such in a comment I’d apparently written and then forgotten. Both got their own issues instead of getting silently folded into this one or, worse, guessed at and “fixed” wrong.
Related reading
A segfault that wasn't a bug, and the API I finally deleted
A MusicKit service-layer cleanup where deleting dead methods crashed every test at once - and the fix was a clean build, not a debugger.
Closing the test gaps: pure logic, an unreachable mock branch, and a Swift 6 flip
Extracting algorithms out of MusicKit's reach, a mock parameter that was silently ignored, and two tests that had been passing for the wrong reason all along.
My mocks couldn't fail: error injection and a Swift 6 isolation crash
Every catch branch was dead code in tests. A 15-line failure seam fixed that, and then one unannotated test suite took down the whole runner.
You might also find useful
Proton VPN
Commercial VPN with NetShield filtering and a kill switch.
As a Proton Partner, I earn from qualifying purchases of Proton's privacy and security services (Pass, Mail, VPN, Drive).
Learn moreAdGuard for iOS
System-wide ad and tracker blocking on iOS, no separate DNS server required.
As an AdGuard affiliate, I earn from qualifying purchases.
Learn moreRackNerd VPS
Budget VPS hosting for lightweight always-on services.
As a RackNerd affiliate, I earn from qualifying purchases.
Learn more