Fastlane: Make and Ship App Store Screenshots (2026 Guide)
fastlane es una suite de herramientas de Ruby para automatizar las partes aburridas del lanzamiento de aplicaciones iOS y Android. Sus tres acciones relacionadas con capturas de pantalla — snapshot, frameit y deliver — cubren todo el pipeline: ejecutan tu aplicación dentro de un XCUITest para capturar imágenes sin procesar, las envuelven en marcos de dispositivos con textos de marketing y suben el resultado a App Store Connect. Esta guía recorre todo el pipeline de extremo a extremo con los archivos de configuración, las definiciones de carriles (lanes) y el flujo de trabajo de CI que necesitas para ejecutarlo.
Al final tendrás: una configuración fijada con Ruby Bundler, una clave de API de App Store Connect, un Snapfile y un SnapshotHelper.swift en funcionamiento, un Framefile.json con palabras clave y títulos por captura de pantalla, un Deliverfile ajustado para subidas exclusivas de capturas de pantalla, un Fastfile de cuatro carriles (lanes) y un flujo de trabajo de GitHub Actions que ejecuta todo en un ejecutor macos-26.
1. Requisitos previos y modelo mental
Antes de instalar Ruby, ten clara la idea conceptual. El pipeline de capturas de pantalla consta de tres etapas independientes, cada una propiedad de una acción de fastlane distinta:
- Capturar — un XCUITest se ejecuta en un simulador y llama a
snapshot("01-Home")en los momentos que deseas registrar. La acciónsnapshotde fastlane inicia los simuladores correctos, cambia cada uno al idioma (locale) correspondiente, ejecuta la prueba y coloca los archivos PNG resultantes enfastlane/screenshots/<locale>/. - Enmarcar —
frameitlee cada archivo PNG, elige un marco de dispositivo basado en la resolución de la imagen, opcionalmente compone un fondo y un título de marketing, y escribe un archivo_framed.pngjunto al original. - Subir —
deliverrecorre la carpeta de capturas de pantalla, asocia cada imagen con una familia de pantallas de App Store Connect (por ejemplo, iPhone 6.9", iPad 13"), y reemplaza el conjunto de capturas de pantalla en la versión editable de la App Store mediante la API de App Store Connect.
Cada etapa se puede ejecutar de forma independiente. Puedes tomar capturas de pantalla sin subirlas, enmarcar capturas producidas por otra herramienta o subir capturas preparadas previamente sin tener que invocar el simulador.
2. Instalar fastlane de forma sensata: Bundler
No uses brew install fastlane. Fija la versión de fastlane por proyecto con Bundler para que todas las máquinas que compilan tu proyecto — tu portátil, el de un compañero, el sistema de CI — ejecuten la misma versión. Desde la raíz del proyecto:
# system Ruby on macOS 14+ is fine, but rbenv/asdf is cleaner
gem install bundler
bundle init
echo 'gem "fastlane"' >> Gemfile
bundle install --path vendor/bundle
# from now on, run fastlane via:
bundle exec fastlane <lane>Haz commit de Gemfile y Gemfile.lock. Añade vendor/bundle a tu .gitignore. Ahora inicializa fastlane en el proyecto:
bundle exec fastlane init
# choose option 4: "Manual setup"Esto crea un directorio fastlane/ con los archivos Fastfile y Appfile. Completa tu identificador de lote (bundle identifier) y el ID de tu equipo en Appfile:
# fastlane/Appfile
app_identifier("com.example.myapp")
apple_id("[email protected]") # only needed if you fall back to legacy auth
team_id("ABCDE12345") # Developer Portal team ID3. La clave de API de App Store Connect
La autenticación por usuario/contraseña está obsoleta para cuentas nuevas y protegida por doble factor para los demás, lo que la hace inservible en entornos de CI. En su lugar, usa una clave de API de App Store Connect . En App Store Connect → Usuarios y acceso → Integraciones → API de App Store Connect:
- Generar clave de API (solo se hace una vez por equipo; los archivos
.p8perdidos no se pueden volver a descargar). - Asígnala el rol de Gestor de aplicaciones. Desarrollador no es suficiente para subir capturas de pantalla; Administrador es más de lo que necesitas.
- Anota el ID de clave (10 caracteres, por ejemplo,
ABCD1234EF) y el ID de emisor del equipo (UUID en la parte superior de la misma página). - Descarga el archivo
AuthKey_ABCD1234EF.p8.
fastlane lee la clave de un archivo JSON. Guárdalo como fastlane/asc_api_key.json (y añade esa ruta a tu .gitignore):
// fastlane/asc_api_key.json
{
"key_id": "ABCD1234EF",
"issuer_id": "57246542-96fe-1a63-e053-0824d011072a",
"key": "-----BEGIN PRIVATE KEY-----\nMIGTAg...truncated...A==\n-----END PRIVATE KEY-----",
"duration": 1200,
"in_house": false
}duration es el tiempo de vida de cada JWT generado en segundos; el máximo que acepta Apple es 1200 (20 minutos). El campo key contiene todo el contenido del archivo .p8, incluyendo las líneas BEGIN/END PRIVATE KEY, utilizando \n literal para los saltos de línea.
En CI, nunca subas el JSON al repositorio. Almacena el contenido del JSON como un secreto único (por ejemplo, ASC_API_KEY_JSON) y escribe el archivo en tiempo de ejecución; abajo encontrarás un ejemplo en la sección de GitHub Actions.
4. snapshot — Capturar capturas de pantalla en XCUITest
snapshot funciona inyectando un pequeño asistente (helper) de Swift en tu target de pruebas de interfaz de usuario (UI). El asistente se integra en el entorno de ejecución de las pruebas de modo que cada llamada a snapshot("nombre") desde tu prueba tome una captura de la pantalla del simulador, le asigne un nombre y la escriba en una ubicación del disco que fastlane ya sabe cómo encontrar.
Generar el asistente
bundle exec fastlane snapshot initEsto crea fastlane/Snapfile y fastlane/SnapshotHelper.swift. Añade SnapshotHelper.swift a tu target de pruebas de interfaz de usuario en Xcode (arrástralo hacia adentro, asegúrate de que "MyAppUITests" sea el único target seleccionado; nunca lo incluyas en el binario de la aplicación).
Snapfile
Snapfile indica a snapshot qué dispositivos arrancar, en qué idiomas ejecutar cada prueba y qué esquema de pruebas de interfaz de usuario invocar:
# fastlane/Snapfile
devices([
"iPhone 17 Pro Max", # 6.9" -> 1320 x 2868 (required slot in 2026)
"iPhone 17 Pro", # 6.3" -> 1206 x 2622 (optional, nicer in store listings)
"iPad Pro 13-inch (M4)", # 13" -> 2064 x 2752 (required if you ship an iPad build)
])
languages([
"en-US",
"de-DE",
"fr-FR",
"es-ES",
"ja",
])
scheme("MyAppUITests") # the UI-testing scheme that runs Snapshot tests
output_directory("./fastlane/screenshots")
clear_previous_screenshots(true)
override_status_bar(true) # 9:41, full battery, full signal
concurrent_simulators(true)
stop_after_first_error(true)
number_of_retries(1)Puntos destacados:
devices— los nombres deben coincidir exactamente con lo que imprimexcrun simctl list devices. Apple cambia los nombres cada año (por ejemplo, "iPhone 17 Pro Max" reemplazó a "iPhone 16 Pro Max"). Si el nombre de un dispositivo es incorrecto, snapshot lo omitirá silenciosamente.languages— pasa un código de región como"en-US"o un código de idioma básico como"ja". Cada entrada genera una carpeta dentro deoutput_directory.override_status_bar(true)— utilizasimctl status_bar overridepara mostrar las 9:41, batería completa y señal completa de Wi-Fi/red celular en cada captura. Apple no lo exige estrictamente, pero la mayoría de los revisores lo esperan.concurrent_simulators— ejecuta múltiples simuladores en paralelo. Reduce el tiempo de ejecución aproximadamente por el número de dispositivos, pero cada simulador consume unos 3 GB de RAM, por lo que es exigente en entornos de CI con pocos recursos.clear_previous_screenshots— eliminafastlane/screenshots/<locale>/al inicio de cada ejecución. Sin esto, las capturas obsoletas de pruebas eliminadas se acumularán indefinidamente.
Conectar snapshot en tu XCUITest
SnapshotHelper expone dos funciones independientes: setupSnapshot(_:) (llámala una vez por prueba) y snapshot(_:) (llámala donde quieras registrar un fotograma).
// MyAppUITests/MyAppUITests.swift
import XCTest
final class MyAppUITests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
let app = XCUIApplication()
setupSnapshot(app) // injects the locale + screenshot bridge
app.launchArguments += [
"-UITests",
"-AppleLanguages", "(\(Snapshot.deviceLanguage))",
"-AppleLocale", Snapshot.currentLocale,
]
app.launch()
}
func testScreenshots() {
let app = XCUIApplication()
snapshot("01-Home") // tap pattern: drive UI, then snapshot
app.tabBars.buttons["Library"].tap()
snapshot("02-Library")
app.cells.element(boundBy: 0).tap()
snapshot("03-Detail")
app.navigationBars.buttons.element(boundBy: 0).tap()
app.tabBars.buttons["Settings"].tap()
snapshot("04-Settings")
}
}Algunas notas prácticas:
- Pasa
-UITestscomo argumento de lanzamiento y compruébalo en tu aplicación para desactivar la analítica, cargar datos semilla deterministas, saltarte el onboarding o simular respuestas de red. Los revisores (y tu yo del futuro) te lo agradecerán. snapshotse bloquea hasta que finaliza la captura de pantalla, por lo que puedes continuar inmediatamente con la siguiente interacción.- Si la interfaz tiene animaciones, añade
UIView.setAnimationsEnabled(false)controlado por un argumento de lanzamiento. Capturar en medio de una animación genera imágenes borrosas. - Nombra las capturas de pantalla con un prefijo numérico (
01-,02-) para que el orden del nombre de archivo coincida con el orden de visualización de App Store Connect.deliverlas sube en orden léxico.
Ejecutar snapshot
bundle exec fastlane snapshot
# or, equivalently, in a Fastfile lane:
# capture_ios_screenshotsEl resultado se almacena en fastlane/screenshots/<locale>/iPhone 17 Pro Max-01-Home.png y similares. Snapshot también genera screenshots.html; ábrelo para revisar todos los idiomas y dispositivos en una sola página.
5. frameit — Añadir marcos de dispositivos y títulos
Las capturas de pantalla sin procesar son solo vistas del dispositivo. frameit las envuelve en marcos físicos de dispositivos, opcionalmente añade un fondo, un título de marketing y una línea de "palabra clave" más pequeña por encima.
# Download device frames once (cached under ~/.frameit/)
bundle exec fastlane frameit download_frames
# Frame everything in fastlane/screenshots, including subfolders
bundle exec fastlane frameit --use_platform IOSPara cada archivo foo.png en la estructura de capturas, frameit escribe un archivo foo_framed.png junto a él. Los originales se conservan; deliver selecciona automáticamente la versión enmarcada si está disponible (y recurre a la versión sin procesar si no lo está).
Framefile.json
Los marcos por defecto parecen pruebas de desarrollo: marco negro, sin fondo y sin texto. Configúralos con fastlane/screenshots/Framefile.json:
// fastlane/screenshots/Framefile.json
{
"device_frame_version": "latest",
"default": {
"keyword": {
"font": "./fonts/Inter-SemiBold.ttf",
"color": "#FFFFFF",
"padding": 50
},
"title": {
"font": "./fonts/Inter-Bold.ttf",
"color": "#FFFFFF"
},
"background": "./background.png",
"padding": 80,
"show_complete_frame": false,
"title_below_image": false,
"stack_title": true
},
"data": [
{
"filter": "Home",
"keyword": { "color": "#9F7AEA" },
"frame": "BLACK"
},
{
"filter": "Settings",
"keyword": { "color": "#3B82F6" },
"frame": "WHITE"
}
]
}Campos clave:
background— una imagen PNG sobre la que se compone el dispositivo enmarcado. Debe ser más ancha que tu captura de pantalla más grande.frameitcentra el dispositivo verticalmente por defecto;title_below_imageyshow_complete_framecontrolan cómo interactúan el texto y el marco.data[]— anulaciones específicas por captura de pantalla filtradas por una subcadena del nombre de archivo de la captura. La segunda entrada de arriba solo se aplica a los archivos que contienen "Settings" en el nombre. Úsalo para tematizar con colores por fila.frame— anula el color del marco del dispositivo para los archivos que coincidan. Los valores queframeitreconoce enFramefile.jsonsonBLACK,WHITE,GOLDyROSE_GOLD. El arte del marco en sí se descarga de los archivos Sketch de recursos de marketing de Apple a través defastlane frameit download_frames.
Archivos title.strings y keyword.strings por idioma
Los textos de marketing provienen de dos archivos de cadenas paralelos por idioma: title.strings para el título principal y keyword.strings para la etiqueta más pequeña arriba. Las claves son los nombres de archivo de las capturas de pantalla sin extensión ni prefijo de dispositivo:
/* fastlane/screenshots/en-US/title.strings */
"01-Home" = "Track every match.\nIn one tap.";
"02-Library" = "Your full history,\nalways with you.";
"03-Detail" = "Drill into any session.";
"04-Settings" = "Sync across all devices.";/* fastlane/screenshots/en-US/keyword.strings */
/* keywords are rendered above the title, smaller */
"01-Home" = "FAST";
"02-Library" = "ORGANIZED";
"03-Detail" = "DEEP";
"04-Settings" = "EVERYWHERE";Las traducciones van en fastlane/screenshots/de-DE/title.strings y fastlane/screenshots/de-DE/keyword.strings, fastlane/screenshots/ja/title.strings, etc. Usa \n para saltos de línea. Los idiomas que falten usarán la captura de pantalla sin traducir (sin título renderizado); no hay fallback automático al inglés.
Fuentes
Coloca archivos TTF u OTF en fastlane/screenshots/fonts/ y haz referencia a ellos con una ruta relativa en Framefile.json. Se admiten fuentes variables. Si haces referencia a una fuente que no existe, frameit volverá silenciosamente a una tipografía sans-serif por defecto y el resultado se verá mal sin previo aviso.
6. deliver — Subir a App Store Connect
deliver recorre la carpeta de capturas de pantalla, asocia cada archivo PNG con una familia de pantallas de App Store Connect, y luego se comunica con la API de App Store Connect para reemplazar el conjunto de capturas en la versión actualmente editable. Con autenticación por clave de API y un Deliverfile bien enfocado, el paso de subida se reduce a un solo comando.
Estructura de carpetas
deliver espera una estructura plana por idioma, sin subcarpetas de dispositivos. La familia de pantallas se detecta a partir de la resolución de la imagen (y, en caso de ambigüedad, del prefijo de dispositivo en el nombre de archivo que snapshot ya añade):
fastlane/screenshots/
├── en-US/
│ ├── iPhone 17 Pro Max-01-Home_framed.png # 6.9" iPhone
│ ├── iPhone 17 Pro Max-02-Library_framed.png
│ ├── iPad Pro 13-inch (M4)-01-Home_framed.png # 13" iPad
│ ├── title.strings
│ └── keyword.strings
├── de-DE/
│ └── ...
└── Framefile.jsonDeliverfile
# fastlane/Deliverfile
app_identifier("com.example.myapp")
team_id("ABCDE12345")
# Auth via App Store Connect API key (preferred over username/password).
api_key_path("./fastlane/asc_api_key.json")
# Where to read screenshots / metadata from.
screenshots_path("./fastlane/screenshots")
metadata_path("./fastlane/metadata")
# Only push screenshots — leave the binary, pricing, IAPs, etc. alone.
skip_binary_upload(true)
skip_metadata(false)
skip_screenshots(false)
skip_app_version_update(true)
# Don't ask for confirmation in CI.
force(true)
overwrite_screenshots(true)
run_precheck_before_submit(false)
submit_for_review(false)
# Match a screenshot file against the right App Store display family.
# Useful when fastlane's resolution-based detection is ambiguous.
ignore_language_directory_validation(false)Los parámetros que más importan:
skip_binary_upload— sin esto,deliverbuscará un archivo IPA y se negará a ejecutarse si no está presente.skip_metadata— establécelo entruesi solo deseas subir capturas y no tienes un directoriofastlane/metadata/. Establécelo enfalsepara subir títulos localizados, descripciones, palabras clave y texto promocional en la misma llamada.force(true)— omite la pregunta de confirmación "¿Estás seguro?" quedelivermuestra antes de subir. Requerido en CI.overwrite_screenshots(true)— borra el conjunto de capturas existente en cada familia de pantallas antes de subir las nuevas. Sin esto, las nuevas subidas se añadirán a las antiguas hasta el límite de 10 capturas, y luego fallará.run_precheck_before_submit(false)—precheckanaliza los metadatos en busca de términos de riesgo ("Beta", nombres de competidores, palabras censuradas). Es ideal antes del envío, pero incorrecto para actualizaciones exclusivas de capturas de pantalla.
Simulación y luego envío
# verify which display families and locales will be touched, no upload
bundle exec fastlane deliver --verify_only
# inspect the resolved configuration
bundle exec fastlane deliver --print_resolved_options
# real upload
bundle exec fastlane deliverEn la primera subida real, deliver imprime una vista previa HTML en fastlane/preview.html y espera confirmación a menos que force(true) esté activado. Abre siempre la vista previa la primera vez en una nueva familia de dispositivos; ahí es cuando se hacen evidentes las discrepancias de familias de pantallas.
7. El archivo Fastfile completo
Un archivo con cuatro carriles (lanes) que cubren capturar, enmarcar, capturar+enmarcar y envío completo. El desarrollo local usa un carril y el sistema de CI usa otro.
# fastlane/Fastfile
default_platform(:ios)
platform :ios do
desc "Capture screenshots with snapshot"
lane :screenshots do
capture_ios_screenshots # alias for snapshot
end
desc "Frame screenshots with frameit"
lane :frame do
frame_screenshots(
path: "./fastlane/screenshots",
use_platform: "IOS"
)
end
desc "Build framed screenshots end-to-end"
lane :build_marketing do
capture_ios_screenshots
frame_screenshots(path: "./fastlane/screenshots", use_platform: "IOS")
end
desc "Upload screenshots to App Store Connect"
lane :upload_screenshots do
upload_to_app_store( # alias for deliver
skip_binary_upload: true,
skip_metadata: true,
skip_app_version_update: true,
force: true,
overwrite_screenshots: true,
run_precheck_before_submit: false
)
end
desc "Full release pipeline: capture, frame, upload"
lane :ship_screenshots do
capture_ios_screenshots
frame_screenshots(path: "./fastlane/screenshots", use_platform: "IOS")
upload_to_app_store(
skip_binary_upload: true,
skip_metadata: true,
skip_app_version_update: true,
force: true,
overwrite_screenshots: true
)
end
endcapture_ios_screenshots, frame_screenshots y upload_to_app_store son los nombres canónicos de snapshot, frameit y deliver. Los nombres cortos siguen funcionando, pero los largos son más claros y no chocan con palabras clave de Ruby.
8. CI en GitHub Actions
Las capturas de pantalla son lentas (15 minutos es lo habitual para 5 idiomas × 3 dispositivos) pero se pueden paralelizar bien entre simuladores. Un único ejecutor macos-26 con simuladores concurrentes suele ser suficiente.
# .github/workflows/screenshots.yml
name: Screenshots
on:
workflow_dispatch:
push:
paths:
- "fastlane/**"
- "MyAppUITests/**"
jobs:
screenshots:
runs-on: macos-26 # Xcode 26.x default; macos-15 also works with explicit xcode-select
timeout-minutes: 90
env:
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
FASTLANE_SKIP_UPDATE_CHECK: "1"
FASTLANE_HIDE_CHANGELOG: "1"
steps:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_26.3.app
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler-cache: true
- name: Write App Store Connect API key
run: |
mkdir -p fastlane
echo "$ASC_API_KEY_JSON" > fastlane/asc_api_key.json
env:
ASC_API_KEY_JSON: ${{ secrets.ASC_API_KEY_JSON }}
- name: Capture, frame, upload
run: bundle exec fastlane ios ship_screenshots
- name: Archive framed screenshots
if: always()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: fastlane/screenshotsCosas que hacen que las ejecuciones en CI sean fiables:
- Fijar la versión de Xcode. Usa
sudo xcode-select -scon una ruta explícita. Los ejecutores alojados en GitHub incluyen múltiples versiones de Xcode y la predeterminada es la que hayan decidido para ese mes. - Fijar la imagen del ejecutor. Usa una imagen con versión como
macos-26omacos-15, nomacos-latest. Una actualización del ejecutor tres semanas antes del lanzamiento es el tipo de sorpresa que quieres evitar. - Caché de la instalación de Bundler.
bundler-cache: trueensetup-rubyahorra un minuto o dos en cada ejecución. - Escribir la clave de API desde un único secreto. Almacenar
key_id,issuer_idykeycomo secretos separados es más cómodo para la rotación pero más propenso a errores. Un solo secreto estructurado como JSON está bien para equipos pequeños. - Subir las capturas enmarcadas como artefacto incluso si el paso de subida falla. Casi siempre querrás inspeccionar lo que se generó antes de volver a ejecutar.
9. Errores comunes y soluciones
"Could not find a device matching..."
Los nombres de dispositivos de Snapshot deben coincidir exactamente con xcrun simctl list devicetypes. Apple lanza un dispositivo nuevo cada año y el control de versiones basado en el calendario de Apple hace que la suite de herramientas avance rápido. "iPhone 17 Pro Max" se lanza con Xcode 26 (finales de 2025); en Xcode 16 el dispositivo de 6.9" era "iPhone 16 Pro Max". Después de cada actualización de Xcode, vuelve a ejecutar xcrun simctl list devicetypes | grep iPhone y actualiza Snapfile.
"Unable to verify upload" / 401 Unauthorized
Tu JWT expiró a mitad de la subida, la clave de API ha sido revocada o su rol fue degradado. Comprueba que duration en asc_api_key.json sea como máximo 1200 y luego vuelve a generar la clave.
"App Store Connect is locked"
La versión a la que estás subiendo está en estado En revisión o Pendiente de publicación por el desarrollador. Las capturas de pantalla son de solo lectura en estos estados. Crea una nueva versión (la sección "Preparar para el envío") y vuelve a ejecutar.
Las capturas de pantalla terminan en la familia de pantallas incorrecta
deliver asocia las imágenes por su resolución. Si exportaste una captura de iPhone de 6.9" a 1320 × 2868, caerá en el slot de 6.9"; si la escalaste a 1284 × 2778, caerá en el slot heredado de 6.5". Si ambas familias de pantallas existen en tu versión, proporciona la familia de dispositivos en el nombre del archivo (este es el prefijo que snapshot ya genera). Las exportaciones manuales a menudo lo omiten.
"Screenshot has alpha channel" / transparencia inesperada
App Store Connect ha rechazado históricamente los archivos PNG con transparencia, y deliver sigue advirtiendo cuando detecta un canal alfa. La página actual de especificaciones de capturas de Apple ya no menciona esta regla explícitamente, pero aplanar el canal alfa es la opción más segura. Procesa el archivo con sips -s format png con un perfil de color PNG, o vuelve a exportarlo sin canal alfa. El resultado compuesto de frameit siempre es opaco; la salida de simctl io ... screenshot sin procesar puede incluir alfa si tu vista raíz no es opaca.
"Locale ru-RU does not exist for this app"
deliver solo sube a los idiomas de App Store Connect que ya existen en la versión. Añade el idioma en App Store Connect primero (o define force_create_app(true) + metadatos en deliver) y luego vuelve a ejecutar.
Los simuladores concurrentes consumen toda la RAM
Cada simulador de iPhone 17 Pro Max iniciado con el teclado desplegado consume unos 2.5 GB. En un MacBook de 16 GB, ejecutar tres a la vez provocará uso de memoria swap y cuelgues a mitad de la prueba. Establece concurrent_simulators(false) localmente y deja que CI los ejecute en paralelo en un ejecutor más potente.
10. Cuándo fastlane es demasiado
El pipeline de capturas de pantalla de fastlane es excelente cuando:
- Ya tienes un target de pruebas de UI y tu equipo se siente cómodo manteniendo fixtures de XCUITest.
- Quieres que las capturas de pantalla sean un artefacto de CI, regenerado con cada versión.
- Localizas tu app y quieres que el diseño se defina una vez en el código, sin tener que rediseñarlo por idioma.
Es la opción incorrecta cuando:
- Quieres una dirección de arte completa en cada captura (tipografía, composición, elementos decorativos).
frameites un motor de plantillas, no una herramienta de diseño. - Necesitas enviar una captura de pantalla con calidad de marketing de una función que aún no existe en la aplicación, o que solo está detrás de un feature flag al que tu target de pruebas no puede acceder.
- Eres un desarrollador independiente que prefiere diseñar una vez en una aplicación de Mac y hacer clic en Subir. La suite de herramientas de Ruby más XCUITest más la fijación de versiones de Xcode representa una sobrecarga de mantenimiento real.
Para un flujo de trabajo centrado en el diseño, Screenshot Bro cubre el mismo terreno — diseños localizados, marcos de dispositivos y subida a App Store Connect con un solo clic con la misma clave de API — sin la complejidad de XCUITest.
Resumen rápido (TL;DR)
# Setup (once)
bundle init && echo 'gem "fastlane"' >> Gemfile && bundle install
bundle exec fastlane init
bundle exec fastlane snapshot init
bundle exec fastlane frameit download_frames
# Per release
bundle exec fastlane ship_screenshotsEse es todo el pipeline. Dos comandos al momento de instalar, un comando por lanzamiento. La complejidad reside en los archivos de configuración anteriores, y una vez escritos, apenas cambian.
¿Te preguntas si vale la pena configurar esto o si es mejor usar una aplicación de Mac para el mismo trabajo? Consulta Fastlane snapshot frente a Screenshot Bro para ver la comparación detallada y conocer el flujo de trabajo combinado.