Las pruebas de juegos móviles presentan desafíos únicos que van mucho más allá del QA tradicional de aplicaciones móviles. Los juegos exigen rendimiento en tiempo real, experiencias multijugador fluidas y consumo optimizado de recursos en miles de configuraciones de dispositivos. Esta guía completa explora enfoques especializados de pruebas para aplicaciones de juegos móviles, desde monitoreo de rendimiento hasta pruebas automatizadas en Unity y Unreal Engine.
Introducción a los Desafíos de Pruebas de Juegos Móviles
Los juegos móviles operan en un entorno excepcionalmente exigente. A diferencia de las aplicaciones web o empresariales, los juegos deben mantener renderizado consistente a 60 FPS, responder a entradas táctiles en milisegundos, gestionar restricciones de memoria en dispositivos de gama baja y ofrecer experiencias atractivas en dispositivos que van desde teléfonos Android (como se discute en Mobile App Performance Testing: Metrics, Tools, and Best Practices) (como se discute en Appium 2.0: New Architecture and Cloud Integration for Modern Mobile Testing) económicos hasta iPhones insignia.
Desafíos clave específicos de pruebas de juegos móviles:
- Variabilidad de rendimiento: El mismo código del juego funciona drásticamente diferente en varios hardwares
- Requisitos en tiempo real: Caídas de frames y latencia impactan directamente la experiencia de juego
- Restricciones de recursos: Batería, memoria y límites térmicos afectan el comportamiento del juego
- Dependencia de red: Juegos multijugador requieren manejo robusto de conectividad
- Complejidad de monetización: Compras in-app, anuncios y economías virtuales necesitan pruebas rigurosas
- Actualizaciones frecuentes: Los juegos reciben actualizaciones de contenido más frecuentemente que las apps típicas
Probar juegos móviles requiere tanto habilidades tradicionales de QA como conocimiento especializado de renderizado gráfico, motores de juego, perfilado de rendimiento y métricas de experiencia del jugador.
Pruebas de Rendimiento: FPS, Caídas de Frames y Renderizado
La tasa de frames es la métrica de rendimiento más crítica para juegos móviles. Los jugadores notan inmediatamente cuando los FPS caen por debajo de 60 (o 30 para dispositivos de gama baja), lo que lleva a malas reseñas y abandono de usuarios.
Enfoques de Medición de FPS
Integración con Unity Profiler:
using UnityEngine;
using UnityEngine.Profiling;
public class FPSMonitor : MonoBehaviour
{
private float deltaTime = 0.0f;
private int frameCount = 0;
private float fpsSum = 0.0f;
void Update()
{
deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f;
float fps = 1.0f / deltaTime;
frameCount++;
fpsSum += fps;
// Registrar métricas cada 60 frames
if (frameCount >= 60)
{
float avgFPS = fpsSum / frameCount;
LogPerformanceMetric("AvgFPS", avgFPS);
LogPerformanceMetric("MemoryUsage", Profiler.GetTotalAllocatedMemoryLong() / 1048576f);
frameCount = 0;
fpsSum = 0.0f;
}
}
void LogPerformanceMetric(string metricName, float value)
{
Debug.Log($"[Performance] {metricName}: {value:F2}");
// Enviar a servicio de analytics
}
}
Android ADB Frame Stats:
# Monitorear FPS en tiempo real en dispositivo Android
adb shell dumpsys gfxinfo com.tujuego.paquete framestats
# Extraer datos de timing de frames
adb shell dumpsys gfxinfo com.tujuego.paquete | grep "50th\|90th\|95th\|99th"
# Monitoreo continuo de FPS con timestamp
while true; do
echo "$(date +%H:%M:%S) - $(adb shell dumpsys gfxinfo com.tujuego.paquete | grep 'Total frames rendered')"
sleep 5
done
iOS Instruments:
Usar la plantilla Game Performance de Xcode Instruments para monitorear:
- Tasa de frames (FPS)
- Utilización de GPU
- Uso de CPU por núcleo
- Asignaciones de memoria
- Tiempo de compilación de shaders
Análisis de Caídas de Frames
Las caídas de frames ocurren cuando el renderizado toma más tiempo que el presupuesto de frame (16.67ms para 60 FPS, 33.33ms para 30 FPS).
Objetivo FPS | Presupuesto Frame | Caídas Aceptables | Umbral Crítico |
---|---|---|---|
60 FPS | 16.67ms | <5% frames >20ms | >10% frames >20ms |
30 FPS | 33.33ms | <5% frames >40ms | >10% frames >40ms |
120 FPS | 8.33ms | <5% frames >12ms | >10% frames >12ms |
Causas comunes de caídas de frames:
- Picos de draw calls: Demasiados objetos renderizados simultáneamente
- Presión de GC: Pausas de recolección de basura en Unity/C#
- Cálculos de física: Detección de colisión compleja
- Compilación de shaders: Carga de shader por primera vez
- Carga de assets: Carga sincrónica de recursos durante gameplay
Pruebas de Consumo de Memoria y Batería
Los dispositivos móviles tienen límites estrictos de memoria y restricciones de batería. Los juegos deben optimizar ambos para prevenir crashes y reseñas negativas.
Estrategia de Pruebas de Memoria
Unity Memory Profiler:
using UnityEngine;
using System;
public class MemoryTracker : MonoBehaviour
{
private long lastMemoryUsage = 0;
public void TrackMemoryUsage(string sceneName)
{
// Forzar recolección de basura para medición precisa
GC.Collect();
System.Threading.Thread.Sleep(100);
long totalMemory = GC.GetTotalMemory(false);
long nativeMemory = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong();
Debug.Log($"[Memory] Scene: {sceneName}");
Debug.Log($" Managed Heap: {totalMemory / 1048576f:F2} MB");
Debug.Log($" Native Memory: {nativeMemory / 1048576f:F2} MB");
Debug.Log($" Delta: {(nativeMemory - lastMemoryUsage) / 1048576f:F2} MB");
lastMemoryUsage = nativeMemory;
// Alertar si la memoria excede umbrales
if (nativeMemory > 1024 * 1048576) // 1GB
{
Debug.LogWarning("Uso de memoria excede 1GB - riesgo potencial de crash en dispositivos de gama baja");
}
}
}
Checklist de pruebas de memoria:
- Uso base de memoria en menú principal
- Crecimiento de memoria durante sesiones extendidas de juego (30+ minutos)
- Uso pico de memoria durante escenas intensivas
- Memoria liberada después de transiciones de escena
- Huella de memoria de texturas por configuración de calidad
- Detección de fugas de memoria (uso creciente sin meseta)
Pruebas de Consumo de Batería
Android Battery Stats:
# Resetear estadísticas de batería
adb shell dumpsys batterystats --reset
# Jugar juego durante duración de prueba (ej., 30 minutos)
# Extraer datos de consumo de batería
adb shell dumpsys batterystats com.tujuego.paquete
# Obtener uso específico de batería de la app
adb shell dumpsys batterystats | grep -A 20 "com.tujuego.paquete"
Objetivos de optimización de batería:
Tier Dispositivo | Drenaje Máx Batería | Duración Prueba | Temp Aceptable |
---|---|---|---|
Flagship | 20% por hora | 1 hora | <42°C |
Gama media | 25% por hora | 1 hora | <45°C |
Gama baja | 30% por hora | 1 hora | <48°C |
Contribuidores al drenaje de batería:
- Renderizado GPU: Gráficos de alta calidad, efectos de post-procesamiento
- Actividad de red: Llamadas API frecuentes, multijugador en tiempo real
- Brillo de pantalla: Siempre probar al 100% de brillo
- Servicios en segundo plano: Analytics, anuncios, notificaciones push
- Wake locks: Prevenir suspensión del dispositivo durante gameplay
Pruebas de Latencia de Red y Multijugador
Los juegos multijugador son extremadamente sensibles a las condiciones de red. Las pruebas deben cubrir varios escenarios de conectividad.
Medición de Latencia
Prueba de Ping Multijugador Unity:
using UnityEngine;
using System.Net.NetworkInformation;
using System.Diagnostics;
public class NetworkMonitor : MonoBehaviour
{
private Ping ping;
private Stopwatch stopwatch;
public void MeasureLatency(string serverAddress)
{
ping = new Ping();
stopwatch = Stopwatch.StartNew();
ping.SendAsync(serverAddress, 1000, null);
ping.PingCompleted += PingCompletedCallback;
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
long latency = e.Reply.RoundtripTime;
LogLatencyMetric(latency);
if (latency > 150)
UnityEngine.Debug.LogWarning($"Alta latencia detectada: {latency}ms");
}
}
private void LogLatencyMetric(long latency)
{
UnityEngine.Debug.Log($"[Network] Latency: {latency}ms");
// Categorizar experiencia
string quality = latency < 50 ? "Excelente" :
latency < 100 ? "Buena" :
latency < 150 ? "Regular" : "Pobre";
UnityEngine.Debug.Log($"[Network] Calidad de Conexión: {quality}");
}
}
Pruebas de Condiciones de Red
Escenarios de prueba:
Escenario | Latencia | Pérdida Paquetes | Ancho Banda | Comportamiento Esperado |
---|---|---|---|---|
WiFi Excelente | 20-50ms | 0% | 50 Mbps | Calidad completa, sin lag |
4G Bueno | 50-100ms | 0-1% | 20 Mbps | Gameplay fluido |
4G Pobre | 100-200ms | 1-3% | 5 Mbps | Compensación latencia activa |
3G | 200-500ms | 3-5% | 2 Mbps | Calidad reducida, advertencias |
Cambio red | Varía | Picos | Varía | Manejo de reconexión |
Herramientas para simulación de red:
- Charles Proxy: Limitar ancho de banda, simular latencia
- Network Link Conditioner (iOS): Perfiles de red preestablecidos
- Opciones Desarrollador Android: Limitar datos en segundo plano
- Unity Network Simulator: Emulación integrada de condiciones de red
Unity Testing Framework y Automatización de Pruebas
Unity proporciona frameworks completos de pruebas para testing automatizado de juegos.
Unity Test Framework
Ejemplo de Prueba PlayMode:
using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
public class GameplayTests
{
[UnityTest]
public IEnumerator PlayerTakesDamageCorrectly()
{
// Arrange: Cargar escena de juego
UnityEngine.SceneManagement.SceneManager.LoadScene("GameScene");
yield return null; // Esperar un frame para carga de escena
var player = GameObject.FindObjectOfType<PlayerController>();
int initialHealth = player.Health;
// Act: Aplicar daño
player.TakeDamage(25);
yield return new WaitForSeconds(0.1f);
// Assert: Verificar que la salud disminuyó
Assert.AreEqual(initialHealth - 25, player.Health);
Assert.IsTrue(player.IsAlive);
}
[UnityTest]
public IEnumerator GameMaintains60FPSUnderLoad()
{
// Arrange: Generar 100 enemigos
var enemyPrefab = Resources.Load<GameObject>("Enemy");
for (int i = 0; i < 100; i++)
{
GameObject.Instantiate(enemyPrefab, Random.insideUnitSphere * 50, Quaternion.identity);
}
yield return null;
// Act: Monitorear FPS por 5 segundos
float testDuration = 5.0f;
float elapsed = 0;
int frameCount = 0;
float totalFPS = 0;
while (elapsed < testDuration)
{
totalFPS += 1.0f / Time.unscaledDeltaTime;
frameCount++;
elapsed += Time.unscaledDeltaTime;
yield return null;
}
float avgFPS = totalFPS / frameCount;
// Assert: FPS promedio debe estar sobre 55 (permitiendo margen de 5 FPS)
Assert.Greater(avgFPS, 55f, $"FPS promedio fue {avgFPS:F1}, esperado >55");
}
}
Pruebas EditMode para Lógica de Juego
using NUnit.Framework;
public class InventorySystemTests
{
private InventorySystem inventory;
[SetUp]
public void Setup()
{
inventory = new InventorySystem(maxSlots: 20);
}
[Test]
public void AddItem_IncreasesItemCount()
{
// Arrange
var item = new Item("Health Potion", ItemType.Consumable);
// Act
bool added = inventory.AddItem(item);
// Assert
Assert.IsTrue(added);
Assert.AreEqual(1, inventory.ItemCount);
}
[Test]
public void AddItem_ExceedingMaxSlots_ReturnsFalse()
{
// Arrange
for (int i = 0; i < 20; i++)
{
inventory.AddItem(new Item($"Item{i}", ItemType.Material));
}
// Act
bool added = inventory.AddItem(new Item("ExtraItem", ItemType.Material));
// Assert
Assert.IsFalse(added);
Assert.AreEqual(20, inventory.ItemCount);
}
}
Enfoques de Pruebas en Unreal Engine
Unreal Engine proporciona el framework de Automation Testing y Gauntlet para pruebas de juegos.
Pruebas de Automatización Unreal
Ejemplo de Prueba Funcional en C++:
#include "Tests/AutomationCommon.h"
#include "Misc/AutomationTest.h"
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FPlayerMovementTest,
"Game.Player.Movement",
EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter
)
bool FPlayerMovementTest::RunTest(const FString& Parameters)
{
// Arrange: Obtener personaje del jugador
APlayerCharacter* Player = GetWorld()->SpawnActor<APlayerCharacter>();
FVector InitialLocation = Player->GetActorLocation();
// Act: Simular movimiento hacia adelante por 1 segundo
Player->MoveForward(1.0f);
GetWorld()->Tick(LEVELTICK_All, 1.0f);
// Assert: El jugador debería haberse movido hacia adelante
FVector FinalLocation = Player->GetActorLocation();
TestTrue("Player moved forward", FinalLocation.X > InitialLocation.X);
// Cleanup
Player->Destroy();
return true;
}
Framework Gauntlet para Pruebas de Integración
Prueba Funcional en Blueprint:
Gauntlet permite pruebas de gameplay scripteadas:
- Crear escenarios de prueba en Blueprint
- Definir condiciones de éxito/fallo
- Ejecutar pruebas en servidores de build
- Generar reportes de prueba con capturas de pantalla
Ejemplo de controlador de prueba Gauntlet:
class FGamePerformanceTest : public FAutomationTestBase
{
public:
bool RunPerfTest()
{
// Lanzar juego con mapa específico
LaunchGame("TestMap_Combat");
// Esperar inicialización del juego
WaitForGameReady();
// Generar escenario de prueba (100 enemigos AI)
SpawnEnemies(100);
// Monitorear rendimiento por 60 segundos
bool PassedFPSTest = MonitorFPS(60.0f, MinFPS: 30.0f);
bool PassedMemoryTest = MonitorMemory(60.0f, MaxMB: 2048);
return PassedFPSTest && PassedMemoryTest;
}
};
Fragmentación de Dispositivos y Compatibilidad
Los juegos móviles deben funcionar en miles de configuraciones de dispositivos.
Estrategia de Cobertura de Dispositivos
Enfoque de pruebas basado en tiers:
Tier | Cobertura | Dispositivos Ejemplo | Prioridad |
---|---|---|---|
Tier 1 | Top 5 dispositivos | iPhone 15 Pro, Galaxy S24, Pixel 8 | Crítica |
Tier 2 | Gama media popular | iPhone SE, Galaxy A54, Pixel 7a | Alta |
Tier 3 | Gama baja/legacy | Android económico, iPhone 12 | Media |
Tier 4 | Casos extremos | Tablets, plegables, resoluciones inusuales | Baja |
Factores críticos de fragmentación:
- Variaciones de GPU: Mali, Adreno, PowerVR, GPUs Apple se comportan diferente
- Resoluciones de pantalla: Probar relaciones de aspecto de 16:9 a 21:9
- Versiones de SO: Soportar 2-3 años de historial de SO
- Configuraciones de RAM: Dispositivos de 2GB a 12GB+ RAM
- Tipos de almacenamiento: UFS, eMMC afectan tiempos de carga
Pruebas Automatizadas de Dispositivos
Integración con Firebase Test Lab:
# test_matrix.yaml
platforms:
- name: Android
devices:
- model: flame # Pixel 4
version: 29
orientation: portrait
- model: starqlteue # Galaxy S9+
version: 28
orientation: landscape
- model: OnePlus7
version: 30
orientation: portrait
test-targets:
- game-launch-test
- tutorial-completion-test
- 30min-gameplay-test
Pruebas de Compras In-App y Monetización
La monetización de juegos requiere pruebas rigurosas de flujos de pago, economías virtuales e integraciones de anuncios.
Checklist de Pruebas IAP
Verificación de flujo de compra:
using UnityEngine;
using UnityEngine.Purchasing;
public class IAPTestValidator
{
public void ValidatePurchaseFlow(Product product)
{
// Escenarios de prueba:
// 1. Compra exitosa
Assert.True(ProcessPurchase(product.transactionID));
Assert.True(VerifyReceipt(product.receipt));
Assert.True(GrantVirtualGoods(product.definition.id));
// 2. Cancelación de compra
CancelPurchase(product);
Assert.False(WasVirtualGoodsGranted(product.definition.id));
// 3. Restauración de compra
RestorePurchases();
Assert.True(NonConsumablesRestored());
// 4. Fallo de red durante compra
SimulateNetworkFailure();
Assert.True(PurchaseQueuedForRetry(product));
}
}
Casos de prueba IAP comunes:
- Éxito de compra con entrega inmediata
- Manejo de fallo de compra (fondos insuficientes, cancelada)
- Interrupción de red durante compra
- Validación de recibo (Apple/Google)
- Restauración de compra en nuevo dispositivo
- Renovación y expiración de suscripción
- Manejo de reembolsos
- Precisión de conversión de moneda
Pruebas de Integración de Anuncios
Escenarios de prueba para anuncios:
Tipo Anuncio | Casos de Prueba | Criterio de Éxito |
---|---|---|
Video Recompensado | Completar reproducción, cierre temprano, sin anuncio disponible | Recompensa otorgada solo al completar |
Intersticial | Timing, limitación frecuencia, botón cerrar | No intrusivo, respeta cooldowns |
Banner | Posicionamiento, tasa de refresco, click-through | No obstruye gameplay |
Pruebas de Balance y Progresión del Juego
El balance del juego requiere pruebas basadas en datos y análisis de comportamiento del jugador.
Seguimiento de Métricas de Progresión
using UnityEngine;
public class ProgressionAnalytics
{
public void TrackLevelCompletion(int levelID, float completionTime, int attempts)
{
// Calcular métricas de dificultad
float avgCompletionTime = GetAverageCompletionTime(levelID);
float completionRate = GetCompletionRate(levelID);
// Señalar problemas de balance
if (completionRate < 0.4f)
{
Debug.LogWarning($"Nivel {levelID} tiene baja tasa de completación: {completionRate:P0}");
}
if (completionTime > avgCompletionTime * 2)
{
Debug.Log($"Jugador luchó con nivel {levelID} - tomó {completionTime:F1}s vs promedio {avgCompletionTime:F1}s");
}
// Seguir ritmo de progresión
LogMetric("level_completion", new {
level = levelID,
duration = completionTime,
attempts = attempts,
player_level = GetPlayerLevel(),
equipment_power = GetEquipmentPower()
});
}
}
Áreas de enfoque de pruebas de balance:
- Balance de economía: Tasas de ganancia vs gasto de moneda
- Curva de dificultad: Incremento gradual de desafío
- Tiempo de progresión: Horas necesarias para avance significativo
- Presión de monetización: Brecha de experiencia F2P vs jugadores de pago
- Bucles de engagement: Tasas de completación de misiones diarias
Pruebas de Carga y Estrés para Juegos Online
Los juegos online requieren pruebas robustas del lado del servidor.
Estrategia de Pruebas de Carga
Script de simulación para prueba de estrés de matchmaking:
import asyncio
import aiohttp
import time
class GameServerLoadTest:
def __init__(self, server_url, concurrent_users):
self.server_url = server_url
self.concurrent_users = concurrent_users
self.results = []
async def simulate_player(self, player_id):
async with aiohttp.ClientSession() as session:
# Conectar a servidor
start_time = time.time()
async with session.ws_connect(f"{self.server_url}/game") as ws:
# Autenticar
await ws.send_json({
"action": "authenticate",
"player_id": player_id
})
# Unirse a matchmaking
await ws.send_json({
"action": "join_matchmaking",
"game_mode": "ranked"
})
# Esperar partida
match_found = False
while not match_found:
msg = await ws.receive_json()
if msg["type"] == "match_found":
match_time = time.time() - start_time
self.results.append({
"player_id": player_id,
"match_time": match_time
})
match_found = True
async def run_test(self):
tasks = [
self.simulate_player(f"player_{i}")
for i in range(self.concurrent_users)
]
await asyncio.gather(*tasks)
# Analizar resultados
avg_match_time = sum(r["match_time"] for r in self.results) / len(self.results)
print(f"Tiempo promedio de matchmaking: {avg_match_time:.2f}s")
print(f"Partidas exitosas: {len(self.results)}/{self.concurrent_users}")
# Ejecutar prueba con 1000 jugadores concurrentes
test = GameServerLoadTest("wss://game-server.example.com", 1000)
asyncio.run(test.run_test())
Objetivos de pruebas de carga:
Métrica | Objetivo | Advertencia | Crítico |
---|---|---|---|
Usuarios concurrentes | 10,000+ | 5,000 | <2,000 |
Tiempo matchmaking | <10s | 10-20s | >30s |
Tiempo respuesta servidor | <100ms | 100-200ms | >300ms |
Pérdida paquetes | <0.5% | 0.5-2% | >3% |
Pruebas de Calidad Gráfica en Dispositivos
La calidad visual debe escalar apropiadamente en los tiers de dispositivos.
Validación de Configuraciones de Calidad
Prueba automatizada de preset de calidad:
using UnityEngine;
public class QualityPresetTester : MonoBehaviour
{
[System.Serializable]
public class QualityBenchmark
{
public string qualityLevel;
public float minFPS;
public float maxMemoryMB;
public float testDuration;
}
public QualityBenchmark[] benchmarks = new QualityBenchmark[]
{
new QualityBenchmark { qualityLevel = "Low", minFPS = 30, maxMemoryMB = 512, testDuration = 60 },
new QualityBenchmark { qualityLevel = "Medium", minFPS = 45, maxMemoryMB = 768, testDuration = 60 },
new QualityBenchmark { qualityLevel = "High", minFPS = 60, maxMemoryMB = 1024, testDuration = 60 }
};
public void RunQualityTests()
{
foreach (var benchmark in benchmarks)
{
QualitySettings.SetQualityLevel(GetQualityLevelIndex(benchmark.qualityLevel));
float avgFPS = MeasureAverageFPS(benchmark.testDuration);
float peakMemory = MeasurePeakMemory(benchmark.testDuration);
bool fpsPass = avgFPS >= benchmark.minFPS;
bool memoryPass = peakMemory <= benchmark.maxMemoryMB;
Debug.Log($"Calidad: {benchmark.qualityLevel} - FPS: {avgFPS:F1} (objetivo: {benchmark.minFPS}) - Memoria: {peakMemory:F0}MB (máx: {benchmark.maxMemoryMB}MB)");
Debug.Log($"Resultado: {(fpsPass && memoryPass ? "PASS" : "FAIL")}");
}
}
}
Pruebas de regresión visual:
Usar herramientas de comparación de capturas de pantalla para detectar cambios visuales no intencionados:
- Capturar capturas de pantalla base para cada nivel de calidad
- Después de cambios de código, capturar nuevas capturas
- Comparar diferencias de píxeles usando herramientas de diff de imagen
- Señalar cambios que excedan umbral (ej., >5% diferencia de píxeles)
Pruebas de Audio y Hápticos
El sonido y la retroalimentación háptica impactan significativamente la experiencia del jugador.
Checklist de Pruebas de Audio
Verificación de implementación de audio:
- Música de fondo hace loop sin problemas
- Efectos de sonido se activan en eventos correctos del juego
- Ducking de audio durante diálogos
- Configuraciones de volumen persisten entre sesiones
- Audio no continúa cuando app está en segundo plano
- Posicionamiento de audio espacial (sonido 3D)
- Impacto de rendimiento de audio (uso de CPU)
Pruebas de hápticos:
using UnityEngine;
public class HapticsValidator : MonoBehaviour
{
public void TestHapticFeedback()
{
// Probar háptico ligero
Handheld.Vibrate(); // Impacto ligero iOS
// Validar disparadores hápticos:
// - Presión de botón: Háptico ligero
// - Recolección de ítem: Háptico medio
// - Daño al jugador: Háptico fuerte
// - Game over: Vibración en patrón
// Verificar que háptico respeta:
// - Modo silencioso del dispositivo (iOS)
// - Configuración de preferencia del usuario
// - Modo ahorro de batería
}
}
CI/CD para Proyectos de Juegos
Los pipelines automatizados de build y testing son esenciales para desarrollo de juegos.
Integración con Unity Cloud Build
Ejemplo de configuración de build:
# unity-cloud-build.yaml
targets:
android-production (como se discute en [Cross-Platform Mobile Testing: Strategies for Multi-Device Success](/blog/cross-platform-mobile-testing)):
platform: android
scriptingBackend: il2cpp
buildSettings:
development: false
compressionMethod: lz4
pre-build-script: Scripts/PreBuild.sh
post-build-script: Scripts/PostBuild.sh
ios-production:
platform: ios
scriptingBackend: il2cpp
xcodeVersion: latest
buildSettings:
development: false
test-suites:
unit-tests:
platform: editmode
testCategories: [Unit, Integration]
playmode-tests:
platform: playmode
testCategories: [Functional, Performance]
minPassRate: 95%
GitHub Actions para Pruebas de Juegos
name: Game Build and Test
on:
push:
branches: [main, develop]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: game-ci/unity-test-runner@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
testMode: all
artifactsPath: test-results
- name: Upload test results
uses: actions/upload-artifact@v3
with:
name: Test results
path: test-results
build:
needs: test
runs-on: ubuntu-latest
strategy:
matrix:
platform: [Android, iOS]
steps:
- uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
targetPlatform: ${{ matrix.platform }}
- name: Deploy to TestFlight/Play Console
run: ./deploy-scripts/${{ matrix.platform }}.sh
Reportes automatizados de pruebas:
- Tasas de éxito de pruebas unitarias
- Benchmarks de rendimiento (FPS, memoria)
- Seguimiento de tamaño de build
- Reportes de crash de dispositivos de prueba
- Métricas de cobertura de código
Conclusión
Las pruebas de juegos móviles demandan experiencia especializada más allá del QA tradicional. El éxito requiere:
- Monitoreo de rendimiento: Seguimiento continuo de FPS, memoria y batería
- Pruebas de red: Medición de latencia y cobertura de escenarios de conectividad
- Automatización: Unity Test Framework y pruebas de Automatización Unreal
- Cobertura de dispositivos: Pruebas estratégicas en tiers de dispositivos
- Validación de monetización: Pruebas rigurosas de integración IAP y anuncios
- Pruebas de balance: Análisis de progresión y economía basado en datos
- Integración CI/CD: Pipelines automatizados de builds y pruebas
Al implementar estrategias completas de pruebas que cubran rendimiento, funcionalidad, compatibilidad y experiencia del jugador, los equipos de QA aseguran que los juegos móviles entreguen experiencias estables y atractivas en diversos dispositivos y condiciones de red. La inversión en infraestructura robusta de pruebas paga dividendos a través de mayor retención de jugadores, mejores reseñas y menos problemas post-lanzamiento.