
En el desarrollo de juegos, las pruebas manuales pueden volverse repetitivas y propensas a errores rápidamente. ¿Alguna vez te has encontrado en uno de estos ciclos de prueba aparentemente interminables mientras trabajas en una nueva función o intentas corregir un error?
Al automatizar tus pruebas de código, puedes dedicar más tiempo al desarrollo de juegos creativos y menos a tareas de control de calidad repetitivas (pero importantes) que garantizan que agregar, eliminar o cambiar código no arruina tu proyecto.
Unity te ayuda a crear, administrar y ejecutar pruebas automatizadas para tus juegos con Unity Test Framework.
Unity Test Framework (UTF) te permite probar el código de tu proyecto en los modos Edit y Play. También puedes orientarte al código de prueba para varias plataformas, como plataformas independientes, iOS o Android.
El UTF se instala agregándolo a tu proyecto con Package Manager.
Debajo del capó, UTF se integra con NUnit, que es una conocida biblioteca de pruebas de código abierto para lenguajes .NET.
Hay dos categorías principales de pruebas que puedes escribir con UTF: modo de edición y modo de juego:
Las pruebas del modo de edición se ejecutan en Unity Editor y tienen acceso tanto al Editor como al código del juego. Eso significa que puedes probar tus extensiones personalizadas del Editor o utilizar pruebas para modificar los ajustes en el Editor y entrar en el modo Play. Esto es útil para ajustar los valores del Inspector y, luego, ejecutar pruebas automatizadas con muchos ajustes diferentes.
Las pruebas del modo Play te permiten ejercitar el código de tu juego durante el tiempo de ejecución. Las pruebas se suelen ejecutar como corrutinas utilizando el atributo [UnityTest]. Esto te permite probar un código que puede ejecutarse en varios frames. De forma predeterminada, las pruebas del modo Play se ejecutarán en el Editor, pero también puedes hacerlo en una compilación de jugador independiente para varias plataformas de destino.

Para seguir con este ejemplo, deberás instalar el paquete Starter Assets - Third Person Character Controller de Unity Asset Store e importarlo en un nuevo proyecto.

Instala UTF a través de Window > Package Manager. Busca Test Framework en Unity Registry en Package Manager. Asegúrate de seleccionar la versión 1.3.3 (la versión más reciente en el momento de escribir este artículo).
Una vez instalado el UTF, abre el archivo Packages/manifest.json con un editor de texto y agrega una sección de comprobables después de las dependencias, de la siguiente manera:
,
"testables": [
"com.unity.inputsystem"
]
Guarda el archivo. Esto te resultará útil más adelante, cuando necesitarás hacer referencia al ensamblado Unity.InputSystem.TestFramework para probar y emular la entrada del jugador.
Regresa al Editor y permite que se instale la versión más reciente.

Haz clic en Window > General > Test Runner para ver la ventana del Editor Test Runner.
En esta parte del tutorial, el enfoque será crear pruebas del modo Play. En lugar de usar las opciones Create Test Assembly Folder (crear carpeta de ensamblado de prueba) en la ventana Test Runner, las crearás con la ventana Project (proyecto).
Con la raíz de tu carpeta Project Assets resaltada, haz clic derecho y elige Create > Testing > Tests Assembly Folder (Crear > Pruebas > Carpeta de ensamblado de pruebas).
Se agrega una carpeta del proyecto Tests, la cual contiene un archivo Tests.asmdef (definición de ensamblado). Esto es necesario para que las pruebas hagan referencia a tus módulos y dependencias de juego.
El código del controlador de personaje se referenciará en las pruebas y también necesitará una definición de ensamblado. Luego, configurarás algunas definiciones y referencias de ensamblado para facilitar las pruebas entre los módulos.
Haz clic derecho en la carpeta del proyecto Assets/StarterAssets/InputSystem y elige Create > Assembly Definition. Dile algo descriptivo, por ejemplo, StarterAssetsInputSystem.
Selecciona el nuevo archivo StarterAssetsInputSystem.asmdef y, con el Inspector, agrega una referencia de definición de ensamblado a Unity.InputSystem. Haz clic en Apply.
Haz clic derecho en la carpeta del proyecto Assets/StarterAssets/Third PersonController/Scripts y elige Create > Assembly Definition. Dile algo descriptivo, por ejemplo, ThirdPersonControllerMain.
Como hiciste con la definición de ensamblado anterior, abre ThirdPersonControllerMain en el Inspector y selecciona referencias para:
- Unity.InputSystem
- StarterAssetsInputSystem
Haz clic en Aplicar.

Para emular partes de Input System, deberás hacer referencia a esta herramienta en tus pruebas. Además, deberás hacer referencia al espacio de nombres StarterAssets en un ensamblado que crearás para el código Third Person Controller.
Abre Tests.asmdef en el Inspector y agrega una referencia a las siguientes definiciones de ensamblado:
- UnityEngine.TestRunner
- UnityEditor.TestRunner
- Unity.InputSystem
- Unity.InputSystem.TestFramework
- ThirdPersonControllerMain
Haz clic en Apply.

Tu primera prueba incluirá algunos conceptos básicos sobre cómo cargar y mover el personaje principal del paquete Third Person Controller.
Para comenzar, configura el nuevo proyecto con una escena de entorno de prueba simple y un recurso de Prefab de personaje con el que trabajar.
Abre la escena llamada Assets/StarterAssets/Third PersonController/Scenes/Playground.unity y guarda una copia de ella en el menú File > Save As (Archivo > Guardar como) en esta nueva ruta: Assets/Scenes/SimpleTesting.unity
Si notas materiales rosados en la vista de Juego, utiliza el convertidor del canal de renderizado para actualizar los materiales del canal de renderizado integrado al canal de renderizado universal (URP). Consulta este artículo para ver una descripción general rápida.
Crea una nueva carpeta en tu carpeta Project Assets llamada Resources. Nota: El nombre de la carpeta «Resources» es importante para que se pueda utilizar el método Unity Resources.Load().
Arrastre y suelte el GameObject PlayerArmature en la vista Scene en la nueva carpeta Resources y elija crear un prefab original cuando se le solicite. Cambiar el nombre del personaje del asset Prefab.
Este será el personaje base que utilizarás el Prefab en tus pruebas de ahora en adelante.
Eliminar el GameObject PlayerArmature de la nueva escena de SimpleTesting y guardar los cambios en la escena.
Para el último paso de la configuración de prueba inicial, ve a File > Build Settings (Archivo > Ajustes de compilación) y elige Add Open Scenes (Agregar escenas abiertas) para agregar la escena Scenes/SimpleTesting (Pruebas simples) a los ajustes de compilación.
Selecciona la carpeta Tests en la carpeta Project Assets. Haz clic derecho y elige Create > Testing > C# Test Script.
Asignar el nombre al nuevo Script CharacterTests. Abre el script en tu IDE para ver más de cerca.
Se suministran dos stubs de método con el archivo de clase inicial, lo que demuestra algunos conceptos básicos de la prueba.
Luego, asegúrate de que las pruebas carguen una escena del juego "centrada en las pruebas". Esta debe ser una escena que contenga el mínimo requerido para probar el sistema o componente en el que te enfocas.
Actualiza la clase CharacterTests para agregar dos sentencias nuevas con la clase InputTestFixture:
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
public class CharacterTests: InputTestFixture
Agregar dos campos privados a la parte superior de la clase CharacterTests:
Personaje GameObject = Resources.Load("Personaje");
Teclado del teclado;
El campo de personaje almacenará una referencia al Prefab del personaje, cargado desde la carpeta Resources. El teclado contiene una referencia al dispositivo de entrada de teclado proporcionado por InputSystem.
Para anular el método Setup() de la clase InputTestFixture base, proporciona el tuyo propio en la clase CharacterTests:
public override void Setup()
{
SceneManager.LoadScene("Scenes/SimpleTesting");
base.Setup();
keyboard = InputSystem.AddDevice();
var mouse = InputSystem.AddDevice();
Press(mouse.rightButton);
Release(mouse.rightButton);;
}
El método Setup() ejecuta la clase base Setup() y, luego, configura tu propia clase CharacterTests cargando la escena de prueba e inicializando el dispositivo de entrada del teclado.
La entrada del mouse se agrega puramente para que el Third Person Controller comience a recibir la entrada del dispositivo de teclado simulado/virtual. Esto es casi como una acción de "establecer enfoque".
Para tu primera prueba, instanciarás el personaje del Prefab y asegurarás que no sea null. Agrega el siguiente método a tu clase de prueba:
[Prueba]
public void TestPlayerInstantiation()
{
GameObject characterInstance = GameObject.Instantiate(personaje, Vector3.zero, Quaternion.identity);
Assert.That(characterInstance, !Is.Null);
}
Mientras estás allí, es posible que desees limpiar los métodos de prueba de la plantilla de muestra. Eliminar los métodos CharacterTestsSimplePasses y CharacterTestsWithEnumeratorPasses.

Guarda el script y regresa a la ventana Test Runner en el Editor. Resalta la prueba TestPlayerInstantiation y haz clic en Run Selected (Ejecutar seleccionado).
La marca de verificación verde significa que se aprobó un examen. Aseveraste que el personaje se puede cargar desde recursos, instanciar en la escena de prueba y no es null en ese punto.
Te habrás dado cuenta de que la anotación [Test] se utilizó para esta prueba en lugar de la anotación [UnityTest]. El atributo UnityTest permite que las corrutinas ejecuten pruebas en varios frames. En este caso, solo tienes que instanciar el personaje y afirmar que está cargado.
En general, debes usar el atributo NUnit Test en lugar del atributo UnityTest en el modo de edición, a menos que necesites dar instrucciones especiales, omitas un frame o esperes cierto tiempo en el modo Play.

Luego, utilizarás UnityTest para afirmar que mantener presionada la tecla del control hacia adelante hace que el personaje avance.
Agrega el nuevo método de prueba que se proporciona a continuación a tu clase CharacterTests.
Aparecieron dos nuevos métodos auxiliares de prueba: Press() y Release(). Ambas son proporcionadas por la clase base InputTestFixture y te ayudan a emular el control de InputSystem presionando y soltando.
El método TestPlayerMoves() hace lo siguiente:
Instancia una instancia del personaje a partir del Prefab en la ubicación (X: 0, Y: 0, Z: 0)
Presiona la tecla de flecha hacia arriba en el teclado virtual durante 1 segundo y, luego, suéltala
Espera 1 segundo más (para que el personaje se ralentice y deje de moverse)
Afirma que el personaje se ha movido a una posición en el eje Z superior a 1.5 unidades.
Guarda el archivo, regresa al Test Runner y ejecuta la nueva prueba.

Luego, probarás un script MonoBehaviour personalizado agregando un componente simple Player Health.
Crear un nuevo script en Assets/StarterAssets/Third PersonController/Scripts. Llamémoslo PlayerHealth.
Abre el script en tu IDE y reemplaza el contenido por el código que se proporciona a continuación.
Aquí se agrega mucho código nuevo. Para resumirlo, este script determinará si el personaje del jugador está cayendo. Si una vez caes al suelo, la salud del personaje se reduce un 10 %.
Busca el Prefab del personaje en Assets/Resources. Abre el Prefab y agrega el nuevo componente de script PlayerHealth.
Luego, utilizarás la escena de prueba para asegurarte de que la salud del jugador se deteriore después de caerse de una cornisa.
Con el atributo [UnityTest], puedes escribir una prueba del modo Play para detectar daños por caídas. Al caer durante más de 0.2 segundos, el jugador debe recibir 0.1f de daño (el equivalente al 10% de la salud máxima).
En la escena de SimpleTesting, verás una escalera que conduce a una cornisa. Esta es una plataforma de prueba para generar el personaje sobre el script PlayerHealth y probarlo.
Vuelve a abrir CharacterTests.cs y agrega un nuevo método de prueba llamado TestPlayerFallDamage:
[UnityTest]
public IEnumerator TestPlayerFallDamage()
{
// generar el personaje en un área lo suficientemente alta en la escena de prueba
GameObject characterInstance = GameObject.Instantiate(personaje, nuevo Vector3(0f, 4f, 17.2f), Quaternion.identity);
// Obtener una referencia al componente PlayerHealth y afirmar que se encuentra en estado de salud total (1f)
var characterHealth = characterInstance.GetComponent();
Assert.That(characterHealth.Health, Is.EqualTo(1f));
// Salir de la cornisa y esperar la caída
Press(keyboard.upArrowKey);
devolver rendimiento nuevo WaitForSeconds(0.5f);
Release(keyboard.upArrowKey);
yield return new WaitForSeconds(2f);
// Afirmar que se perdió 1 punto de salud debido al daño por caída
Assert.That(characterHealth.Health, Is.EqualTo(0.9f));
}
También deberás agregar una referencia utilizando el espacio de nombres StarterAssets en la parte superior del archivo de la clase:
usar StarterAssets;
La prueba de arriba sigue un patrón típico de arreglo, acción y afirmación (AAA), comúnmente encontrado en las pruebas:
La sección Assert verifica que la acción del método que se está probando se comporte según lo esperado.
Luego, probarás un script MonoBehaviour personalizado agregando un componente simple Player Health.
Crear un nuevo script en Assets/StarterAssets/Third PersonController/Scripts. Llamémoslo PlayerHealth.
Abre el script en tu IDE y reemplaza el contenido por el código que se proporciona a continuación.
Aquí se agrega mucho código nuevo. Para resumirlo, este script determinará si el personaje del jugador está cayendo. Si una vez caes al suelo, la salud del personaje se reduce un 10 %.
Busca el Prefab del personaje en Assets/Resources. Abre el Prefab y agrega el nuevo componente de script PlayerHealth.
Luego, utilizarás la escena de prueba para asegurarte de que la salud del jugador se deteriore después de caerse de una cornisa.
Con el atributo [UnityTest], puedes escribir una prueba del modo Play para detectar daños por caídas. Al caer durante más de 0.2 segundos, el jugador debe recibir 0.1f de daño (el equivalente al 10% de la salud máxima).
En la escena de SimpleTesting, verás una escalera que conduce a una cornisa. Esta es una plataforma de prueba para generar el personaje sobre el script PlayerHealth y probarlo.
Vuelve a abrir CharacterTests.cs y agrega un nuevo método de prueba llamado TestPlayerFallDamage:
[UnityTest]
public IEnumerator TestPlayerFallDamage()
{
// generar el personaje en un área lo suficientemente alta en la escena de prueba
GameObject characterInstance = GameObject.Instantiate(personaje, nuevo Vector3(0f, 4f, 17.2f), Quaternion.identity);
// Obtener una referencia al componente PlayerHealth y afirmar que se encuentra en estado de salud total (1f)
var characterHealth = characterInstance.GetComponent();
Assert.That(characterHealth.Health, Is.EqualTo(1f));
// Salir de la cornisa y esperar la caída
Press(keyboard.upArrowKey);
devolver rendimiento nuevo WaitForSeconds(0.5f);
Release(keyboard.upArrowKey);
yield return new WaitForSeconds(2f);
// Afirmar que se perdió 1 punto de salud debido al daño por caída
Assert.That(characterHealth.Health, Is.EqualTo(0.9f));
}
También deberás agregar una referencia utilizando el espacio de nombres StarterAssets en la parte superior del archivo de la clase:
usar StarterAssets;
La prueba de arriba sigue un patrón típico de arreglo, acción y afirmación (AAA), comúnmente encontrado en las pruebas:
La sección Arrange de un método de prueba unitaria inicializa los objetos y establece el valor de los datos que se pasan al método que se está probando.
La sección Act invoca el método en prueba con los parámetros dispuestos. En este caso, la invocación del método que se está probando se maneja mediante una interacción de física cuando el jugador toca el suelo después de caer.
La sección Assert verifica que la acción del método que se está probando se comporte según lo esperado.

Vuelve al Editor y ejecuta la nueva prueba. Al ejecutarse en el modo Play, verás al personaje salirse del borde, caer (superando el umbral de 0.2 segundos para categorizar una caída) y recibir daño después de tocar el suelo.
Las pruebas no solo sirven para probar que los cambios en el código no rompen la funcionalidad, sino que también pueden servir como documentación o indicadores para ayudar a que los desarrolladores piensen en otros aspectos del juego al modificar los ajustes.

Como se mencionó anteriormente, al ejecutar las pruebas del modo Play en Test Runner de forma predeterminada, se ejecutan en el modo Play con Unity Editor. También puedes cambiarlos para que se ejecuten bajo un jugador independiente.
Usa la selección desplegable Run Location (Ejecutar ubicación) en la ventana Test Runner para cambiar las pruebas a fin de ejecutarlas en compilaciones de jugadores independientes.
Una vez que hayas comenzado a crear un conjunto de pruebas, el siguiente paso es ejecutarlas automáticamente una vez que se hayan completado. Las pruebas unitarias y de integración automatizadas que se ejecutan después de la compilación son útiles para detectar regresiones o errores lo antes posible. También se pueden ejecutar como parte de un sistema automatizado remoto en la nube.
Muchas veces, lo ideal es que captures los resultados de las pruebas en un formato personalizado para que los resultados se puedan compartir con un público más amplio. Para capturar los resultados de las pruebas fuera de Unity Editor, deberás dividir los procesos de compilación y ejecución.
Crea un nuevo script en la carpeta de tu proyecto Tests llamado SetupPlaymodeTestPlayer.
La clase SetupPlaymodeTestPlayer implementará la interfaz ITestPlayerBuildModifier. Lo utilizarás para anular y "engancharte" al método ModifyOptions, que recibe las opciones del jugador de la compilación y te permite modificarlas.
usar System.IO;
using UnityEditor;
using UnityEditor.TestTools;
[ensamblado: TestPlayerBuildModifier(typeof(SetupPlaymodeTestPlayer))]
public class SetupPlaymodeTestPlayer : ITestPlayerBuildModifier
{
public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
{
playerOptions.options &= ~(BuildOptions.AutoRunPlayer | BuildOptions.ConnectToHost);
var buildLocation = Path.GetFullPath("TestPlayers");
var fileName = Path.GetFileName(playerOptions.locationPathName);
if (!string.IsNullOrEmpty(fileName))
buildLocation = Path.Combine(buildLocation, fileName);
playerOptions.locationPathName = buildLocation;
devolver playerOptions;
}
}
Este script modificador de Player Build personalizado hace lo siguiente cuando se ejecutan pruebas en el modo Play (Run Location: On Player):
Desactiva la ejecución automática para los jugadores creados y omite la opción de jugador que intenta conectarse al host en el que se está ejecutando
Cambia la ubicación de la ruta de compilación a una ruta dedicada dentro del proyecto (TestPlayers)
Con esto completo, ahora puedes esperar que las compilaciones se encuentren en la carpeta TestPlayers cada vez que terminen de compilarse. Esto ahora completa las modificaciones de compilación y elimina el vínculo entre compilación y ejecución.
Luego, implementarás el informe de resultados. Esto te permitirá escribir los resultados de la prueba en un lugar personalizado, listo para la generación y publicación automatizadas de informes.
Crea un nuevo script en la carpeta de tu proyecto Tests llamado ResultSerializer (que se proporciona a continuación). Esta clase utilizará una referencia de ensamblado para TestRunCallback e implementará la interfaz ITestRunCallback.
Esta implementación de ITestRunCallback incluye un método RunFinished personalizado, que es el que configura una compilación de jugador con pruebas para escribir los resultados de la prueba en un archivo XML llamado testresults.xml.

Con SetupPlaymodeTestPlayer.cs y ResultSerializer.cs combinados, los procesos de compilación y ejecución ahora están divididos. Al ejecutar las pruebas, los resultados se enviarán a testresults.xml, ubicado en la ubicación Application.persistentDataPath de la plataforma del jugador.
Para utilizar algunos de los tipos de estas clases de gancho, deberás agregar una referencia adicional a Tests.asmdef. Actualiza para agregar la referencia de definición del ensamblado UnityEditor.UI.EditorTests.
Al ejecutar las pruebas en el reproductor, ahora se obtendrá una compilación del jugador en la carpeta TestPlayers y un archivo testresults.xml en Application.persistentDataPath.

Curso Unity Test Framework
El paquete Test Framework incluye un curso de prueba con ejercicios de muestra para ayudarte a obtener más información sobre las pruebas con Unity. Asegúrate de tomar los archivos del proyecto para el curso con Package Manager.
Uso de Package Manager > Paquetes: Unity Registry > Test Framework, busca la lista desplegable Samples (muestras) e importa los ejercicios del curso.
Los ejercicios se importarán a tu proyecto y se ubicarán en Assets/Samples/ Test Framework. Cada muestra incluye una carpeta de ejercicios para que trabajes, así como una solución para comparar tu propio trabajo a medida que avanzas.
QA tu código con UTF
Esta charla Unite Copenhague sobre el UTF ofrece más detalles y algunos otros casos de uso interesantes para la personalización de las pruebas. Consulta esta página para ver qué más es posible hacer.
Depuración en Unity
Acelera tu flujo de trabajo de depuración en Unity con artículos sobre:
- Microsoft Visual Studio 2022
- Microsoft Visual Studio Code
Libros electrónicos técnicos avanzados
Unity proporciona varias guías avanzadas para ayudar a los desarrolladores profesionales a optimizar el código del juego. Crea una guía de estilo en C#: Escribe código más limpio que sea escalable y recopila consejos de expertos de la industria sobre cómo crear una guía de estilo de código para ayudar a tu equipo a desarrollar una base de código limpia, legible y escalable.
Otra guía popular entre nuestros usuarios son más de 70 consejos para aumentar la productividad con Unity. Incluye muchos consejos para ahorrar tiempo y mejorar tu flujo de trabajo agregado diario con Unity 2020 LTS, incluidos consejos que hasta los desarrolladores experimentados podrían haberse perdido.
Documentación
Explora más a fondo la API más reciente de TestRunner, conoce otros atributos personalizados de UTF y descubre más ciclos de vida a los que puedes dedicarte con la documentación de UTF.
Encuentra todos los libros y artículos electrónicos avanzados de Unity en el centro de prácticas recomendadas de Unity.