Android: Aumentando a qualidade com teste funcional utilizando Robotium

Existe uma frase de Abraham Lincoln: “Se eu tivesse oito horas para derrubar uma árvore, passaria seis horas afiando meu machado”. Você deve estar pensando nesse exato momento: “O que tem haver machado e árvore com o desenvolvimento de software?” e minha resposta seria: “Nada.”, porém a idéia da frase, podemos trazê-la para nosso mundo de desenvolvimento de software.

O que podemos tirar dessa frase é que há momentos que necessitamos parar e tentar trazer uma segurança e qualidade para o nosso código, e acredito que uma das formas de podermos “afiar” nosso “machado” é a prática de testes funcionais e também os testes unitários. Sem sombra de dúvidas.

Neste post irei apresentar a ferramenta Robotium utilizada para criar testes funcionais no Android para garantir maior qualidade para nossos sistemas.

O bacana do Robotium é que está sendo constantemente melhorado, as suas features são liberadas constantemente. Uma que estou bastante ansioso é a de cobertura de código:

Features we want to implement in the future
Automatic measurement of user interface test coverage.

Para quem ainda não sabe o que é teste funcional, conhecido também como teste de caixa preta, consiste em computar o comportamento externo do software, deixando de lado o comportamento interno. Básicamente é dado informações de entrada, processado e esperado um resultado e este resultado é comparado com um previamente esperado.

Exemplo prático, imagine que eu tenha uma tela de login, que deverá possuir 2 campos para serem preenchidos de nome de usuário e senha. Posso validar através do teste funcional desde a presença dos edits, labels e botões.

Vamos pegar esse exemplo da tela de login.

Link do Robotium aqui.

É necessário baixar o .jar do Robotium e adiciona-lo ao projeto de teste.

Primeiramente vamos criar um projeto Android, chamaremos de “TesteComRobotium” e marcaremos o check “Create a Test Project” para ser criado um projeto de testes também.



Vamos pegar o layout main.xml do projeto criado e colocaremos o código a seguir:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Usuário" />

    <EditText
        android:id="@+id/edtUsuario"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Senha" />

    <EditText
        android:id="@+id/edtSenha"
        android:password="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnLogar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Logar" />

</LinearLayout>


Feito isso, vamos criar uma classe no projeto de testes chamada “TesteComRobotiumActivityTest” para podermos testar a nossa tela. Coloque a implementação a seguir:

//Esta classe irá herdará de uma classe do nosso framework Robotium
public class TesteComRobotiumActivityTest extends ActivityInstrumentationTestCase2<TesteComRobotiumActivity>{

	private Solo solo; //Criada variavel solo que é responsavel por acessar a activity
	
	public TesteComRobotiumActivityTest() {
		super("br.robotium", TesteComRobotiumActivity.class); //Definindo a activity que iremos testar
	}
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		solo = new Solo(getInstrumentation(), getActivity());
	}
	
	public void testLogin(){
		assertTrue(solo.searchText("Usuário"));//Irá verificar se existe o texto "Usuário" na tela
		assertTrue(solo.searchText("Senha"));//Irá verificar se existe o texto "Usuário" na tela
	}	
}


Feito isso, poderemos rodar o teste e verificar se o teste passará. Clicando com o botão direito em cima do projeto e selecionando Run As > Android JUnit Test



E logo após poderemos ver o resultado:



As duas condições impostas no metodo testLogin irão passar.

Podemos notar que a variável ‘solo’ chama o metodo searchText, este método irá varrer na tela e procurar o texto passado como parâmetro, caso o texto seja encontrado, será retornado true, caso contrario, false. E também utilizamos o método assertTrue, ele significa que estamos esperando uma resposta positiva da função imposta no seu parâmetro de entrada, caso o parâmetro de entrada venha retornar false neste método, o nosso teste irá falhar.

Até aí tudo bem, agora precisamos validar se o nosso usuário e senha estão sendo validados após clicar em “Logar”. Para realizar o teste iremos implementar o seguinte trecho de código dentro da Activity:

public class TesteComRobotiumActivity extends Activity implements OnClickListener{

	private EditText edtUsuario;
	private EditText edtSenha;
	private Button btnLogar;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        edtUsuario = (EditText) findViewById(R.id.edtUsuario);
    	edtSenha = (EditText) findViewById(R.id.edtSenha);
    	btnLogar = (Button) findViewById(R.id.btnLogar);
    	btnLogar.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
    	switch (v.getId()) {
		case R.id.btnLogar:
			validarLogin();
			break;
		}
    }

	private void validarLogin() {
		//Caso o usuario seja admin e a senha 123...
		if (edtUsuario.getText().equals("admin") && edtSenha.getText().equals("123")) {
			Toast.makeText(this, "Login realizado com sucesso!", 2000).show();
		}else{
			Toast.makeText(this, "Usuário ou senha incorretos!", 2000).show();
		}
	}
}


Fizemos básicamente implementar um processo de “validação” para o login, quando o nome de usuário for “admin” e a senha for “123″ será exibida mensagem de login realizado com sucesso, caso contrário, será exibida uma mensagem de usuário ou senha incorretos. Iremos agora fazer um teste funcional em cima disso.

Adicionaremos as seguintes linhas de código na nossa classe de teste:

         public void testUsuarioESenhaIncorretos(){
		//Estaremos criando os 2 edits para podermos preencher posteriormente...
		EditText edtUsuario = (EditText) solo.getView(br.robotium.R.id.edtUsuario);
		EditText edtSenha = (EditText) solo.getView(br.robotium.R.id.edtSenha);
		
		solo.enterText(edtUsuario, "bla");
		solo.enterText(edtSenha, "bla");
		solo.clickOnButton("Logar");
		assertTrue(solo.searchButton("Usuário ou senha incorretos!")); 	
	}
	
	public void testUsuarioESenhaCorretos(){
		//Estaremos criando os 2 edits para podermos preencher posteriormente...
		EditText edtUsuario = (EditText) solo.getView(br.robotium.R.id.edtUsuario);
		EditText edtSenha = (EditText) solo.getView(br.robotium.R.id.edtSenha);
		
		solo.enterText(edtUsuario, "admin");
		solo.enterText(edtSenha, "123");
		solo.clickOnButton("Logar");
		assertTrue(solo.searchButton("Login realizado com sucesso!")); 	
	}



E ao rodar novamente poderemos ver passam todos os testes.


Bem, essa é uma das possibilidades de melhoria de qualidade de software, não é com ela que poderemos garantir um software 100% funcionando, isento de bugs. Existem algumas brechas para este tipo de teste. Existem vários outros tipos de testes, mas minha opinião o ideal e que acredito que possa trazer grande é fazer a junção de testes funcionais e testes unitários para garantir ainda mais a qualidade do nosso software.

Existem possibilidades a mais para serem testadas com o Robotium, mas o intuito deste post era só apresentar o básico da ferramenta. Em outro momento demonstrarei outros exemplos mais complexos.

Android: Mudando de tela e passando dados

Bem, é muito importante no Android podermos trocar de telas e passar algum conteúdo, alguma informação de uma tela para outra. Isso é possível através da Intent.
A Intent possui um método chamado putExtra que possui dois argumentos de entradas, onde o primeiro é o nome do parâmetro e o segundo o valor do mesmo.

Imagine que estamos na ActivityPrincipal e queremos ir para a ActivitySecundaria, onde precisamos passar o valor de uma variável do tipo string chamada nome com o conteúdo “joãozinho”.

Teremos o seguinte:

  String variavelNome = "Joãozinho";
  Intent intent = new Intent(this, ActivitySecundaria.class);
  intent.putExtra("nome", variavelNome);
  startActivity(intent);

Neste trecho de código, podemos ver que estamos criando a variavelNome e atribuindo o valor “Joãozinho” para ela, e logo em seguida instânciamos uma intent com a INTENÇÃO de de passar o valor da variável e depois chamar a outra tela(ActivitySecundaria).

Até aí tudo bem, e na ActivitySecundaria, como devemos fazer?
Nela, precisaremos também criar uma Intent que “capture” o valor do “nome” que despejamos na ActivityPrincipal.
Ficará da seguinte forma:

  Intent intent = getIntent();
  String nome = intent.getStringExtra("nome");

Instanciamos a intent com o getIntent() e logo após chamamos o metodo getStringExtra(“nome”) para capturar o conteúdo que tínhamos passado na tela anterior.
Caso o valor que quiséssemos capturar fosse um double, por exemplo, deveríamos utilizar o método
getDoubleExtra() e se fosse um boolean seria getBooleanExtra() e assim por diante…

CategoriasAndroid, Intent

Design Pattenrs: Singleton

Você já teve a necessidade de instânciar uma única vez um objeto?
Pois bem, Singleton é um padrão de projeto para desenvolvimento de software.
Basicamente, este padrão garante a existência de somente apenas uma única instância de uma determinada classe, isso quer dizer que o padrão Singleton vem a previnir que um objeto não seja instanciado mais de uma vez.

Vários projetos de software precisam que determinadas classes possuam apenas uma instância. Como por exemplo um objeto que contém a configuração do sistema.

Podemos ver a modelagem logo abaixo de como ficaria:

Iniciando o desenvolvimento no Android – Parte 2/2

Nesta segunda parte iremos colocar um botão em uma tela, onde este botão terá uma ação de chamar uma outra tela. Para quem não viu a primeira parte, clique aqui.

Vamos abrir o main.xml, que nada mais é do que o layout principal do nosso aplicativo.

Dando um duplo clique no arquivo main.xml teremos a seguinte visualização:

Podemos notar que no lado esquerdo da imagem a cima temos o “Palette” que é onde ficam os objetos, separados por abas. Logo no canto inferior da imagem podemos observar dois botões, o “Graphical Layout” e o “main.xml”, onde o primeiro podemos visualizar a tela e o segundo visualizar o código xml da tela.

Bem, agora vamos adicionar um botão na tela, temos duas opcões: clicar e arrastar o botão ou digitar na mão o código xml que gere um botão. Vale lembrar que, ao adicionar um botão no estilo drag-drop podemos ver o xml gerado.

Após adicionar o botão, poderemos mudar as propriedades do mesmo, como o nome do botão e o texto que será exibido no botão.



Como podemos ver nas imagens a cima, coloquei o texto a ser exibido no botão de “Proxima Tela”, e o nome do botão de “btnTela2″.

Vamos agora criar uma nova Activity:

E vamos chama-la de Tela2Activity:

Logo após vamos criar um arquivo xml chamado tela2.xml:


E incluiremos um textview no layout, e colocaremos a propriedade text dele de “Tela 2″.

Feito isso, vamos dar acão para o botão na activity principal do projeto.

import br.com.R.id;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import br.com.Tela2Activity;

public class ProjetoAndroidActivity extends Activity {
//Criando uma variável chamada botao2 e referenciando ela ao botão btnTela2.
	Button botao2 = (Button) findViewById(id.btnTela2);	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//desenhando a view main na activity corrente.
        setContentView(R.layout.main);

//Implementando uma acão no botao2.
        botao2.setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View v) {
//Criando uma intent, onde iremos dizer para onde essa "intenção" irá.
				Intent it = new Intent(ProjetoAndroidActivity.this, Tela2Activity.class);
//Funcão para dar inicio a intent.
	  		    startActivity(it);
			}
		});

    }
}

Agora vamos na activity da Tela 2 e vamos mandar ela desenhar o layout respectivo.

import android.app.Activity;
import android.os.Bundle;

public class Tela2Activity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
//desenhando a tela2.xml
		setContentView(R.layout.tela2);
	}
}

E por ultimo precisamos declarar no arquivo AndroidManifest.xml a activity criada.
Vale salientar que todo e qualquer criacão de Activity deverá ser declara no AndroidManifest, para quem programa em Java Web, esse arquivo tem a mesma finalidade que o web.xml.


Clicando no botão “AndroidManifest.xml” para que podemos adicionar o xml abaixo:

<activity android:name=".Tela2Activity"/>    

E o AndroidManifest ficará assim:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="br.com"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".ProjetoAndroidActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity android:name=".Tela2Activity"/>    
    </application>

</manifest>

E agora é só rodar o aplicativo… ;)

CategoriasActivity, Android, Intent

Iniciando o desenvolvimento no Android – Parte 1/2

outubro 31, 2011 2 comentários

Olá galerinha, estou aqui mais uma vez com este post para demonstrar como fazer uma aplicação Android simples. NEste post será dividido em 2. Onde essa primeira parte irei mostrar para vocês como criar o projeto e roda-lo. Já na segunda parte iremos colocar um botão em uma tela, onde este botão terá uma ação de chamar uma outra tela. Básicamente iremos utilizar Activity e Intent. O conceito dessas 2 estão neste post.

Bem, primeiramente precisaremos criar um projeto:

Preencheremos o nome do projeto…

Selecionaremos a versão do Android (selecionei a 2.2)

E por ultimo preencher o package.

Logo após finalizar será criado o projeto que conterá esses arquivos:

Vamos rodar o projeto e ver o que vai aparecer. Clicando com o botão direito em cima do projeto criado vamos em Run as > Android application.

Após fazer mandar rodar o app irá abrir uma janela, esta janela é a máquina virtual que já irá mostrar a aplicação. Um “hello world” padrão.

CategoriasActivity, Android, Intent

Arquitetura do Android – Parte 2/2

  • BroadcastReceiver
  • É responsável por receber os “anúncios” do sistema. Durante seu funcionamento, o Android executa vários eventos, como por exemplo o recebimento de mensagens(sms), alteração de configurações, etc. Quando um desses eventos ocorre, o Android envia um “anúncio” em broadcast para todas as aplicações do aparelho que possam vir a desejar recebe-la, porém o sistema não é o único que pode enviar esses anúncios, é possível também que outras aplicações possam vir a fazê-lo.

  • Notification
  • É uma forma interessante e agradável de informar ao usuário que alguma mensagem de alguma aplicação está ativa no momento.
    Nesta notificação o usuário pode visualizar o seu conteúdo ou simplesmente ignora-lo. Para visualização da notificação pode-se disparar uma intent para iniciar algum recurso ou processo diferente.

  • Service
  • É uma forma de criar componentes específicos para aplicações que precisem utilizar operações que possam demorar, evitando assim que o gerenciador do sistema operacional não destrua o processo e também que possuam funcionalidadesque executem de modo invisível, sem a interação do usuário.

    CategoriasAndroid

    ITDay 2011 – Android: Mercado&Desenvolvimento

    Bem pessoal, palestrei hoje (15/out/2011) no ITDay 2011, onde falei sobre o mercado e um pouquinho sobre o desenvolvimento na plataforma Android.

    CategoriasAndroid, Palestra, Software

    Design Patterns: Conceito

    Na engenharia de software um padrão de projeto é uma solução geral para certos problemas repetitivos que normalmente ocorrem no design do software. Um design Patterns (padrão de projeto) não é um projeto finalizado que possa vir a ser transformado imediatamente em código, e sim uma descrição/modelo de como se deve resolver um determinado problema que pode ser usado em diversas situações.

    Os padrões de design podem acelerar o processo de desenvolvimento, fornecendo paradigmas de desenvolvimento comprovados. Design de software eficaz requer considerar as questões que não podem tornar-se visíveis até mais tarde na execução. Reutilizando padrões de projeto ajuda a prevenir problemas sutis que podem causar grandes problemas e melhora a legibilidade do código para programadores e arquitetos familiarizado com os padrões.

    Arquitetura do Android – Parte 1/2

    Para quem não conhece a plataforma Android, ela é uma das tecnologias que mais cresce atualmente no mundo mobile.
    Para quem conhece um pouco de Java sai na frente, fazendo com que a curva de aprendizagem seja menor, porém o paradigma mobile é bem diferente do web e também do desktop.

  • Activity
  • Esta classe é responsável por controlar todo e qualquer evento ocorrido. Em relação aos controles visuais a classe Activity não se responsabiliza por cria-las, na verdade dentro dela é chamada a classe View, que essa sim é responsável pela chamada pelo controle visual, objetos de um game, canvas e etc.

    O Android trabalha com o conceito de pilhas, a forma que ele gerencia as Activity, ou seja, a tela que estiver na apresentação do celular, esta estará no topo da pilha. No momento em que se chama uma outra tela, esta nova irá para o topo e a que se encontrava anteriormente no topo fica em segundo lugar na pilha.

    O Android trata TODAS as Activitys da mesma forma, seja ela desenvolvida por “terceiros” ou nativa.

  • Intent
  • Podemos considerar que esta classe é a mais poderosa da estrutura do Android. É impossível imaginar a não utilização dela. É através dela que a aplicação irá se comunicar, não somente através de janelas da própria aplicação, como também com as aplicações nativas do Android.

    CategoriasActivity, Android, Intent

    Agile Brazil 2011 – Fortaleza

    Este ano um dos eventos sobre agilidade mais importante do país irá acontecer nesta próxima semana em fortaleza. O evento irá se inicializar dia 27 e terá seu termino dia 1º de Julho.

    Os dois primeiros dias do evento (27 e 28 de julho) ocorrerá alguns cursos, dentre eles cursos sobre TDD, certificação para scrum master, certificação para product owner e sobre Lean Thinking. O restante dos dias serão para palestras, workshops e etc.

    Neste grande evento teremos a oportunidade de ouvir o Jim Highsmith, consultor executivo para a ThoughtWorks, Vinícius Teles, um desenvolvedor e fundador da empresa ImproveIt e também o Joshua Kerievsky, um especialita na metodologia XP e Lean.

    CategoriasUncategorized
    Seguir

    Obtenha todo post novo entregue na sua caixa de entrada.

    Join 116 other followers