Automatizando capturas de tela da loja com fastlane snapshot e frameit
8 min de leitura

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.

A
Escrito por
Começar a ler

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.

Principais pontos
  • 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

  1. Adicione um target de UI Test ao seu projeto do Xcode, se ainda não tiver um.
  2. Rode fastlane snapshot init na pasta do projeto. Ele cria um Snapfile e um SnapshotHelper.swift.
  3. Adicione o SnapshotHelper.swift ao 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 snapshot

Outras 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 variants

Uma 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íliaMoldura mais recente no repositórioAinda não tem
iPhoneiPhone 17, 17 Pro, 17 Pro MaxModelos iPhone 18, iPhone Air
iPadiPad Pro (12,9 polegadas) (4ª geração), iPad Pro (11 polegadas)iPad Pro de 13 polegadas e iPad Air (série M)
Google PixelPixel 5Pixel 6 em diante
SamsungFamília Galaxy S21Modelos Galaxy S mais novos
MacMacBook Air, MacBook Pro 13 e 16As 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_changelogs

O 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)
end

Se 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
CustoGratuito, open sourceDe planos grátis a planos pagos
ConfiguraçãoTestes de UI, Snapfile, Framefile, Ruby e ImageMagickEnviar as capturas, escolher um layout
Rodar de novo após uma mudança na interfaceUm comando, todos os dispositivos e idiomasCapturar de novo e substituir na mão
Controle visualConfiguração: fonte, cores, espaçamento, fundoUma tela de design visual
Molduras de dispositivoO que tiver no repositório de moldurasDepende da biblioteca da ferramenta
Fica no controle de versãoSimNormalmente 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.

Experimente agora

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 e override_status_bar(true).
  • Android: tools.fastlane:screengrab, LocaleTestRule, CleanStatusBar, Screengrab.screenshot(), um Screengrabfile.
  • frameit: ImageMagick, Framefile.json com um fundo, title.strings por 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.