Âmbito
Este artigo tem como objetivo mostrar como podemos testar as aplicações móveis usando Xamarin Test Cloud, sejam estas aplicações Xamarin ou aplicações nativas.
Introdução
O desenvolvimento móvel tem tido um crescimento exponencial, trazendo com isso um “booom” de aplicações para as diversas lojas. Claro está, que muitas das vezes quantidade não significa qualidade e quantas vezes nós próprios nos deparamos com potências aplicações que apenas precisam de melhorias, e em alguns casos a aplicação funciona bem numa plataforma e noutra não (por razões diversas). Com este crescimento e com base nas diversas necessidades muitas soluções têm surgido no mercado para que os programadores possam acompanhar o desempenho da aplicação durante a sua utilização.
Independentemente da forma como os programadores acompanham as suas aplicações para fazer manutenção corretiva, coloca-se a seguinte questão: será que isto é uma boa solução? Isto é, será que é bom serem os nossos utilizadores a encontrar os bugs e comportamentos não esperados? Porque isto é ou tem sido uma realidade… Ou será que os programadores devem-se preocupar com estratégias de testes antes de esta chegar ao utilizador final?
Seguindo boas práticas podemos dizer que cada aplicação deve ser testada antes de chegar ao utilizador final, e deve-se definir pelo menos os testes unitários e os testes de aceitação (em alguns casos pode haver necessidade de definir os testes de integração, com serviços externos, como por exemplo o BackEnd). Com a criação de testes vamos conseguir provar que o comportamento desenvolvido é o que está a ser testado, e se alguma alteração quebrar os testes ou o bom funcionamento da aplicação, é possível colocar em causa se houve um erro inicial, um erro no momento da alteração ou se o problema em causa não foi tido em conta, e claro está, proceder à correção.
Tipos de testes
A fase de testes é o processo que permite garantir que o desenvolvimento realizado faz efetivamente o que foi definido inicialmente. Esta fase pode incluir vários tipos de testes, tendo cada um o seu propósito, resumidamente podemos dizer que:
- Os testes unitários são testes escritos normalmente pelo(s) programador(es) que visa validar as várias funcionalidades de forma isolada, ie, o programador cria vários testes para verificar que um determinado método, classe, módulo ou componente é válido de acordo com os requisitos e faz o que é expetável.
- Os testes de integração são testes criados com o objetivo de validar a integração de classes, módulo ou componentes umas com as outras. No caso de aplicações móveis podemos dar como exemplo para testes de integração a comunicação entre o backend e a aplicação móvel.
- Os testes de aceitação são testes criados maioritariamente pela equipa de QA, e que visa testar a aplicação como sendo uma caixa negra, ie, é sabido à partida que é possível realizar um conjunto de operações e ao efetuar essas operações é expetável um resultado final.
Na figura 1, podemos ver outros tipos de testes, e a relação custo/esforço e nº de testes, claro está que o mais comum é a criação de testes unitários, e nem sempre é feita a cobertura de todos os tipos de testes.
Execução automática de testes
Outra questão extremamente relevante, é a execução dos diversos testes ser um processo automático, ie, à medida que as alterações se vão refletindo se possa confirmar que tudo o que estava a funcionar está efetivamente a funcionar, sem que se tenha que recorrer a processos manuais. Por esta razão, muitas vezes é criando um sistema de integração continua (usando por exemplo Team City ou TFS Online), em que na operação de checkin / push para o gestor de controlo de versões são executados todos os testes, referente à aplicação, e só após a confirmação de que todos os testes estão OK é que são aceites as novas funcionalidades ou alterações por parte do servidor.
Um programador mais atento vai questionar-se: é verdade que posso executar os testes unitários e de integração em processo automático, usando as ferramentas de desenvolvimento e de testes (seja NUnit ou MSTest), mas então, e os testes de aceitação? Uma vez que para verificar os diversos testes de aceitação é preciso executar a aplicação!? Vou ter constantemente uma equipa de QA a fazer o processo manualmente?
Neste artigo vamos ver como podemos escrever e executar os testes de aceitação de forma automática recorrendo à solução da Xamarin, o Test Cloud.
Descrição
Para dar suporte ao artigo, consideremos a aplicação TODO, desenvolvida com base na plataforma Xamarin, cujo código fonte pode ser obtido no seguinte endereço https://github.com/xamarin/xamarin-forms-samples/tree/master/Todo.
Consideremos agora que foi terminada uma das fases de desenvolvimento, e que existe um conjunto de funcionalidades testadas recorrendo a testes unitários e de integração. Visto isto, a equipa de desenvolvimento e/ou a equipa de QA pretende proceder à criação de testes de aceitação, para validar todo o fluxo da aplicação e as diversas funcionalidades. Desta forma, vamos proceder à criação dos testes de aceitação, recorrendo à biblioteca Xamarin.UITest.
Xamarin.UITest
A Xamarin.UITest é uma biblioteca desenvolvida pela Xamarin que permite escrever os testes automáticos de aceitação, ao nível da UI, de aplicações desenvolvidas com base na plataforma Xamarin. Esta biblioteca é baseada em Calabash – uma biblioteca que permite escrever testes automáticos de aceitação, ao nível UI, para aplicações nativas iOS e Android.
Na figura 3, podemos ver o diagrama de decisão relativo às frameworks que podemos utilizar nas aplicações móveis.
Esta biblioteca:
- É baseada em C# e usa a biblioteca NUnit (versão 2.6.4)
- Está apenas disponível para Xamarin.iOS e Xamarin.Android
- É suportada pelos diversos IDE (Xamarin Studio e Visual Studio)
- O Xamarin Studio disponibiliza projetos template para Xamarin.iOS, Xamarin.Android e Cross-Platform
- O Visual Studio apenas disponibiliza projetos template para projetos Cross-Platform
- Está disponível através de pacote Nuget – cuja versão atual é Xamarin.UITest 1.2.0
- É executado sobre um agente, Xamarin Test Cloud Agent, que vai permitir executar os testes sobre a aplicação (quer estejamos perante o simulador ou um dispositivo)
Criação de projeto
Comecemos por abrir o projeto TODO no Xamarin Studio, como podemos visualizar nas imagens seguintes.
O template do projeto de testes, que acabamos de criar, inclui dois ficheiros: AppInitializer.cs
e Test.cs
.
AppInitializer
A classe AppInitializer
, com apenas um método (StartApp
) irá:
- Definir a aplicação sobre qual correm os testes
- Com base no pacote APK, IPA ou bundle (.app)
app = ConfigureApp.iOS.AppBundle("../../path/todo.app"); app = ConfigureApp.Android.ApkFile("../../path/todo.apk");
- Com base no nome da aplicação instalada no dispositivo
app = ConfigureApp.iOS.InstalledApp("com.xamarin.todo"); app = ConfigureApp.Android.InstalledApp("com.xamarin.todo");
- Com base no projeto definido na solução
- Com base no pacote APK, IPA ou bundle (.app)
- Definir o dispositivo que irá executar os testes (por omissão é usado o simulador)
- Iniciar a aplicação, quando o método
StartApp
é invocado
Para saber mais detalhes, consulte a documentação fornecida pela Xamarin:
Para o caso da aplicação TODO iremos ter o seguinte code snippet:
public class AppInitializer { public static IApp StartApp (Platform platform) { // TODO: If the iOS or Android app being tested is included in the solution // then open the Unit Tests window, right click Test Apps, select Add App Project // and select the app projects that should be tested. // The iOS project should have the Xamarin.TestCloud.Agent NuGet package // installed. To start the Test Cloud Agent the following code should be // added to the FinishedLaunching method of the AppDelegate: // #if ENABLE_TEST_CLOUD // Xamarin.Calabash.Start(); // #endif if (platform == Platform.Android) { return ConfigureApp .Android .ApkFile ("../../../Todo.Droid/bin/Debug/TodoDroid.apk") .StartApp (); } return ConfigureApp .iOS .AppBundle ("../../../Todo.iOS/bin/iPhoneSimulator/Debug/TodoiOS.app") .StartApp (); } }
De realçar que na configuração inicial do pacote da aplicação para iOS, é possível surgir o erro
SetUp: System.Exception: The app bundle in XTC/Todo/PCL/Todo.iOS/bin/iPhoneSimulator/Debug/TodoiOS.app does not seem to be properly linked with Calabash. Please verify that it includes the Calabash component.
que significa que a aplicação iOS não contém a referência para o Xamarin Test Cloud Agent ou não contém a chamada ao método Xamarin.Calabash.Start()
no event handler AppDelegate.FinishedLaunching
. Para o caso em que este erro continue a surgir e esteja tudo bem configurado, é recomendável que se apague a pasta bin
do projeto de iOS e se faça build novamente.
Tests
A classe Tests
define um método que é designado por setup
que permite iniciar os testes sobre a UI da aplicação, e contém os vários testes para as diversas plataformas (na prática podem existir mais do que uma classe com testes, dependendo da organização destes).
Por omissão, esta classe está definida para lançar os testes nas duas plataformas, isto porque a classe está decorada com os seguintes atributos:
[TestFixture (Platform.Android)] [TestFixture (Platform.iOS)] public class Tests { ... }
Isto significa, se os testes definidos estiverem a suportar mais do que uma plataforma, a sua execução originará que vários simuladores iniciem a aplicação ao mesmo tempo (em alguns casos poderá ter interesse analisar em simultâneo o comportamento da aplicação nas diversas plataformas, não sendo, no entanto, um cenário comum).
O IDE irá lançar a aplicação no simulador ou no dispositivo, consoante o que estiver configurado. No caso da plataforma Android é requisito haver pelo menos um dispositivo conectado ao ADB, para que assim seja possível executar a aplicação e consequentemente os testes. É também requisito que a aplicação tenha permissões de internet, independentemente se esta requer o envio/receção de dados, uma vez que a anatomia da biblioteca requer esta permissão.
Nota: Sendo a biblioteca Xamarin.UI.Tests baseada em NUnit, é possível usar o atributo [Category]
para categorizar os testes e desta forma organizar os diversos testes.
Interface IAPP
A classe Tests
pode ser alterada, sendo possível definir os testes que se pretender. A interface IApp acessível por esta classe, permitirá a interação com a UI da aplicação, e portanto, é possível localizar elementos gráficos (textbox, botões, …), lançar eventos (como por exemplo “Tapping”, “Typing”), entre outras operações como podemos ver na figura 9, e iremos descrever mais à frente neste artigo.
Vejamos alguns code snippets:
- Tirar screenshot à aplicação e atribuição do nome da imagem
app.Screenshot ("First screen.");
- Pressionar o botão com o texto ou id “Add”
app.Tap (c => c.Marked ("Add"));
- Obtenção do botão (visível) com o texto ou id “Save”
AppResult[] matchedItems = app.Query( c => c.Button().Marked("Save"));
- Obtenção de controlos baseado no tipo por plataforma
- Para iOS
var matches = app.Query(c => c.Class("UILabel")); var matches = app.Query(c => c.Class("TextView"));
- Para Android
var matches = app.Query(c => c.Button()); var matches = app.Query(c => c.TextField());
- Para iOS
Execução de testes localmente
Atualmente o melhor cenário para correr os testes será usando o Xamarin Studio num Mac, uma vez que é a única forma de executar os testes para iOS. No Xamarin Studio é possível escolher a vista Unit Testing, como podemos ver na figura 10.
No menu “Unit Testing”, do lado direito, é possível escolher o(s) teste(s) que pretendemos executar, como podemos ver na figura 11.
Portanto, para o código fornecido pela classe Tests
[TestFixture (Platform.Android)] [TestFixture (Platform.iOS)] public class Tests { IApp app; Platform platform; public Tests (Platform platform) { this.platform = platform; } [SetUp] public void BeforeEachTest () { app = AppInitializer.StartApp (platform); } [Test] public void AppLaunches () { app.Screenshot ("First screen."); } }
O construtor da classe é invocado, e de seguida é invocado o método Setup
que irá conhecer a plataforma para a qual os testes vão ser executados, e por fim o método AppLaunches
é invocado e um screenshot é tirado. Considerando que vamos executar os testes apenas para iOS, a figura 12, mostra a aplicação no simulador de iOS.
O resultado da execução irá ser apresentado no painel Test Results, como podemos ver na figura 13.
Xamarin Test Record
Os testes de aceitação podem ser definidos manualmente, no entanto, a sua definição manual pode não ser um processo tão simples quanto isso. No lançamento do Xamarin 4, a Xamarin lançou a versão preview do Xamarin Test Record, que é uma aplicação que permite gravar as operações efetuadas na aplicação, ie, o Test Record irá escrever os testes, que irão verificar o comportamento da aplicação, que são obtidos pela execução manual da aplicação. Desta forma é possível replicar automaticamente o comportamento efetuado pelo utilizador.
À data da publicação deste artigo, o Xamarin Teste Record está apenas disponível para Mac, sendo possível obtê-lo em https://xamarin.com/test-cloud/recorder.