
No desenvolvimento de jogos, os testes manuais podem rapidamente se tornar repetitivos e propensos a erros. Você já se viu em um desses ciclos de teste aparentemente intermináveis enquanto trabalha em um novo recurso ou tenta corrigir um bug?
Ao automatizar seus testes de código, você pode passar mais tempo no desenvolvimento criativo de jogos e menos em tarefas repetitivas (mas importantes) de QA que garantem que adicionar, remover ou alterar código não quebre seu projeto.
Unity ajuda você a criar, gerenciar e executar testes automatizados para seus jogos com o Unity Test Framework.
O Unity Test Framework (UTF) permite que você teste o código do seu projeto em ambos os modos Edit e Play. Você também pode direcionar o código de teste para várias plataformas, como standalone, iOS ou Android.
O UTF é instalado adicionando-o ao seu projeto com o Package Manager.
Nos bastidores, o UTF se integra ao NUnit, que é uma biblioteca de testes de código aberto bem conhecida para linguagens .NET.
Existem duas categorias principais de testes que você pode escrever com o UTF, modo de edição e modo de reprodução:
Os testes de Edit mode são executados no Editor do Unity e têm acesso ao código do Editor e do jogo. Isso significa que você pode testar suas extensões personalizadas do Editor ou usar testes para modificar configurações no Editor e entrar no modo de reprodução, o que é útil para ajustar valores do Inspector e, em seguida, executar testes automatizados com muitas configurações diferentes.
Os testes de Play mode permitem que você exerça seu código de jogo em tempo de execução. Os testes são geralmente executados como coroutines usando o atributo [UnityTest]. Isso permite que você teste código que pode ser executado em vários quadros. Por padrão, os testes do modo de reprodução serão executados no Editor, mas você também pode executá-los em uma build de player standalone para várias plataformas de destino.

Para acompanhar este exemplo, você precisará instalar o Starter Assets – Third Person Character Controller package da Unity Asset Store e importá-lo em um novo projeto.

Instale o UTF via Window > Package Manager. Pesquise por Test Framework no Registro Unity no Gerenciador de Pacotes. Certifique-se de selecionar a versão 1.3.3 (a versão mais recente no momento da escrita).
Uma vez que o UTF esteja instalado, abra o arquivo Packages/manifest.json com um editor de texto e adicione uma seção testables após dependencies, assim:
,
"testables": [
"com.unity.inputsystem"
]
Salve o arquivo. Isso será útil mais tarde, quando você precisará referenciar a assembly Unity.InputSystem.TestFramework para testar e emular a entrada do jogador.
Volte para o Editor e permita que a versão mais recente seja instalada.

Clique em Window > General > Test Runner para visualizar a janela do editor Test Runner.
Nesta parte do tutorial, o foco será na criação de testes em modo Play. Em vez de usar as opções Criar Pasta de Assembly de Teste na Janela do Test Runner, você as criará usando a janela do Projeto.
Com a raiz da sua pasta de Assets do Projeto destacada, clique com o botão direito e escolha Create > Testing > Tests Assembly Folder.
Uma pasta de projeto Tests é adicionada, contendo um arquivo Tests.asmdef (definição de assembly). Isso é necessário para que os testes referenciem seus módulos de jogo e dependências.
O código do Character Controller será referenciado nos testes e também precisará de uma definição de assembly. Em seguida, você configurará algumas definições de montagem e referências para facilitar os testes entre os módulos.
Clique com o botão direito na pasta do projeto Assets/StarterAssets/InputSystem e escolha Criar > Definição de Montagem. Dê um nome descritivo, por exemplo StarterAssetsInputSystem.
Selecione o novo arquivo StarterAssetsInputSystem.asmdef e, usando o Inspetor, adicione uma Referência de Definição de Montagem para Unity.InputSystem. Clique em Aplicar.
Clique com o botão direito na pasta do projeto Assets/StarterAssets/ThirdPersonController/Scripts e escolha Criar > Definição de Montagem. Dê um nome descritivo, por exemplo ThirdPersonControllerMain.
Como você fez com a definição de montagem anterior, abra ThirdPersonControllerMain no Inspetor e selecione referências para:
- Unity.InputSystem
- StarterAssetsInputSystem
Clique em Aplicar.

Para emular partes do Sistema de Entrada, você precisará referenciá-lo em seus testes. Além disso, você precisará referenciar o namespace StarterAssets em uma montagem que você criará para o código do Controlador de Terceira Pessoa.
Abra Tests.asmdef no Inspetor e adicione uma referência às seguintes definições de montagem:
- UnityEngine.TestRunner
- UnityEditor.TestRunner
- Unity.InputSystem
- Unity.InputSystem.TestFramework
- ThirdPersonControllerMain
Clique em Aplicar.

Seu primeiro teste cobrirá alguns conceitos básicos sobre carregar e mover o personagem principal do pacote Third Person Controller.
Comece configurando o novo projeto com uma cena de ambiente de teste simples e um recurso Prefab de personagem para trabalhar.
Abra a cena chamada Assets/StarterAssets/ThirdPersonController/Scenes/Playground.unity e salve uma cópia dela usando o menu Arquivo > Salvar Como neste novo caminho: Assets/Scenes/SimpleTesting.unity
Se você notar materiais rosa na visualização do jogo, use o Conversor de Pipeline de Renderização para atualizar materiais do Pipeline de Renderização Integrado para o Pipeline de Renderização Universal (URP). Veja este artigo para uma visão geral rápida.
Crie uma nova pasta na sua pasta de Projetos chamada Recursos. Observação: O nome da pasta “Recursos” é importante aqui para permitir que o método Resources.Load() do Unity seja usado.
Arraste e solte o GameObject PlayerArmature na visualização da cena na nova pasta Recursos e escolha criar um Prefab Original quando solicitado. Renomeie o ativo Prefab para Personagem.
Este será o Prefab base do personagem usado em seus testes daqui para frente.
Remova o GameObject PlayerArmature da nova cena SimpleTesting e salve as alterações na cena.
Para a última etapa na configuração inicial do teste, vá para Arquivo > Configurações de Construção e escolha Adicionar Cenas Abertas para adicionar a cena Cenas/SimpleTesting às configurações de construção.
Selecione a pasta Testes na pasta de Projetos. Clique com o botão direito e escolha Criar > Teste > Script de Teste C#.
Nomeie o novo Script como CharacterTests. Abra o script em seu IDE para dar uma olhada mais de perto.
Dois stubs de método são fornecidos com o arquivo de classe inicial, demonstrando algumas noções básicas de teste.
Em seguida, você garantirá que os testes carreguem uma cena de jogo "focada em testes". Esta deve ser uma cena contendo o mínimo necessário para testar o sistema ou componente no qual você está se concentrando.
Atualize a classe CharacterTests para adicionar duas novas usando declarações e implemente a classe InputTestFixture:
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
public class CharacterTests : InputTestFixture
Adicione dois campos privados ao topo da classe CharacterTests:
GameObject character = Resources.Load("Character");
Teclado teclado;
O campo de personagem armazenará uma referência ao Prefab do Personagem, carregado da pasta Resources. Teclado manterá uma referência ao dispositivo de entrada do Teclado fornecido pelo InputSystem.
Substitua o método Setup() da classe base InputTestFixture fornecendo o seu próprio na classe CharacterTests:
public override void Setup()
{
SceneManager.LoadScene("Scenes/SimpleTesting");
base.Setup();
teclado = InputSystem.AddDevice();
var mouse = InputSystem.AddDevice();
Press(mouse.rightButton);
Libere(mouse.rightButton);;
}
O método Setup() executa o método Setup() da classe base e, em seguida, configura sua própria classe CharacterTests carregando a cena de teste e inicializando o dispositivo de entrada do teclado.
A entrada do mouse é adicionada puramente para que o Controlador de Terceira Pessoa comece a receber entrada do dispositivo de teclado simulado/virtual. Isso é quase como uma ação de ‘definir foco’.
Para seu primeiro teste, você instanciará o personagem do Prefab e afirmará que não é nulo. Adicione o seguinte método à sua classe de teste:
[Test]
public void TestPlayerInstantiation()
{
GameObject characterInstance = GameObject.Instantiate(character, Vector3.zero, Quaternion.identity);
Assert.That(characterInstance, !Is.Null);
}
Enquanto você está lá, pode querer limpar os métodos de teste do modelo de amostra. Remova os métodos CharacterTestsSimplePasses e CharacterTestsWithEnumeratorPasses.

Salve o script e volte para a janela Test Runner no Editor. Realce o teste TestPlayerInstantiation e clique em Run Selected.
A marca de verificação verde significa um teste aprovado. Você afirmou que o personagem pode ser carregado dos recursos, instanciado na cena de teste e não é nulo nesse ponto.
Você pode ter notado que a anotação [Teste] foi usada para este teste em vez da anotação [UnityTest]. O atributo UnityTest permite que corrotinas executem testes em vários quadros. Neste caso, você só precisa instanciar o personagem e afirmar que ele foi carregado.
Geralmente, você deve usar o atributo de teste NUnit em vez do atributo UnityTest no modo de edição, a menos que precise fornecer instruções especiais, precise pular um quadro ou esperar um certo período de tempo no modo de jogo.

Em seguida, você usará o UnityTest ao afirmar que manter pressionada a tecla do controlador para frente move o personagem para frente.
Adicione o novo método de teste fornecido abaixo à sua classe CharacterTests.
Dois novos métodos auxiliares de teste apareceram; Press() e Release(). Ambos são fornecidos pela classe base InputTestFixture e ajudam você emular a pressão e liberação do controle do InputSystem.
O método TestPlayerMoves() faz o seguinte:
Instancia uma instância do personagem a partir do Prefab do personagem na localização (X: 0, Y: 0, Z: 0)
Pressiona a tecla de seta para cima no teclado virtual por 1 segundo, depois a solta
Espera mais 1 segundo (para o personagem desacelerar e parar de se mover)
Afirma que o personagem se moveu para uma posição no eixo Z maior que 1,5 unidades.
Salve o arquivo, retorne ao Test Runner e execute o novo teste.

Em seguida, você testará um script Monobehaviour personalizado adicionando um componente simples de Player Health.
Crie um novo script em Assets/StarterAssets/ThirdPersonController/Scripts. Nomeie-o como PlayerHealth.
Abra o script em seu IDE e substitua o conteúdo pelo código fornecido abaixo.
Há muito código novo adicionado aqui. Para resumir, este script determinará se o personagem do jogador está em um estado de queda. Se o chão for atingido uma vez em um estado de queda, a saúde do personagem é reduzida em 10%.
Localize o Prefab do personagem em Assets/Resources. Abra o Prefab e adicione o novo componente de script PlayerHealth.
Em seguida, você usará a cena de teste para afirmar que a saúde do jogador cai após cair de uma borda.
Usando o atributo [UnityTest], você pode escrever um teste de modo Play que testa o dano de queda. Ao cair por mais de 0,2 segundos, o jogador deve sofrer 0,1f de dano (o equivalente a 10% da saúde máxima).
Na cena SimpleTesting, você verá uma escada levando a uma borda. Esta é uma plataforma de teste para gerar o personagem em cima e testar o script PlayerHealth.
Abra CharacterTests.cs novamente e adicione um novo método de teste chamado TestPlayerFallDamage:
[UnityTest]
public IEnumerator TestPlayerFallDamage()
{
// gere o personagem em uma área alta na cena de teste
GameObject characterInstance = GameObject.Instantiate(character, new Vector3(0f, 4f, 17.2f), Quaternion.identity);
// Obtenha uma referência ao componente PlayerHealth e afirme que está atualmente com saúde total (1f)
var characterHealth = characterInstance.GetComponent();
Assert.That(characterHealth.Health, Is.EqualTo(1f));
// Ande pela borda e aguarde a queda
Press(keyboard.upArrowKey);
yield return new WaitForSeconds(0.5f);
Release(keyboard.upArrowKey);
yield return new WaitForSeconds(2f);
// Afirme que 1 ponto de saúde foi perdido devido ao dano da queda
Assert.That(characterHealth.Health, Is.EqualTo(0.9f));
}
Você também precisará adicionar uma referência using ao namespace StarterAssets no topo do arquivo da classe:
using StarterAssets;
O teste acima segue um padrão típico arranjar, agir, afirmar (AAA), comumente encontrado em testes:
A seção Assert verifica se a ação do método em teste se comporta como esperado.
Em seguida, você testará um script Monobehaviour personalizado adicionando um componente simples de Player Health.
Crie um novo script em Assets/StarterAssets/ThirdPersonController/Scripts. Nomeie-o como PlayerHealth.
Abra o script em seu IDE e substitua o conteúdo pelo código fornecido abaixo.
Há muito código novo adicionado aqui. Para resumir, este script determinará se o personagem do jogador está em um estado de queda. Se o chão for atingido uma vez em um estado de queda, a saúde do personagem é reduzida em 10%.
Localize o Prefab do personagem em Assets/Resources. Abra o Prefab e adicione o novo componente de script PlayerHealth.
Em seguida, você usará a cena de teste para afirmar que a saúde do jogador cai após cair de uma borda.
Usando o atributo [UnityTest], você pode escrever um teste de modo Play que testa o dano de queda. Ao cair por mais de 0,2 segundos, o jogador deve sofrer 0,1f de dano (o equivalente a 10% da saúde máxima).
Na cena SimpleTesting, você verá uma escada levando a uma borda. Esta é uma plataforma de teste para gerar o personagem em cima e testar o script PlayerHealth.
Abra CharacterTests.cs novamente e adicione um novo método de teste chamado TestPlayerFallDamage:
[UnityTest]
public IEnumerator TestPlayerFallDamage()
{
// gere o personagem em uma área alta na cena de teste
GameObject characterInstance = GameObject.Instantiate(character, new Vector3(0f, 4f, 17.2f), Quaternion.identity);
// Obtenha uma referência ao componente PlayerHealth e afirme que está atualmente com saúde total (1f)
var characterHealth = characterInstance.GetComponent();
Assert.That(characterHealth.Health, Is.EqualTo(1f));
// Ande pela borda e aguarde a queda
Press(keyboard.upArrowKey);
yield return new WaitForSeconds(0.5f);
Release(keyboard.upArrowKey);
yield return new WaitForSeconds(2f);
// Afirme que 1 ponto de saúde foi perdido devido ao dano da queda
Assert.That(characterHealth.Health, Is.EqualTo(0.9f));
}
Você também precisará adicionar uma referência using ao namespace StarterAssets no topo do arquivo da classe:
using StarterAssets;
O teste acima segue um padrão típico arranjar, agir, afirmar (AAA), comumente encontrado em testes:
A seção Arrange de um método de teste unitário inicializa objetos e define o valor dos dados que são passados para o método em teste.
A seção Act invoca o método em teste com os parâmetros organizados. Neste caso, a invocação do método em teste é tratada por uma interação física quando o jogador atinge o chão após cair.
A seção Assert verifica se a ação do método em teste se comporta como esperado.

De volta ao Editor, execute o novo teste. Executando no modo Play, você verá o personagem andar até a borda, cair (excedendo o limite de 0,2 segundos para categorizar uma queda) e sofrer dano ao atingir o chão.
Os testes não servem apenas para garantir que as alterações de código não quebrem a funcionalidade, mas também podem servir como documentação ou dicas para ajudar os desenvolvedores a pensar em outros aspectos do jogo ao ajustar configurações.

Como mencionado anteriormente, executar testes no modo Play no Test Runner por padrão os executa no modo Play usando o Unity Editor. Você também pode alterá-los para serem executados em um jogador independente.
Use a seleção suspensa Run Location na janela do Test Runner para alternar testes para serem executados em builds de jogador independente.
Uma vez que você começou a construir um conjunto de testes, o próximo passo é executá-los automaticamente após a conclusão das builds. Testes automatizados unitários e de integração que são executados após a build são úteis para capturar regressões ou bugs o mais cedo possível. Eles também podem ser executados como parte de um sistema de build automatizado remoto na nuvem.
Frequentemente, você vai querer capturar os resultados da execução do teste em um formato personalizado para que os resultados possam ser compartilhados com um público mais amplo. Para capturar resultados de teste fora do Unity Editor, você precisará dividir os processos de build e execução.
Crie um novo script na pasta do seu projeto de Testes chamado SetupPlaymodeTestPlayer.
A classe SetupPlaymodeTestPlayer implementará a interface ITestPlayerBuildModifier. Você usará isso para substituir e "conectar-se" ao método ModifyOptions, que recebe as opções do jogador da build e permite que você as modifique.
usando System.IO;
using UnityEditor;
using UnityEditor.TestTools;
[assembly: TestPlayerBuildModifier(typeof(SetupPlaymodeTestPlayer))]
classe pública 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;
return playerOptions;
}
}
Este script modificador de Player Build personalizado faz o seguinte quando os testes são executados no modo Play (Local de Execução: No Player):
Desativa a execução automática para jogadores construídos e ignora a opção do jogador que tenta se conectar ao host em que está sendo executado
Altera o local do caminho de construção para um caminho dedicado dentro do projeto (TestPlayers)
Com isso completo, você pode agora esperar que as construções sejam localizadas na pasta TestPlayers sempre que terminarem de construir. Isso agora completa as modificações de construção e interrompe o vínculo entre construção e execução.
Em seguida, você implementará a geração de relatórios de resultados. Isso permitirá que você escreva os resultados dos testes em um local personalizado, pronto para geração e publicação automatizada de relatórios.
Crie um novo script na pasta do seu projeto de Testes chamado ResultSerializer (fornecido abaixo). Esta classe usará uma referência de assembly para TestRunCallback e implementará a interface ITestRunCallback.
Esta implementação de ITestRunCallback inclui um método RunFinished personalizado, que é o que configura uma construção de jogador com testes para escrever os resultados dos testes em um arquivo XML chamado testresults.xml.

Com SetupPlaymodeTestPlayer.cs e ResultSerializer.cs combinados, os processos de construção e execução agora estão divididos. Executar testes irá gerar os resultados no testresults.xml localizado no caminho Application.persistentDataPath da plataforma do jogador localização.
Para usar alguns dos tipos nessas classes de hook, você precisará adicionar uma referência extra a Tests.asmdef. Atualize para adicionar a referência de definição de assembly do UnityEditor.UI.EditorTests.
Executar os testes no jogador agora resultará em uma saída de construção do jogador sob seu projeto na pasta TestPlayers e um arquivo testresults.xml na localização Application.persistentDataPath.

Curso do Unity Test Framework
O pacote Test Framework inclui um curso de testes com exercícios de amostra para ajudá-lo a aprender mais sobre testes com Unity. Certifique-se de pegar os arquivos do projeto para o curso usando o Gerenciador de Pacotes.
Usando Gerenciador de Pacotes > Pacotes: Registro do Unity > Test Framework, localize a lista suspensa de Amostras e importe os exercícios do curso.
Os exercícios serão importados para o seu projeto e localizados em Assets/Samples/Test Framework. Cada amostra inclui uma pasta de exercícios para você trabalhar, bem como uma solução para comparar seu próprio trabalho enquanto você acompanha.
QA seu código com UTF
Esta palestra Unite Copenhagen sobre UTF entra em mais detalhes e oferece alguns outros casos de uso interessantes para personalização de testes. Certifique-se de conferir para ver o que mais é possível.
Depuração em Unity
Acelere seu fluxo de trabalho de depuração no Unity com artigos sobre:
- Microsoft Visual Studio 2022
- Microsoft Visual Studio Code
Livros eletrônicos técnicos avançados
A Unity oferece uma série de guias avançados para ajudar desenvolvedores profissionais a otimizar o código do jogo. Crie um guia de estilo C#: Escreva um código mais limpo que escale compila conselhos de especialistas da indústria sobre como criar um guia de estilo de código para ajudar sua equipe a desenvolver uma base de código limpa, legível e escalável.
Outro guia popular entre nossos usuários é 70+ dicas para aumentar a produtividade com Unity. Está repleto de dicas que economizam tempo para melhorar seu fluxo de trabalho agregado do dia a dia com Unity 2020 LTS, incluindo dicas que até mesmo desenvolvedores experientes podem ter perdido.
Documentação
Explore mais a fundo a API TestRunner mais recente, aprenda sobre outros atributos personalizados do UTF e descubra mais ciclos de vida para se conectar com a documentação do UTF.
Encontre todos os e-books e artigos avançados da Unity no hub de melhores práticas da Unity.