Automatiza tus capturas con fastlane snapshot y frameit
Configura fastlane snapshot, screengrab y frameit para hacer, enmarcar y subir capturas de pantalla desde CI, y descubre cuándo compensa esa automatización.
fastlane automatiza las capturas de pantalla de las tiendas en tres fases. snapshot (iOS) y screengrab (Android) ejecutan tus pruebas de interfaz en simuladores o emuladores en cada idioma que indiques y guardan una captura en cada punto que marques. frameit les pone alrededor un marco de dispositivo, un fondo y un titular. deliver y supply suben el resultado a App Store Connect y Google Play. Una vez configurado, regenerar todas las capturas es un solo comando.
Esa última frase es todo el atractivo, y la configuración es todo el costo. Esta guía recorre cada pieza con configuraciones que funcionan y luego da una visión honesta de cuándo compensa.
- fastlane snapshot ejecuta pruebas de interfaz de Xcode en los dispositivos e idiomas de un Snapfile y hace una captura cada vez que una prueba llama a snapshot("name").
- screengrab es el equivalente en Android: ejecuta pruebas de instrumentación, y Screengrab.screenshot("name") guarda cada pantalla en fastlane/metadata/android.
- frameit añade marcos de dispositivo, un fondo y títulos a partir de un Framefile.json y de archivos title.strings por idioma; necesita ImageMagick.
- Los marcos de frameit van por detrás del hardware nuevo: en octubre de 2026 su repositorio de marcos llegaba hasta la familia iPhone 17, el iPad Pro de 12,9 pulgadas (4.ª generación) y el Pixel 5.
- La automatización compensa en apps que publican a menudo en varios idiomas; con un solo idioma y pocas versiones, hacer las capturas a mano suele ser más rápido.
Cómo funciona fastlane snapshot
fastlane snapshot usa las pruebas de interfaz de Xcode. Escribes una prueba de interfaz que recorre tu app; en cada pantalla que valga la pena mostrar, llama a snapshot("01Home"). snapshot ejecuta esa prueba una vez por cada combinación de dispositivo e idioma y reúne las imágenes en fastlane/screenshots/<language>/.
Configuración
- Añade un target de UI Test a tu proyecto de Xcode si todavía no tienes uno.
- Ejecuta
fastlane snapshot initen la carpeta del proyecto. Crea unSnapfiley unSnapshotHelper.swift. - Añade
SnapshotHelper.swiftal target de UI Test.
La prueba de interfaz
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")
}
}setupSnapshot(app) le pasa a la app el idioma y la configuración regional actuales, y así es como una sola prueba genera todos los sets localizados. El argumento -demoData es una convención nuestra: la app lo detecta en las compilaciones de depuración y carga contenido de ejemplo, para que ninguna captura muestre un estado vacío. Poner números delante de los nombres mantiene los archivos en el orden de subida.
El 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"])Los nombres de dispositivo tienen que coincidir con simuladores instalados en tu Xcode; xcrun simctl list devicetypes los muestra. Un simulador de iPhone 17 Pro Max captura a 1320 × 2868, uno de los tamaños que App Store Connect acepta para su hueco de iPhone más grande. Después ejecuta:
fastlane snapshotOtras opciones de snapshot que conviene conocer: localize_simulator también cambia el idioma del sistema del simulador, erase_simulator empieza cada ejecución con un dispositivo limpio, reinstall_app desinstala la app primero y override_status_bar_arguments acepta tus propios flags de simctl status_bar. Si quieres saber qué hacen esos flags, nuestra guía de capturas limpias en simuladores y emuladores los explica, junto con los comandos manuales que snapshot automatiza.
screengrab: el equivalente en Android
screengrab hace el mismo trabajo con pruebas de instrumentación de Android. Añade la librería a tus dependencias de prueba:
// app/build.gradle
androidTestImplementation 'tools.fastlane:screengrab:x.x.x'Asegúrate de que src/debug/AndroidManifest.xml incluye los permisos que indica la documentación (como DISABLE_KEYGUARD) y escribe la prueba:
@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");
}
}LocaleTestRule cambia la configuración regional en cada ejecución, y CleanStatusBar es un envoltorio del modo demo de la interfaz del sistema de Android; la documentación indica que necesita el nivel de API 23 o superior. Compila los APK, genera un Screengrabfile y ejecútalo:
./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 defecto, las capturas van a fastlane/metadata/android/<locale>/images/phoneScreenshots, que es justo donde supply las busca. Una cosa que revisar en Android: Google Play rechaza las capturas cuyo lado largo mide más del doble que el corto, así que elige un perfil de emulador que no supere la proporción 2:1.
frameit: marcos de dispositivo y titulares
frameit toma las capturas en bruto y las mete dentro de marcos de dispositivo. Necesita ImageMagick (brew install imagemagick). Los marcos se descargan automáticamente la primera vez que lo ejecutas.
fastlane frameit # iOS and Mac screenshots
fastlane frameit android # Android screenshots
fastlane frameit silver # silver frame variantsUn marco de dispositivo por sí solo no deja la captura lista para el App Store: puede que la imagen enmarcada no coincida con ningún tamaño que App Store Connect acepte. La documentación de fastlane dice que, para subir al App Store, necesitas un Framefile.json con títulos y un fondo, que genera en su lugar una imagen de marketing completa.
Framefile.json
Ponlo en la carpeta 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 entrada de data se aplica a las capturas cuyo nombre de archivo contiene su filter, y puede sobrescribir los valores por defecto. El texto en sí va en archivos por idioma, title.strings y, opcionalmente, keyword.strings, dentro de la carpeta de cada idioma:
"01Home" = "See every euro, every month";
"02Budget" = "Budgets that adjust themselves";
"03AddExpense" = "Log a purchase in two taps";Esa línea vacía del principio es intencionada: la documentación dice que el archivo tiene que empezar con una, y estar en UTF-8 o en UTF-16 BE con BOM. También indica que tienes que poner un fondo si quieres títulos. Si los títulos no aparecen, revisa primero esas tres cosas.
Los marcos de frameit van por detrás del hardware nuevo
Los marcos de frameit vienen del repositorio frameit-frames, que es independiente, y los marcos se añaden después de que salgan los dispositivos. Cuando lo miramos en octubre de 2026:
| Familia | Marco más reciente en el repositorio | Todavía no está |
|---|---|---|
| iPhone | iPhone 17, 17 Pro, 17 Pro Max | Modelos iPhone 18, iPhone Air |
| iPad | iPad Pro (12,9 pulgadas) (4.ª generación), iPad Pro (11 pulgadas) | iPad Pro de 13 pulgadas y iPad Air (serie M) |
| Google Pixel | Pixel 5 | Pixel 6 y posteriores |
| Samsung | Familia Galaxy S21 | Modelos Galaxy S más recientes |
| Mac | MacBook Air, MacBook Pro 13 y 16 | Los marcos de Mac usan una imagen de fondo más un desplazamiento en lugar de un marco de dispositivo |
En la práctica, si haces las capturas en el simulador más nuevo, puede que no haya marco para él. Tus opciones: capturar en un dispositivo que tenga marco (y aceptar que su tamaño de pantalla quizá no coincida con el hueco de la tienda que quieres), forzar un tipo de dispositivo con force_device_type, o prescindir de los marcos y usar un diseño a sangre completa.
Subir con deliver y 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_changelogsdeliver lee fastlane/screenshots con una subcarpeta por idioma y deduce el tipo de dispositivo a partir de la resolución de cada imagen, así que cada archivo tiene que tener un tamaño aceptado antes de subirlo. supply lee fastlane/metadata/android/<locale>/images/, con las carpetas phoneScreenshots, sevenInchScreenshots y tenInchScreenshots. Si los encadenas en un lane, de la captura a la subida hay un solo comando:
lane :screenshots do
snapshot
frameit(white: true)
deliver(skip_binary_upload: true, skip_metadata: true,
overwrite_screenshots: true)
endSi no usas fastlane pero igualmente quieres ahorrarte la subida manual, escribimos sobre subir directamente a las tiendas de apps desde una herramienta de diseño.
Problemas prácticos para los que conviene prepararse
Ninguno es motivo para no usar fastlane, pero cada uno te cuesta tiempo la primera semana si no lo ves venir.
Las pruebas de capturas son lentas, así que tenlas aparte
Una ejecución es, más o menos, cada pantalla por cada dispositivo por cada idioma. Tres dispositivos y diez idiomas son treinta pasadas por tu prueba. Mantén las pruebas de capturas en su propio scheme o test plan para que no se ejecuten con cada prueba unitaria, y lánzalas en las ramas de release o a mano, no en cada commit.
Espera al contenido, no al reloj
Una causa habitual de una mala captura es hacerla un instante demasiado pronto: un indicador de carga, una imagen a medio cargar, una lista que todavía está animándose. En las pruebas de interfaz, espera a que exista un elemento concreto (waitForExistence(timeout:) en iOS, un idling resource de Espresso o una espera de UI Automator en Android) antes de llamar a snapshot. Las pausas fijas funcionan en tu máquina y fallan en un runner de CI más lento.
Haz que los datos de demo sean deterministas
Si la captura muestra fechas, «hace 3 días» cambia cada día, y los totales se descuadran cuando cambian los datos de prueba. Fija el reloj en tu modo de datos de demo, usa datos de prueba fijos, y las capturas solo cambiarán cuando cambie la interfaz. Eso además permite comparar los resultados en la revisión, que es una de las ventajas reales de tener las capturas en el control de versiones.
La interfaz traducida es solo la mitad de una captura localizada
snapshot te da la interfaz de la app en cada idioma sin esfuerzo. Los titulares de title.strings hay que escribirlos para cada idioma, y una traducción literal de un titular en inglés con gancho a menudo pierde el gancho. Nuestra guía sobre cómo localizar las capturas del App Store explica qué adaptar más allá de las palabras.
CI necesita un Mac con los simuladores adecuados
snapshot se ejecuta en macOS con Xcode, así que CI implica un runner de macOS con instalados los runtimes de simulador que nombra tu Snapfile. Los nombres de dispositivo del Snapfile tienen que coincidir con simuladores que existan en ese runner, así que fija la versión de Xcode que usa tu CI y actualiza el Snapfile cuando cambies a una nueva.
Cuándo compensa la automatización y cuándo no
Hacemos una herramienta de diseño, así que tómate nuestra opinión con eso en mente. Pero fastlane es de verdad la respuesta correcta para algunos equipos.
| fastlane (snapshot + frameit) | Una herramienta de diseño o generador | |
|---|---|---|
| Costo | Gratis, código abierto | De planes gratuitos a planes de pago |
| Configuración | Pruebas de interfaz, Snapfile, Framefile, Ruby e ImageMagick | Subir capturas, elegir un diseño |
| Volver a generar tras un cambio de interfaz | Un comando, todos los dispositivos e idiomas | Volver a capturar y reemplazar a mano |
| Control visual | Configuración: fuente, colores, márgenes, fondo | Un lienzo visual |
| Marcos de dispositivo | Los que tenga el repositorio de marcos | Depende de la biblioteca de la herramienta |
| Vive en el control de versiones | Sí | Normalmente no |
La automatización suele compensar cuando:
- Publicas cada pocas semanas y la interfaz que sale en tus capturas cambia entre versiones.
- Publicas en muchos idiomas, donde cada captura se multiplica por el número de idiomas.
- Ya tienes pruebas de interfaz, o las quieres igualmente.
- Alguien del equipo se siente cómodo encargándose de un conjunto de herramientas con Ruby e ImageMagick en CI.
Suele no compensar cuando:
- Publicas en uno o dos idiomas y actualizas las capturas unas pocas veces al año.
- Las capturas son un problema de diseño: diseños personalizados, ilustraciones, un set panorámico.
- Tus pantallas necesitan un estado difícil de alcanzar desde una prueba de interfaz (pagos, datos en vivo, otros usuarios).
Muchos equipos se quedan a medio camino: snapshot para capturas limpias y localizadas, y una herramienta de diseño para la capa de marketing encima. Nuestra comparativa de Launch Shots y fastlane frameit lo explica, y si estás valorando una herramienta de diseño, nuestra guía para hacer capturas del App Store en Figma muestra la alternativa manual. Launch Shots está en el segundo grupo: tú traes las capturas (incluidas las de snapshot) y se encarga del diseño, la traducción y la subida.
Diseña capturas listas para la tienda en minutos: gratis y sin marca de agua.
Empezar con Launch Shots es gratis. Todas las plantillas (más de 110), más de 220 marcos de dispositivo y mockups 3D, traducción con IA y subida directa a App Store Connect y Google Play Console. Sin tarjeta de crédito.
Empieza gratis →En resumen
- iOS: target de UI Test,
fastlane snapshot init,setupSnapshot(app),snapshot("01Home"), un Snapfile con dispositivos, idiomas yoverride_status_bar(true). - Android:
tools.fastlane:screengrab,LocaleTestRule,CleanStatusBar,Screengrab.screenshot(), un Screengrabfile. - frameit: ImageMagick,
Framefile.jsoncon un fondo,title.stringspor idioma empezando con una línea vacía. - Comprueba que el repositorio de marcos tiene tu dispositivo de captura antes de depender de él.
- deliver y supply se encargan de la subida; antes, comprueba que cada archivo tiene un tamaño aceptado. Nuestra referencia de tamaños de capturas y la lista de comprobación de ASO para el lanzamiento te ayudan con el resto de la ficha.
Preguntas frecuentes
05- ¿Qué es fastlane snapshot?
- fastlane snapshot es una herramienta de código abierto que automatiza las capturas de pantalla de iOS. Ejecuta tus pruebas de interfaz de Xcode en los simuladores e idiomas que indiques en un Snapfile y guarda una captura cada vez que una prueba llama a snapshot("name"). Los resultados quedan en carpetas por idioma que fastlane deliver puede subir a App Store Connect. Es gratis y forma parte de las herramientas de fastlane.
- ¿fastlane frameit es compatible con los últimos iPhone?
- Los marcos de dispositivo de frameit vienen del repositorio independiente frameit-frames y se añaden después de que salgan los dispositivos nuevos. Cuando lo revisamos en octubre de 2026, el repositorio tenía marcos de la familia iPhone 17, pero ninguno de los modelos iPhone 18 ni del iPhone Air, y su marco de iPad Pro más reciente era el de 12,9 pulgadas de 4.ª generación. Revisa el repositorio para el dispositivo con el que haces las capturas antes de depender de él.
- ¿Sigue valiendo la pena usar fastlane snapshot?
- Vale la pena cuando publicas a menudo, en varios idiomas, y la interfaz de tu app cambia entre versiones, porque regenerar todas las capturas pasa a ser un solo comando. Para una app en un solo idioma y con versiones ocasionales, el tiempo de escribir y mantener pruebas de interfaz para las capturas suele ser mayor que hacer a mano un puñado de pantallas.
- ¿Cómo consigo una barra de estado limpia con fastlane snapshot?
- Pon override_status_bar(true) en tu Snapfile. fastlane snapshot dejará la barra de estado de cada simulador en las 9:41, con la batería y la cobertura al máximo, antes de hacer las capturas. Para un control más fino, override_status_bar_arguments acepta tus propios flags de simctl status_bar. En Android, el helper CleanStatusBar de screengrab hace lo mismo usando el modo demo de la interfaz del sistema en API 23 y posteriores.
- ¿frameit puede añadir titulares de marketing a las capturas?
- Sí. frameit lee un Framefile.json con el diseño, las fuentes y los colores, y archivos title.strings y keyword.strings por idioma con el texto, identificado por una parte del nombre de archivo de la captura. Para los títulos hace falta una imagen de fondo. Genera capturas enmarcadas con un título encima o debajo del dispositivo, aunque las opciones de diseño se definen en la configuración, no en un lienzo visual.
