A 12-point TestFlight checklist for catching screenshot-related App Store rejections before you submit — status bar state, watermarks, localized text overflow, dark mode — plus what TestFlight can't catch and how to automate the rest in CI with XCTest.
Read the full article on Shotlingo →
Originally published on shotlingo.com — Shotlingo turns one screenshot template into pixel-perfect, localized App Store & Google Play screenshots in dozens of languages.
Top comments (2)
I particularly appreciate the emphasis on verifying localized text overflow in the article, as this is an often-overlooked aspect that can lead to App Store rejections. The suggestion to automate screenshot validation in CI using XCTest is also invaluable, as it can significantly reduce the manual effort required for testing. One potential improvement to this process could be integrating automated screenshot comparison tools to catch even the slightest visual discrepancies. Have you considered exploring the use of machine learning-based image comparison libraries to further enhance the automation of screenshot validation?
Thanks, good instinct, though I'd split it into two problems, because ML clearly wins one of them and mostly adds noise to the other.
The checks that are pure code state (debug banner, Lorem Ipsum, empty list) are better left as XCTest assertions. They're exact, fast, and they fail with a message that tells you what broke, with no baseline to maintain. Swapping those for image comparison would be a downgrade.
Text overflow is the interesting case, and you're right that assertions have a blind spot there. XCUIElement.label hands you the full string even when the label is visually truncated on screen, so a hierarchy assert passes happily on a clipped German string. Two ways out. The cheap one is exposing a truncation flag from inside the app behind a UI test launch argument and asserting on that, deterministic and free. The vision one is OCR on the captured frame, comparing what actually rendered against the string in your catalog. That catches clipping, and as a bonus it catches the case where the wrong locale's string rendered entirely.
Where I'd be careful is straight pixel diffing of localized screenshots. Every locale differs by design, so you need a baseline per locale, and those baselines rot on every UI change. You end up maintaining forty golden images and approving diffs, which is the same manual review work in a different outfit. If you do go visual, SSIM or a perceptual hash with a tolerance beats raw pixel equality, since an Xcode version bump alone changes antialiasing enough to trip a strict comparison.
The place a vision model genuinely earns its keep is the open ended stuff you can't enumerate as assertions. Is there a permission sheet mid capture, is a real email address visible, does that banner look like a staging ribbon. Those are fuzzy visual categories, one pass per frame, cheap enough to run across a full export set. I'd have it annotate rather than fail the build though, at least until you trust its false positive rate.
Haven't wired that into CI myself yet. If you have, I'd be curious what the false positive rate looked like on the localized frames specifically.