Last Updated August 2020, 6 min. read

Teste o código do seu jogo com o Unity Test Framework

O que você encontrará nesta página: dicas sobre como usar o Unity Test Framework (UTF) para conduzir QA em seus projetos. O UTF é uma das ferramentas mais importantes para garantia de qualidade. É usado para executar testes automatizados no Editor e em plataformas compatíveis. E está disponível para todos os usuários do Unity!  

Uma nova API do Test Runner oferece maior flexibilidade e capacidade de extensão ao UTF, para a maioria das necessidades de testes. Está disponível no Package Manager do Unity, para que possamos enviar correções de bugs e novas atualizações mais rápido. Isso também significa que você pode acessar o código-fonte do UTF localmente. Você pode observar o código-fonte, analisá-lo durante a depuração e modificá-la.  

Para ver a história completa, assista à sessão do UTF na Unite Copenhagen, com Richard Fine e Christian Warnecke, desenvolvedores de ferramentas e testes na Unity.

Teste o código do seu jogo com o Unity Test Framework

Conceitos básicos do Unity Test Framework

If you are new to the Unity Test Framework (UTF), read the documentation for an introduction. In brief, the UTF enables Unity users to test their code in both Edit Mode and Play Mode, and also on target platforms such as Standalone, Android, iOS, and others.

UTF uses a Unity integration of the NUnit library, which is an open-source unit testing library for .Net languages. For more information about NUnit, see the official NUnit website and the NUnit documentation on GitHub

You might also find these blog posts informative:

Performance benchmarking in Unity: How to get started

Testing test-driven development with the Unity Test Runner

Another related solution to learn about is Backtrace, an error management platform that enables you to capture crashes and exceptions and fix them quickly. Watch this Unite Now session for an in-depth introduction. 

Visão geral da API do Test Runner

Você pode executar os testes de maneira programática de qualquer script por meio da API do Test Runner (veja a API abaixo). Ela permite que você recupere uma lista dos testes que serão executados no Modo Edit, Modo Play ou ambos sem executá-los. Você pode vincular alguns callbacks de registro/cancelamento de registro no início e no término de cada teste em cada nível do ciclo de testes, ou seja, em todo o conjunto de teste, em cada instalação de teste e em cada teste e classe de teste. 

No início de cada teste, você recebe informações sobre a rota de teste que está prestes a ser executada. Ao final do teste, você verá os resultados. 

Além de executar o UTF no Modo Play no Unity Editor, um novo ponto de personalização permite a execução nos dispositivos-alvo. Isso é chamado antes de compilar o jogador. Você pode modificar as opções de build do jogador, por exemplo, para alterar as configurações de execução do teste e para especificar os locais da build.

TestRunnerAPI.cs (C#)
void Execute(ExecutionSettings executionSettings);
void RegisterCallbacks<T>(T testCallbacks, int priority = 0) where T : ICallbacks;
void UnregisterCallbacks<T>(T testCallbacks) where T : ICallbacks;
void RetrieveTestList(TestMode testMode, Action<ITestAdaptor> callback);

Separar compilação e execução

Separar os processos de compilação e execução é útil quando você deseja executar testes em um dispositivo-alvo que não está conectado ao computador local, por exemplo, se estiver na nuvem (ou se forem vários dispositivos na nuvem). 

Para isso, primeiro é necessário personalizar o próprio processo de compilação do jogador de teste. Veja como fazer isso: 

  • Desative o AutoRun de modo que, ao compilar o jogador, os testes não sejam inicializados e executados. 
  • Salve em um local conhecido em vez da pasta temporária do sistema (onde seria salvo por padrão. 

Depois, adicione relatórios de resultados personalizados no lado do jogador (usando a interface de callback) para capturar todos os resultados e salvá-los em um arquivo XML, ou qualquer outro formato adequado para o seu projeto. 

Vejas os exemplos de código a seguir para separação de compilação e execução. Na sessão da Unite (em 6:28), Richard Fine apresenta o código passo a passo para ambas as partes dessa aplicação — compilação e relatórios de resultados.

Separar compilação e execução: compilação

Compilação:

 

SplitBuildAndRun:build.cs (C#)
[assembly: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;
   	return playerOptions;
   }
}

Separar compilação e execução: salvar resultados na execução

Execução: 

SplitBuildAndRun:SaveResults.cs (C#)
[assembly:TestRunCallback(typeof(ResultSerializer))]
public class ResultSerializer : ITestRunCallback {
   public void RunStarted(ITest testsToRun) { }
   public void TestStarted(ITest test) { }
   public void TestFinished(ITestResult result) { }
   public void RunFinished(ITestResult testResults) {     
   	var path = Path.Combine(Application.persistentDataPath, "testresults.xml");
   	using (var xw = XmlWriter.Create(path, new XmlWriterSettings{Indent = true}))
       	testResults.ToXml(true).WriteTo(xw);
   	System.Console.WriteLine($"***\n\nTEST RESULTS WRITTEN TO\n\n\t{path}\n\n***");
   	Application.Quit(testResults.FailCount > 0 ? 1 : 0);
   }
}

Inicialização de testes específicos de um item de menu

Frequentemente, quando os desenvolvedores gravam validações, os resultados são exibidos na janela Console, onde podem ser facilmente perdidos no fluxo de mensagens. E se você pudesse obter resultados de validação em um pacote de testes com indicadores claros em um local dedicado no Editor? Isso pode ser feito inicializando testes específicos para um item de menu.  

Comece com um método vinculado a um MenuItem, da mesma maneira que faria com qualquer outro item de menu de extensão do Editor. Esse método criará um objeto de callback de ScriptableObject. Use um ScriptableObject em vez de uma classe regular para que os testes possam realizar ações, como fazer com que um domínio seja recarregado enquanto mantém os callbacks intactos. Ao habilitar o ScriptableObject, ele é registrado para callbacks, e ao desabilitar, o registro é cancelado. 

Depois, configure filtros. Frequentemente, ao inicializar um teste para um MenuItem, deseja-se executar testes para uma categoria ou um grupo específico. Com filtros é possível executar o teste de maneira assíncrona. Será executado ao longo de vários quadros, permitindo que UnityTest, UnitySetUp e UnityTearDown marquem o ciclo da engine durante o teste. Quando o teste for concluído e registrar RunFinished, você poderá defini-lo para exibir uma mensagem ou abrir uma janela de resultados — o que fizer sentido para o seu fluxo de trabalho.

Veja o exemplo de código abaixo. Richard aborda a configuração do código para essa aplicação na sessão da Unite (em 11:50).  

LaunchTestsFromMenuItem.cs (C#)
public class RunTestsFromMenu : ScriptableObject, ICallbacks {
   [MenuItem(“Tools/Run useful tests”)] public static void DoRunTests() {
   	CreateInstance<RunTestsFromMenu>().StartTestRun();
   }
   private void StartTestRun() {
   	hideFlags = HideFlags.HideAndDontSave;
   	CreateInstance<TestRunnerApi>().Execute(new ExecutionSettings {
       	filters = new [] { new Filter{ categoryNames = new[] { “UsefulTests” }}}
   	});
   }
   public void OnEnable() { CreateInstance<TestRunnerApi>().RegisterCallbacks(this); }
   public void OnDisable() { CreateInstance<TestRunnerApi>().UnregisterCallbacks(this); }
   /* ...RunStarted, TestStarted, TestFinished... */
   public void RunFinished(ITestResultAdaptor result) {       
   	…
   	DestroyImmediate(this);
   }

Execução de testes antes da compilação

Executar testes antes da compilação pode ser complicado pois o processo de compilação requer que os testes sejam executados de um callback, portanto, não há oportunidade para impulsionar o ciclo de atualização da engine. Mas o benefício é que você pode verificar se a funcionalidade básica está funcionando, antes de gastar tempo na compilação em si (que pode levar vários minutos em alguns projetos). 

Você pode implementar essa aplicação usando a interface IPreprocessBuildWithReport, da mesma maneira que implementaria qualquer outro tipo de pré-processamento de compilação. Para obter os resultados, registre um callback como de costume.

Como não é possível acessar o Modo Play durante uma compilação, você pode usar a API do Test Runner para executar testes específicos no Modo Edit. Você pode selecionar esses testes filtrando por categoria, como uma categoria de teste de validação pré-compilação. Esses testes podem ser executados de maneira síncrona. 

Ao concluir o teste, verifique os resultados. Se algo falhou, lance uma exceção BuildFailed, que fará com que o processo de compilação seja abortado. 

Essa aplicação pode ser dividida em duas partes — o ResultCollector e o pré-processador — que são detalhados por Richard na palestra (em 15:20). 

Assista a Christian e Richard demonstrarem a API do Test Runner ao vivo. Confira toda a sessão para obter ainda mais dicas de QA! 

RunTestsBeforeBuild.cs (C#)
   public ITestResultAdaptor Result { get; private set; }     
   public void RunStarted(ITestAdaptor testsToRun) { }
   public void TestStarted(ITestAdaptor test) { }
   public void TestFinished(ITestResultAdaptor result) { }
   public void RunFinished(ITestResultAdaptor result)
   {
   	Result = result;
   }
}

Você gostou deste conteúdo?

Usamos cookies para garantir a melhor experiência no nosso site. Visite nossa página da política de cookies para obter mais informações.

Eu entendi