Original:
http://peczenyj.blogspot.com/2008/08/voltas-s-aulas-e-o-java.html
Na época de volta às aulas nas faculdades percebe-se uma grande invasão de alunos desesperados em foruns de informática para resolverem os seus execícios. É facil reconhecer um aluno em pânico com o seu primeiro while ou algum exercício sobre Fibonacci: eles não tentam, simplesmente colam o enunciado do problema esperando a resposta pronta.
Entretanto tão bizarro quanto são os exercícios propostos: um programa que leia pergunte 2 numeros e retorne a soma, ou um programa para calcular alguma coisa que pergunte ao usuário... perai, pergunte? Um programa perguntando? Como?
Este é o típico programa 'interativo' com o usuário. Quando não usa a entrada padrão (algo completamente misterioso para boa parte dos alunos), usam algum recurso SWING. Mas sera que ninguem pensa o quão PREJUDICIAL são estes exercícios?
Normalmente o aluno se preocupa com a apresentação do mesmo, fazendo frescuras de menuzinhos, asteriscos pra lá e pra cá... e o algoritmo que é bom nada. Sinceramente: dane-se os menuzinhos. Sabem quantos programas com menuzinhos e que vão perguntar alguma coisa pro usuario vcs vão fazer na vida profissional de vcs? 0! Zero! Nenhum!
Existem muitas formas de interação com o usuario, hoje em dia vc pode ter interfaces web, por exemplo. Eu acho que, num primeiro momento, a única interação com o usuario deveria ser escrever na tela. Nada mais que isso se o camarada não sabe o que significa um NullPointerException.
Exemplo pratico:
- Prepare um diretório para trabalhar (suponho que vc vai usar linux, senão deve ser facil portar este exemplo para outros sistemas operacionais).
- Crie um diretorio lib e copie o junit-4.4.jar pra lá (use o google pra baixar esse arquivo, se vc não conseguir saia do curso de informática).
- Crie a estrutura abaixo, ainda no diretório de trabalho:
src/java
src/test
- Instale o aplicativo ant (de novo o google te ajuda, alias vc tem algum JDK instalado, certo??).
- Crie um arquivo chamado build.xml no diretorio de trabalho.
- Baixe o arquivo ant-junit.jar daqui [ http://www.java2s.com/Code/Jar/ANT/Downloadantjunitjar.htm ] e copie o .JAR para ~/.ant/lib (se não existe, crie).
Agora vem a proposta: baseado nessa interface:
public interface Algoritmo{
/* dado um numero, retorna true se for par */
boolean ehPar(int numero);
/* calcula o valor absoluto ou modulo de um numero, ex: -1 vira 1, 1 vira 1 */
int calculaModulo(int numero);
/* calcula algum termo da série de fibonacci: se 0, mostra o primeiro, se 1 mostra o segundo...*/
int calculaFibonacci(int elemento);
/* calcula o fatorial do numero indicado */
long calculaFatorial(int numero);
}
Vais criar uma classe chamada, digamos, SuaClasse que implementa esta interface (percebeu que tudo deve ficar em src/java não é?). Não pense na implementação dessa classe ainda.
No diretorio src/test vc vai salvar esta classe:
import junit.framework.TestCase;
public class AlgoritmoTeste extends TestCase{
Algoritmo algoritmo;
public void setUp(){
algoritmo = new SuaClasse();
}
public void tearDown(){
algoritmo = null;
}
public void testEhPar() throws Exception{
assertTrue("2 deve ser par",algoritmo.ehPar(2));
assertTrue("4 deve ser par",algoritmo.ehPar(4));
assertTrue("6 deve ser par",algoritmo.ehPar(6));
assertTrue("1 NAO deve ser par",!algoritmo.ehPar(1));
assertTrue("3 NAO deve ser par",!algoritmo.ehPar(3));
assertTrue("5 NAO deve ser par",!algoritmo.ehPar(5));
}
public void testCalculaModulo() throws Exception{
assertTrue("modulo de 3 deve ser 3",algoritmo.calculaModulo(3) == 3);
assertTrue("modulo de -3 deve ser 3",algoritmo.calculaModulo(-3) == 3);
assertTrue("modulo de 5 deve ser 5",algoritmo.calculaModulo(5) == 5);
assertTrue("modulo de -5 deve ser 5",algoritmo.calculaModulo(-5) == 5);
}
public void testCalculaFibonacci() throws Exception{
assertTrue("elemento 0 da serie fibonacci deve ser 0",algoritmo.calculaFibonacci(0) == 0);
assertTrue("elemento 1 da serie fibonacci deve ser 1",algoritmo.calculaFibonacci(1) == 1);
assertTrue("elemento 2 da serie fibonacci deve ser 1",algoritmo.calculaFibonacci(2) == 1);
assertTrue("elemento 3 da serie fibonacci deve ser 2",algoritmo.calculaFibonacci(3) == 2);
assertTrue("elemento 4 da serie fibonacci deve ser 3",algoritmo.calculaFibonacci(4) == 3);
assertTrue("elemento 5 da serie fibonacci deve ser 5",algoritmo.calculaFibonacci(5) == 5);
assertTrue("elemento 6 da serie fibonacci deve ser 8",algoritmo.calculaFibonacci(6) == 8);
assertTrue("elemento 7 da serie fibonacci deve ser 13",algoritmo.calculaFibonacci(7) == 13);
assertTrue("elemento 11 da serie fibonacci deve ser 89",algoritmo.calculaFibonacci(11) == 89);
assertTrue("elemento 13 da serie fibonacci deve ser 223",algoritmo.calculaFibonacci(13) == 233);
}
public void testCalculaFatorial() throws Exception{
assertTrue("Fatorial de 1 deve ser 1",algoritmo.calculaFatorial(1) == 1);
assertTrue("Fatorial de 2 deve ser 2",algoritmo.calculaFatorial(2) == 2);
assertTrue("Fatorial de 3 deve ser 6",algoritmo.calculaFatorial(3) == 6);
assertTrue("Fatorial de 4 deve ser 24",algoritmo.calculaFatorial(4) == 24);
assertTrue("Fatorial de 5 deve ser 120",algoritmo.calculaFatorial(5) == 120);
assertTrue("Fatorial de 6 deve ser 720",algoritmo.calculaFatorial(6) == 720);
assertTrue("Fatorial de 10 deve ser 3628800L",algoritmo.calculaFatorial(10) == 3628800L);
}
}
Uma ideia sobre o JUnit pode ser encontrada aqui: [ http://guj.com.br/java.tutorial.artigo.40.1.guj ], alias o guj, na sessão de tutoriais, explica varias coisas, é ótimo material de referência!
Ok, vc tem a interface que vc deve respeitar e um arquivo de teste. Vamos falar do arquivo de build do ant.
<project name="Meu Projeto" basedir="." default="dist">
<description>
Aprendendo a fazer um build.xml para o ant
</description>
<property name="lib" location="lib"/>
<property name="src" location="src/java"/>
<property name="test" location="src/test"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<path id="classpath.test">
<pathelement location="${test}" />
<pathelement location="${build}" />
<pathelement location="${lib}/junit-4.4.jar" />
</path>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init" description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile" description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/Algortimo-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean" description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
<target name="test" depends="compile">
<javac srcdir="${test}">
<classpath refid="classpath.test"/>
</javac>
<junit>
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<test name="AlgoritmoTeste"/>
</junit>
</target>
</project>
A utilização desse arquivo é muito simples
$ ant
isso deve compilar a sua classe e gerar um jar (pode ser util no futuro).
$ ant clean
limpa os diretorios que vc acabou de criar com as suas paradas compiladas.
$ ant test
compila e executa os testes unítarios.
É claro que vc vai dizer, e agora??? Bom, veja isso:
public class SuaClasse implements Algoritmo{
public boolean ehPar(int numero){return false;}
public int calculaModulo(int numero){ return -1;}
public int calculaFibonacci(int elemento){return -1;}
public long calculaFatorial(int numero){return -1;}
}
Olha que legal! Uma classe que tem o minimo pra compilar! Agora vamos testar...
$ ant test
Buildfile: build.xml
init:
[mkdir] Created dir: /home/GLOBO.COM/peczenyj/test/junit/build
compile:
[javac] Compiling 2 source files to /home/GLOBO.COM/peczenyj/test/junit/build
test:
[javac] Compiling 1 source file
[junit] Testsuite: AlgoritmoTeste
[junit] Tests run: 4, Failures: 4, Errors: 0, Time elapsed: 0.005 sec
[junit]
[junit] Testcase: testEhPar(AlgoritmoTeste): FAILED
[junit] 2 deve ser par
[junit] junit.framework.AssertionFailedError: 2 deve ser par
[junit] at AlgoritmoTeste.testEhPar(Unknown Source)
[junit]
[junit]
[junit] Testcase: testCalculaModulo(AlgoritmoTeste): FAILED
[junit] modulo de 3 deve ser 3
[junit] junit.framework.AssertionFailedError: modulo de 3 deve ser 3
[junit] at AlgoritmoTeste.testCalculaModulo(Unknown Source)
[junit]
[junit]
[junit] Testcase: testCalculaFibonacci(AlgoritmoTeste): FAILED
[junit] elemento 0 da serie fibonacci deve ser 0
[junit] junit.framework.AssertionFailedError: elemento 0 da serie fibonacci deve ser 0
[junit] at AlgoritmoTeste.testCalculaFibonacci(Unknown Source)
[junit]
[junit]
[junit] Testcase: testCalculaFatorial(AlgoritmoTeste): FAILED
[junit] Fatorial de 1 deve ser 1
[junit] junit.framework.AssertionFailedError: Fatorial de 1 deve ser 1
[junit] at AlgoritmoTeste.testCalculaFatorial(Unknown Source)
[junit]
[junit]
[junit] Test AlgoritmoTeste FAILED
BUILD SUCCESSFUL
Total time: 1 second
Agora basta escrever codigo de verdade na SuaClasse e testar, estara pronto quando TUDO estiver passando. São 4 métodos básicos, sabendo lidar com variaveis locais, if e for, vc consegue muita coisa.
Se eu fosse professor eu daria exercícios assim: o projeto deveria compilar e todos os testes deveriam passar senão o aluno leva 0. A nota viria de acordo com o que eu espero, posso usar um EMMA e ver a cobertura de código, posso avaliar a presença de um Javadoc que preste, etc.
Enfim, eu seria um professor muito malvado }-)