Automatizando capturas de tela da loja com fastlane snapshot e frameit
Configure fastlane snapshot, screengrab e frameit para capturar, emoldurar e enviar capturas de tela pela CI, e veja quando essa automação compensa.
O fastlane automatiza as capturas de tela da loja em três etapas. O snapshot (iOS) e o screengrab (Android) rodam os seus testes de UI em simuladores ou emuladores em todos os idiomas que você listar e salvam uma captura em cada ponto que você marcar. O frameit coloca molduras de dispositivo, um fundo e um título em volta delas. O deliver e o supply enviam o resultado para o App Store Connect e o Google Play. Depois de configurado, gerar de novo todas as capturas de tela é um único comando.
Essa última frase é todo o atrativo, e a configuração é todo o custo. Este guia passa por cada peça com uma configuração que funciona e depois dá uma visão honesta de quando vale a pena.
- O fastlane snapshot roda testes de UI do Xcode nos dispositivos e idiomas de um Snapfile e salva uma captura de tela sempre que um teste chama snapshot("name").
- O screengrab é o equivalente no Android: ele roda testes de instrumentação, e Screengrab.screenshot("name") captura cada tela em fastlane/metadata/android.
- O frameit adiciona molduras de dispositivo, um fundo e títulos a partir de um Framefile.json e de arquivos title.strings por idioma; ele precisa do ImageMagick.
- As molduras do frameit ficam atrás do hardware novo: em outubro de 2026, o repositório de molduras parava na família iPhone 17, no iPad Pro de 12,9 polegadas (4ª geração) e no Pixel 5.
- A automação compensa para apps que lançam versões com frequência em vários idiomas; com um idioma só e lançamentos raros, capturar na mão costuma ser mais rápido.
Como o fastlane snapshot funciona
O fastlane snapshot usa os testes de UI do Xcode. Você escreve um teste de UI que percorre o seu app; em cada tela que vale mostrar, ele chama snapshot("01Home"). O snapshot roda esse teste uma vez para cada combinação de dispositivo e idioma e junta as imagens em fastlane/screenshots/<language>/.
Configuração
- Adicione um target de UI Test ao seu projeto do Xcode, se ainda não tiver um.
- Rode
fastlane snapshot initna pasta do projeto. Ele cria umSnapfilee umSnapshotHelper.swift. - Adicione o
SnapshotHelper.swiftao target de UI Test.
O teste de UI
import XCTest
final class ScreenshotTests: XCTestCase {
override func setUp() {
continueAfterFailure = false
let app = XCUIApplication()
setupSnapshot(app)
app.launchArguments += ["-demoData"]
app.launch()
}
func testStoreScreenshots() {
let app = XCUIApplication()
snapshot("01Home")
app.tabBars.buttons["Budget"].tap()
snapshot("02Budget")
app.buttons["Add expense"].tap()
snapshot("03AddExpense")
}
}O setupSnapshot(app) passa o idioma e a região atuais para o app, e é assim que um único teste gera todos os conjuntos localizados. O argumento -demoData é uma convenção nossa: o app procura por ele nas builds de debug e carrega conteúdo de exemplo, para que nenhuma captura de tela mostre um estado vazio. Colocar números no começo dos nomes mantém os arquivos na ordem de envio.
O Snapfile
# fastlane/Snapfile
devices([
"iPhone 17 Pro Max",
"iPad Pro 13-inch (M5)"
])
languages([
"en-US",
"de-DE",
"ja"
])
scheme("MyAppUITests")
output_directory("./fastlane/screenshots")
clear_previous_screenshots(true)
override_status_bar(true) # 9:41, full battery, full reception
dark_mode(false)
launch_arguments(["-demoData"])Os nomes dos dispositivos precisam bater com simuladores instalados no seu Xcode; o xcrun simctl list devicetypes mostra quais são. Um simulador de iPhone 17 Pro Max captura em 1320 × 2868, um dos tamanhos que o App Store Connect aceita para o espaço do maior iPhone. Depois rode:
fastlane snapshotOutras opções do snapshot que vale conhecer: localize_simulator também muda o idioma do sistema do simulador, erase_simulator começa cada execução com um dispositivo zerado, reinstall_app desinstala o app antes, e override_status_bar_arguments aceita as suas próprias flags do simctl status_bar. Se quiser saber o que essas flags fazem, o nosso guia sobre capturas de tela limpas no simulador e no emulador explica cada uma e os comandos manuais que o snapshot automatiza.
screengrab: o equivalente no Android
O screengrab faz o mesmo trabalho com testes de instrumentação do Android. Adicione a biblioteca às dependências de teste:
// app/build.gradle
androidTestImplementation 'tools.fastlane:screengrab:x.x.x'Garanta que o src/debug/AndroidManifest.xml inclua as permissões que a documentação lista (como DISABLE_KEYGUARD) e depois escreva o teste:
@RunWith(AndroidJUnit4.class)
public class ScreenshotTest {
@ClassRule
public static final LocaleTestRule localeTestRule = new LocaleTestRule();
@BeforeClass
public static void beforeAll() {
CleanStatusBar.enableWithDefaults();
}
@AfterClass
public static void afterAll() {
CleanStatusBar.disable();
}
@Rule
public ActivityScenarioRule<MainActivity> rule =
new ActivityScenarioRule<>(MainActivity.class);
@Test
public void storeScreenshots() {
Screengrab.screenshot("01_home");
onView(withId(R.id.nav_budget)).perform(click());
Screengrab.screenshot("02_budget");
}
}O LocaleTestRule troca a região a cada execução, e o CleanStatusBar é um wrapper do modo de demonstração da System UI do Android; a documentação avisa que ele exige API level 23 ou superior. Gere os APKs, crie um Screengrabfile e rode:
./gradlew assembleDebug assembleAndroidTest
fastlane screengrab init # creates the Screengrabfile
fastlane screengrab# fastlane/Screengrabfile
app_package_name("com.example.app")
app_apk_path("app/build/outputs/apk/debug/app-debug.apk")
tests_apk_path("app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
locales(["en-US", "de-DE", "ja-JP"])
clear_previous_screenshots(true)Por padrão, as capturas de tela vão para fastlane/metadata/android/<locale>/images/phoneScreenshots, que é exatamente onde o supply procura por elas. Uma coisa para conferir no Android: o Google Play rejeita capturas de tela cujo lado maior tenha mais que o dobro do lado menor, então escolha um perfil de emulador que não seja mais alto que 2:1.
frameit: molduras de dispositivo e títulos
O frameit pega as capturas brutas e coloca dentro de molduras de dispositivo. Ele precisa do ImageMagick (brew install imagemagick). As molduras são baixadas automaticamente na primeira vez que você roda.
fastlane frameit # iOS and Mac screenshots
fastlane frameit android # Android screenshots
fastlane frameit silver # silver frame variantsUma moldura de dispositivo sozinha não deixa a imagem automaticamente pronta para a App Store: a imagem emoldurada pode não bater com nenhum tamanho que o App Store Connect aceita. A documentação do fastlane diz que, para envios à App Store, você precisa de um Framefile.json com títulos e um fundo, o que gera uma imagem de marketing completa.
Framefile.json
Coloque-o na pasta screenshots:
{
"device_frame_version": "latest",
"default": {
"title": {
"font": "./fonts/Inter-Bold.ttf",
"font_size": 110,
"color": "#0F172A"
},
"keyword": {
"font": "./fonts/Inter-Bold.ttf",
"color": "#F97316"
},
"background": "./background.jpg",
"padding": 50,
"show_complete_frame": false,
"title_below_image": false
},
"data": [
{ "filter": "01Home" },
{ "filter": "02Budget", "keyword": { "color": "#3B82F6" } },
{ "filter": "03AddExpense" }
]
}Cada item de data corresponde às capturas de tela cujo nome de arquivo contém o seu filter, e pode sobrescrever os padrões. O texto em si fica em arquivos por idioma, title.strings e, opcionalmente, keyword.strings, dentro da pasta de cada idioma:
"01Home" = "See every euro, every month";
"02Budget" = "Budgets that adjust themselves";
"03AddExpense" = "Log a purchase in two taps";Essa linha vazia no começo é de propósito: a documentação diz que o arquivo precisa começar com uma, e precisa estar em UTF-8 ou UTF-16 BE com BOM. Ela também diz que você precisa fornecer um fundo se quiser títulos. Se os títulos não aparecerem, confira essas três coisas primeiro.
As molduras do frameit ficam atrás do hardware novo
As molduras do frameit vêm do repositório frameit-frames, que é separado, e as molduras são adicionadas depois que os aparelhos são lançados. Quando olhamos em outubro de 2026:
| Família | Moldura mais recente no repositório | Ainda não tem |
|---|---|---|
| iPhone | iPhone 17, 17 Pro, 17 Pro Max | Modelos iPhone 18, iPhone Air |
| iPad | iPad Pro (12,9 polegadas) (4ª geração), iPad Pro (11 polegadas) | iPad Pro de 13 polegadas e iPad Air (série M) |
| Google Pixel | Pixel 5 | Pixel 6 em diante |
| Samsung | Família Galaxy S21 | Modelos Galaxy S mais novos |
| Mac | MacBook Air, MacBook Pro 13 e 16 | As molduras de Mac usam uma imagem de fundo com um deslocamento, em vez de uma moldura de dispositivo |
Na prática, se você captura no simulador mais novo, pode não existir moldura para ele. Suas opções são capturar num dispositivo que tenha moldura (e aceitar que o tamanho da tela talvez não bata com o espaço da loja que você quer), forçar um tipo de dispositivo com force_device_type, ou abrir mão das molduras e usar um layout de tela cheia.
Enviando com deliver e supply
# iOS: upload only screenshots, replacing what's there
fastlane deliver --skip_binary_upload --skip_metadata --overwrite_screenshots
# Android: upload only images and screenshots
fastlane supply --skip_upload_apk --skip_upload_aab \
--skip_upload_metadata --skip_upload_changelogsO deliver lê fastlane/screenshots, com uma subpasta por idioma, e descobre o tipo de dispositivo pela resolução de cada imagem, então todo arquivo precisa estar num tamanho aceito antes do envio. O supply lê fastlane/metadata/android/<locale>/images/, com as pastas phoneScreenshots, sevenInchScreenshots e tenInchScreenshots. Encadeado numa lane, ir da captura ao envio é um único comando:
lane :screenshots do
snapshot
frameit(white: true)
deliver(skip_binary_upload: true, skip_metadata: true,
overwrite_screenshots: true)
endSe você não usa o fastlane mas ainda quer pular o envio manual, escrevemos sobre enviar direto para as lojas de apps a partir de uma ferramenta de design.
Pedras no caminho para se planejar
Nenhuma delas é motivo para não usar o fastlane, mas cada uma custa tempo na primeira semana se você não estiver esperando.
Testes de captura de tela são lentos, então mantenha-os separados
Uma execução é, mais ou menos, cada tela, vezes cada dispositivo, vezes cada idioma. Três dispositivos e dez idiomas são trinta passadas pelo seu teste. Deixe os testes de captura de tela num scheme ou test plan próprio, para que não rodem junto com todo teste unitário, e dispare-os nas branches de release ou manualmente, em vez de a cada commit.
Espere pelo conteúdo, não pelo tempo
Uma causa frequente de captura de tela ruim é capturar um instante cedo demais: um spinner, uma imagem carregada pela metade, uma lista ainda entrando com animação. Nos testes de UI, espere um elemento específico existir (waitForExistence(timeout:) no iOS, um idling resource do Espresso ou uma espera do UI Automator no Android) antes de chamar snapshot. Pausas fixas funcionam na sua máquina e falham num runner de CI mais lento.
Deixe os dados de demonstração determinísticos
Se a captura de tela mostra datas, “há 3 dias” muda todo dia, e os totais variam conforme as fixtures mudam. Fixe o relógio no seu modo de dados de demonstração, use fixtures fixas, e as capturas só mudam quando a interface muda. Isso também deixa o resultado comparável por diff no code review, uma das vantagens reais de manter as capturas de tela no controle de versão.
Interface traduzida é só metade de uma captura de tela localizada
O snapshot entrega a interface do app em cada idioma de graça. Os títulos em title.strings ainda precisam ser escritos para cada idioma, e uma tradução literal de um título em inglês com impacto muitas vezes perde o impacto. Nosso guia sobre como localizar capturas de tela da App Store fala do que adaptar além das palavras.
A CI precisa de um Mac com os simuladores certos
O snapshot roda no macOS com Xcode, então CI significa um runner macOS com os runtimes de simulador que o seu Snapfile cita instalados. Os nomes de dispositivo no Snapfile precisam bater com simuladores que existem nesse runner, então fixe a versão do Xcode que a sua CI usa e atualize o Snapfile quando mudar para uma nova.
Quando a automação compensa, e quando não compensa
A gente faz uma ferramenta de design, então leve isso em conta ao ler a nossa opinião. Mas o fastlane é, de verdade, a resposta certa para algumas equipes.
| fastlane (snapshot + frameit) | Uma ferramenta de design ou gerador | |
|---|---|---|
| Custo | Gratuito, open source | De planos grátis a planos pagos |
| Configuração | Testes de UI, Snapfile, Framefile, Ruby e ImageMagick | Enviar as capturas, escolher um layout |
| Rodar de novo após uma mudança na interface | Um comando, todos os dispositivos e idiomas | Capturar de novo e substituir na mão |
| Controle visual | Configuração: fonte, cores, espaçamento, fundo | Uma tela de design visual |
| Molduras de dispositivo | O que tiver no repositório de molduras | Depende da biblioteca da ferramenta |
| Fica no controle de versão | Sim | Normalmente não |
A automação costuma compensar quando:
- Você lança versões a cada poucas semanas e a interface que aparece nas capturas de tela muda entre elas.
- Você publica em muitos idiomas, e cada captura se multiplica pelo número de idiomas.
- Você já tem testes de UI, ou quer tê-los de qualquer jeito.
- Alguém da equipe se sente à vontade para cuidar de um conjunto de ferramentas com Ruby e ImageMagick na CI.
Costuma não compensar quando:
- Você publica em um ou dois idiomas e atualiza as capturas de tela algumas vezes por ano.
- As capturas de tela são um problema de design: layouts personalizados, ilustrações, um conjunto panorâmico.
- As suas telas precisam de um estado difícil de alcançar num teste de UI (pagamentos, dados ao vivo, outros usuários).
Muitas equipes ficam no meio-termo: o snapshot para capturas limpas e localizadas, e uma ferramenta de design para a camada de marketing por cima. Nossa comparação entre Launch Shots e fastlane frameit mostra isso, e se você está avaliando uma ferramenta de design, nosso guia sobre como fazer capturas de tela da App Store no Figma mostra a alternativa manual. O Launch Shots fica no segundo grupo: você traz as capturas (inclusive as do snapshot), e ele cuida do layout, da tradução e do envio.
Crie capturas de tela prontas para as lojas em minutos — grátis, sem marca d'água na exportação.
Você começa a usar o Launch Shots de graça. Todos os modelos (110+), mais de 220 molduras de dispositivo e mockups 3D, tradução por IA e upload direto para o App Store Connect e o Google Play Console. Sem cartão de crédito.
Começar grátis →A versão curta
- iOS: target de UI Test,
fastlane snapshot init,setupSnapshot(app),snapshot("01Home"), um Snapfile com dispositivos, idiomas eoverride_status_bar(true). - Android:
tools.fastlane:screengrab,LocaleTestRule,CleanStatusBar,Screengrab.screenshot(), um Screengrabfile. - frameit: ImageMagick,
Framefile.jsoncom um fundo,title.stringspor idioma começando com uma linha vazia. - Confira se o repositório de molduras tem o seu dispositivo de captura antes de depender dele.
- O deliver e o supply fazem o envio; antes, confira se todo arquivo está num tamanho aceito. Nossa referência de tamanhos de captura de tela e o checklist de ASO para o lançamento ajudam com o resto da página do app.
Perguntas frequentes
05- O que é o fastlane snapshot?
- O fastlane snapshot é uma ferramenta open source que automatiza capturas de tela no iOS. Ele roda os seus testes de UI do Xcode nos simuladores e idiomas listados num Snapfile e salva uma captura sempre que um teste chama snapshot("name"). Os resultados vão para pastas por idioma que o fastlane deliver consegue enviar ao App Store Connect. É gratuito e faz parte das ferramentas do fastlane.
- O fastlane frameit tem suporte aos iPhones mais recentes?
- As molduras de dispositivo do frameit vêm do repositório separado frameit-frames e são adicionadas depois que os novos aparelhos são lançados. Quando conferimos em outubro de 2026, o repositório tinha molduras da família iPhone 17, mas nenhuma para os modelos iPhone 18 nem para o iPhone Air, e a moldura de iPad Pro mais recente era a do de 12,9 polegadas de 4ª geração. Confira no repositório se o dispositivo em que você captura está lá antes de depender dele.
- Ainda vale a pena usar o fastlane snapshot?
- Vale quando você publica com frequência, em vários idiomas, e a interface do app muda entre as versões, porque gerar de novo todas as capturas de tela vira um único comando. Para um app com um só idioma e lançamentos esporádicos, o tempo gasto escrevendo e mantendo testes de UI para as capturas costuma ser maior do que capturar meia dúzia de telas na mão.
- Como deixar a barra de status limpa com o fastlane snapshot?
- Defina override_status_bar(true) no seu Snapfile. O fastlane snapshot então ajusta a barra de status de todos os simuladores para 9:41, com bateria cheia e sinal completo, antes de capturar. Para ter mais controle, override_status_bar_arguments repassa as suas próprias flags do simctl status_bar. No Android, o helper CleanStatusBar do screengrab faz o mesmo usando o modo de demonstração da System UI, a partir da API 23.
- O frameit consegue adicionar títulos de marketing às capturas de tela?
- Sim. O frameit lê um Framefile.json com layout, fontes e cores, e arquivos title.strings e keyword.strings por idioma com os textos, identificados por parte do nome do arquivo da captura. Para ter títulos, é obrigatório ter uma imagem de fundo. Ele gera capturas de tela com moldura e um título acima ou abaixo do dispositivo, mas as opções de layout são configuração, não uma tela de design visual.
