.gif" border="0" hspace="0">
Clique aqui para ler todos os artigos desta edição
Testes unitários em JME
Uma das estratégias que empresas utilizam na busca pela garantia e manutenção de um padrão de qualidade em seus produtos é o desenvolvimento de testes.
No mundo do desenvolvimento de software vem ocorrendo um fenômeno parecido. Desde o momento em que as exigências com relação à qualidade e à robustez do software aumentam, torna-se necessária a realização de testes nas aplicações com o objetivo de entregar produtos mais confiáveis. Muitas são as formas de se testar uma aplicação, por exemplo, submeter o trabalho a:
· testes de carga que procuram analisar o comportamento da aplicação no momento em que há um aumento de acessos;
· testes unitários, que têm por foco a análise das unidades que constituem os sistemas.
O foco deste artigo encontra-se nos testes unitários, mais precisamente, na modalidade de testes que podem ser realizados no momento da codificação para dispositivos portáteis. Discutiremos aqui a utilização de dois frameworks, um chamado j2meunit, para a tarefa da realização de testes unitários
O outro framework analisado será o JMUnit, que embora também seja para a aplicação de testes unitários, já não possui tantas semelhanças com o JUnit. Ainda assim é bastante prático, possuindo uma quantidade de opções de utilização um pouco maior, disponibilizando inclusive a possibilidade do uso de métodos de teste parametrizados.
Neste artigo serão exibidos exemplos da utilização dessas duas ferramentas após uma breve explicação de suas funcionalidades.
Metodologia de testes
Antes de entrarmos no foco desse artigo, frameworks de testes para o desenvolvimento de aplicações que rodam em dispositivos móveis, considero bastante interessante fazer um breve comentário a cerca de uma metodologia de implementação de testes no processo de desenvolvimento.
Existem várias formas de se integrar testes a um processo de desenvolvimento. A mais comum e talvez a mais intuitiva delas é a de efetuar os testes após ter sido feito o processo de codificação da unidade. Assim, por exemplo, primeiro fazemos a classe ‘A’ para então aplicarmos testes sobre ela. Entretanto, uma metodologia que vem ganhando espaço é a do desenvolvimento orientado a testes. Adotar esta metodologia, Test Driven Development (TDD), significa trabalhar no desenvolvimento dos testes antes mesmo de trabalhar na codificação das unidades do sistema. Por exemplo, supondo que queiramos fazer a classe Calculadora em que podem ser citados como métodos somar e subtrair, primeiro elaboraríamos o teste para os seus métodos para só então procedermos a construção deles.
À primeira vista, esta abordagem pode parecer um tanto quanto burocrática, afinal porque não começar logo a por a 'mão na massa' e só então passar para os testes. De fato, a aplicação desta metodologia pode, de início, ser um pouco mais lenta que a tradicional, entretanto, a sua adoção possibilita que o desenvolvedor tenha um código menos sujeito a bugs, uma vez que já de início são traçados os padrões de qualidade a que determinada parte do sistema deve obedecer.
Não bastasse isso, essa técnica diminui bastante algo que vou chamar de 'efeito sanfona' no desenvolvimento. Este ocorre quando o programador, ao passo que evolui no seu processo de codificação, precisa ficar voltando ao código gerado anteriormente para corrigir defeitos que acidentalmente tenham passado pelos seus olhos. Além disso, testes, quando bem feitos, servem como documentação de um sistema. Dessa forma, caso ainda seja preciso dar um ou outro passo atrás no processo, uma documentação mais completa é capaz de tornar esse processo menos demorado.
Onde obter os frameworks
Os dois frameworks tratados nesse artigo podem ser encontrados no sourceforge. O j2meunit, através do endereço http://j2meunit.sourceforge.net/, e o JMUnit através do endereço http://sourceforge.net/projects/JMUnit/.
J2ME Unit
Como será visto na parte prática deste artigo, a maneira como utilizamos o j2meunit é muito parecida com a forma como utilizamos o JUnit. Com isso, as pessoas que já possuem alguma experiência com a utilização do JUnit terão mais facilidade para entender este artigo.
Vamos começar pela principal diferença existente entre esses dois frameworks. O JUnit faz forte uso de reflexão, talvez a chave de sua facilidade, já que para criarmos um método de teste com esse framework precisamos apenas iniciar o nome desse método com o prefixo ‘test’, por exemplo, testSoma(). Entretanto, a API de reflexão não é disponível em JME, logo encontramos uma grande diferença na forma como ambos irão funcionar. Quando trabalhamos com JUnit é fundamental que todos os nossos métodos comecem com ‘test’, com j2meunit não temos essa necessidade, este possui outros meios que tornam possível rodar os seus testes. Entretanto, as boas práticas recomendam a utilização deste padrão também quando se trabalha com dispositivos móveis, uma vez que isso torna o código mais legível. A partir da manutenção desse padrão, será mais fácil para qualquer pessoa identificar dentro de sua classe de testes quais os métodos são realmente de testes e quais são aqueles que existem apenas para auxiliar estes métodos.
Antes de começarmos a nossa prática, vamos definir o conceito de Testcase. Damos esse nome à classe desenvolvida com o objetivo de efetuar testes automáticos sobre uma das unidades do sistema. Assim, supondo termos um sistema que simboliza um carro e fará uso das classes Pneu e Suspensão, teríamos, em uma situação ideal, um Testcase para a classe Pneu, outro para Suspensão, bem como um para cada uma das classes desenvolvidas, ou seja uma classe de testes responsável por testar cada uma das unidades do sistema.
Iremos começar a nossa prática explicando como devemos proceder para a criação de um Testcase com o j2meunit. Esta tarefa é muito simples, tudo o que devemos fazer é uma classe que herde da classe j2meunit.framework.TestCase, por exemplo:
public class ATest extends TestCase
Feito isso, podemos começar a criação dos nossos métodos de teste, de preferência, por questões de legibilidade, fazendo uso da convenção legada pelo JUnit, iniciando o nome de seus métodos de teste com o prefixo ‘test’.
A grande desvantagem da inexistência de reflexão é que para suprir essa limitação é preciso criar um método chamado suite() que deve fazer com que os testes rodem de forma explícita e que deve ter como retorno um objeto Test. Esse procedimento também é possível no JUnit, mas não chega a ser uma obrigação.
Test é uma interface que possui apenas três métodos e é implementada entre outras pela classe TestSuite, que será comentada mais adiante. Os três métodos de teste existentes na interface são utilizados apenas para que a TestSuite execute o seu trabalho. Eles servem para:
· Contar a quantidade de test cases rodados: public abstract int countTestCases();
· Calcular o número de etapas de um teste que devem ser monitoradas: public abstract int countTestSteps();
· Rodar e coletar os resultados dos testes: public abstract void run(TestResult result).
Se você não estiver satisfeito com as opções de TestSuite, qualquer pessoa pode fazer sua própria classe que a substitua, bastando para tal implementar a interface Test.
É nesse método, suite(), que estão incluídos todos os métodos de teste que o desenvolvedor implementou
A forma mais indicada e mais comum de se fazer a adição desses testes no TestSuite é através da interface j2meunit.framework.TestMethod. Essa atua como um wrapper, uma espécie de casca que deve envolver cada um dos métodos de testes que devem rodar de forma simultânea. Esta interface possui um único método, chamado ‘run’, que recebe como parâmetro um TestCase que representa a classe de testes e o método de teste, como pode ser visto na Listagem 1. É necessária a criação de uma instância de TestMethod para cada método adicionado.
Além de TestMethod, podem ser adicionados ao TestSuite vários TestCase, como pode ser visto na Listagem 2.
Da mesma forma como fazemos com o JUnit, também podemos criar uma classe que rode todos os testes de uma vez. Para isso, basta que criemos um método suite() nessa classe que tenha adicionado a si todas as suites das outras classes de teste, como foi dito acima.
O j2meunit disponibiliza duas alternativas para a visualização dos resultados dos testes: através do console em modo texto ou então através do simulador, fazendo os testes serem rodados por uma espécie de MIDlet.
Para analisarmos os resultados dos testes em modo texto precisamos apenas fazer uma classe com um método main(), que pode ser a própria classe do teste ou uma em especial, responsável por rodar todos os testes. Considero a última estratégia mais interessante, já que torna mais simples o trabalho do gerenciamento dos testes, tornando ele mais automático.
Dentro do método main() devemos chamar o método main() da classe j2meunit.textui.TestRunner. Esse último deve receber um array de String composto pelo nome das classes onde existem testes que devem ser rodados, ou seja, pode ser composto pelo nome de uma única classe que deverá rodar todos os testes, ou então o nome de cada uma das classes de teste.
Para rodar os testes
Quando queremos trabalhar com MIDlets ainda existe outra opção, justamente para situações em que não queiramos fazer uma subclasse de TestRunner. Com o objetivo de se evitar esse trabalho é possível, no arquivo descritor do projeto (.jad), adicionar a propriedade J2MEUnitTestClasses e passarmos para ela como valor a classe que é suite de testes de outras classes, ou seja, aquela que irá gerenciar as outras classes de testes. Isso porque a classe TestRunner possui um método startApp() onde é feita a busca por essa propriedade e consequentemente pela suite de testes que esteja ligada a ela.
...