sexta-feira, 29 de agosto de 2008

Despedida do Antonio

Esta foi a ultima semana do Antonio na globo.com. A despedida foi em grande estilo, com direito a galeria gourmet. Fica o exemplo e a saudade desse grande colega.

Em clima de festa com direito a montinho e tudo:


Fico feliz por ter surpreendido do Antonio nesses poucos meses que trabalhei com ele, agora os desafios são outros (aka Expurgo...)!

Toninho, boa sorte no Yahoo!

segunda-feira, 25 de agosto de 2008

SQL Injection - A fina arte de criar paginas realmente inseguras

Este post diz tudo:


Por mais que existam alertas sobre os perigos de SQL Injection, muita gente resolve ignorar e criar sistemas cujas consultas ao banco de dados são feitas através de concatenações de strings com os dados oriundos do usuário.

Uma das primeiras coisas que aprendi quando trabalhava como testador foi tentar este código em telas de login:

' or '1' ='1


Imagine que o impacto dessa belezinha em uma query como esta:

"SELECT USUARIO FROM TABELA WHERE USUARIO = '" + usuario + "' AND SENHA = '" + senha + "'"

temos, então:

SELECT USUARIO FROM TABELA WHERE USUARIO = 'qqCoisa' AND SENHA = '' or '1' ='1'


Consegui efetuar o login devido a extrema preguiça do desenvolvedor que nunca se interessou em estudar um pouco de segurança, muito menos sabe o que é um prepared statement. Isso no melhor dos casos, posso querer inserir um DROP TABLE da vida facilmente, pois o sistema está, literalmente, de pernas abertas.

Recentemente um colega testou esse tipo de ataque contra um site de uma instituição por curiosidade. Ele conseguiu obter um arquivo contento a senha e o IP do banco de dados e conseguiu acessa-lo, perceberam o perigo?

Sinceramente? Se eu vejo um site que cai nesse truque eu não sinto pena. Não vou zoar ou fazer algo maléfico, as vezes até tento avisar, mas não sei se vale a pena: ou o sistema custou muito barato ou custou muito caro, foi produzido por uma consultoria que lucou 1980% em cima do salario do estágiario e que, por mais documentos que tenham produzido não conseguiram fazer algo básico: um site seguro contra hackers que estudam pela Wikipedia.

Se o seu site não pode receber aspas simples, duplas ou %, tenha MUITO medo, pois alguem VAI fazer algo em breve...

segunda-feira, 11 de agosto de 2008

Closures em Java - Parte 2

Ainda sobre a Closures do java 7, agora será possivel fazer isso:

public class A {
public static void main(String args[]) {
@Shared int acumulador = 0;

{int => int } xxx = { int i => acumulador += i; i};

System.out.println(xxx.invoke(1));
System.out.println(xxx.invoke(2));
System.out.println(xxx.invoke(3));
System.out.println("o valor do acumulador eh " + acumulador );

}
}


Só eu estou achando divertido?

http://gafter.blogspot.com/2008/08/java-closures-prototype-feature.html

sexta-feira, 8 de agosto de 2008

Closures em Java

Olha o que vai ter no java 1.7

public class A {
public static void main(String args[]) {
exec( { int a, int b => a + b });
exec( { int a, int b => a * b });
exec( { int a, int b =>
System.out.println("closure " + a + ":" + b);
(a * a) + (b * b)
});
}
public static void exec({ int, int => int } closure){
System.out.println(closure.invoke(3,2));
}
}


$ java -Xbootclasspath/p:./closures-2008-08-04/lib/closures.jar   A
5
6
closure 3:2
13


Divertido :)

Fonte:
http://guj.com.br/posts/list/99477.java

Parsing de XML na linguagem ABC

A maior parte das linguagens de progração em uso pelo mundo tem pelo menos 1024 bibliotecas para trabalhar com arquivos XML. Me espanta saber que muitos querem "gravar e ler" arquivos nesse formato mas não fazem ideia do que é um XML!

Eis um bom começo:
http://www.w3schools.com/xml/default.asp

Acho que nenhuma linguagem tem mais variações sobre o mesmo tema que Java: http://guj.com.br/artigos.jsp#87031

Testable & Untestable Code

Leitura recomendada:

http://misko.hevery.com/2008/07/24/how-to-write-3v1l-untestable-code/
http://www.testingreflections.com/node/view/7221

quinta-feira, 7 de agosto de 2008

The Good, the Bad and the Ugly

Depois de ter visto algumas vezes "Era uma vez no Oeste" (com Charles Bronson tocando harmônica), finalmente pude conferir o clássico "Três Homens em Conflito" (The Good, the Bad and the Ugly) do mestre Sergio Leone.

Clint Eastwood, Eli Wallach e Lee Van Cleef estão perfeitos nessa história cheia de sangue, traições e a obcessão pela riqueza. As panorâmicas de Leone sobre o desertico velho oeste e a caracterização dos homens embrutecidos daquela época, onde a vida não valia mais do alguns dólares, são majestosas, com direito à mostrar parte da guerra civil americana.



Esqueçam aqueles filmes de indios e tiros falsos: são personagens densos, únicos, em um momento diferente da história, com momentos fantásticos (como a cena em que o "Feio" monta um revolver com as peças de outros). Sem falar no olhar mortal do "Olhos de Anjo" Lee Van Cleef, que passa uma frieza na espinha...

- "When you have to shoot, shoot. Don’t talk!"

Sem falar no maravilhoso tema de Ennio Morriconi, clássico absoluto. O estilo Western não é vazio como muitos pensam, basta saber apreciar.

Voltas às Aulas e o Java - parte 2

Existe o clássico problema de determinar se um aluno passou ou não de ano quando são informados as notas e o número de faltas.

Vejamos:
1) O número de faltas é acima do permitido?. Aqui entra um if dos bons com uma comparação numérica, quando um número é maior ou igual a outro.
2) A média é basicamente somar as X notas e dividir por X (se for média aritmética). Somar e dividir são operações matemáticas básicas.

Uma forma de fazer é:
if( numero_de_faltas > maximo_de_faltas_toleradas) {
// reprovado por faltas
} else if ( media_do_aluno < media_para_passar ){
// reprovado por nota
}
// se nem um nem outro, esta aprovado


O ruim dessa abordagem é que o aluno estar aprovado é uma condição "que sobra". Se passarmos a focar a aprovação do mesmo ficaria assim:

if( media_do_aluno >= media_para_passar && numero_de_faltas <= maximo_de_faltas_toleradas) {
// aprovado!
} else {
// reprovado!
}


É claro que eu posso que eu posso querer saber o motivo pelo qual o aluno foi reprovado:

if( media_do_aluno >= media_para_passar && numero_de_faltas <= maximo_de_faltas_toleradas) {
// aprovado!
} else if(numero_de_faltas > maximo_de_faltas_toleradas){
// reprovado pelo número de faltas: ignoro a média.
} else {
// aqui só sobra a reprovação por nota,
// basta fazer a tabela-verdade dessas expressões
}


Se o foco do professor for o algoritmo, isso é o que deveria ser analisado. Quem implementa corretamente um método que recebe X notas e um número de faltas e consegue responder a essas perguntas consegue descrever facilmente os casos de teste para verificar se a implementação corresponde ao que se espera.

Um programa que tenha algum tipo de interação (seja Swing ou console) ajuda a fazer um macarrão de código, mesclando o algoritmo com o controle de estado dos "menuzinhos". No fim vemos laços de repetição aonde não são necessários, calculo de média errado, etc.

Ok, não acho que um marinheiro de primeira viagem devesse começar por JUnit, mas uma com boa noção dos fundamentos da linguagem e evitando a interação desnecessária com o usuario (poderia ser usado até os parâmetros do main), acredito num melhor desempenho. O risco é o aluno acreditar que java é dificil ou que tudo se resume a getters/setters e gigantescos try/catch's onde as exceptions são varridas pra debaixo do tapete.

Eu colocaria TDD num segundo momento, mas ai sem perdão, ensinando o caboclo a fazer do jeito certo o quanto antes. O que é dificil se eles conseguem passar sem saber fazer aritmética básica.

quarta-feira, 6 de agosto de 2008

Algumas pessoas PRECISAM fazer programas interativos

Este código:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv){
int i;
double total =0;

for(i=1;i < argc;i++){
total = total + atof(argv[i]);
}

printf("A soma dos %d parametros eh %f\n",(argc - 1),total);

return 0;
}


É limpo, prático e scriptável. Não preciso fazer pergunta nenhuma nem tratar nada que o usuario informe: no maximo posso ver o número de parâmetros e reclamar. Basta saber como funciona o laço for e saber que argc é o número de parâmetros que eu passei para o programa e argv é um vetor de strings (que, em C puro, são vetores de chars) onde cada elemento é um parâmetro. O primeiro é sempre o nome do programa (a posição 0, que eu pulei).

$ gcc -Wall soma.c
$ ./a.out 1 2 3 4 5
A soma dos 5 parametros eh 15.000000


Eu compilo e pelo para que todos os warnings possiveis sejam mostrados. Novamente não tive nenhum problema e o código funciona bem. Nem um flush de stdin foi preciso. Se eu colocar uma palavra no meio, como abóbora, será ignorado.

Não é mais facil assim do que fazer milhões de menus? Nem precisa de system("pause") system("cls")!

Test Driven Development - parte 1.

Veja este código:

 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));
}


Dentro de uma classe de teste, usando o framework JUnit, a leitura dessas linhas é a seguinte:

Eu tenho um objeto chamado algortimo.
A chamada algoritmo.ehPar(2) deve retornar true, pois 2 é par, e este método informa se o parâmetro informado é, ou não, par.
O método assertTrue recebe dois parâmetros: uma mensagem informando o significado deste teste, e o resultado do mesmo.

Se o método estivesse com algum problema e retornasse false, isso:

assertTrue("2 deve ser par",algoritmo.ehPar(2));

seria o mesmo que

assertTrue("2 deve ser par",false);

Logo, o teste falha, pois 2 deve ser par.

Esta é uma forma programática de garantir o comportamento do código que eu desenvolvo: testando. Se o meu método só depende dos parâmetros informados, é muito simples verificar o seu funcionamento.

Desenvolvendo os testes antes de implementar o código, tendo apenas as assinaturas dos métodos (por isso recorri a uma interface aqui, lembra?), eu posso pensar nos comportamentos esperados e, então, vou desenvolvendo até que todos os testes estejam passando.

Não é nada fácil, funciona melhor quando o projeto que estás desenvolvendo está começando, porém os resultados são excelentes: veja o quanto de tempo estás economizando! Se tu pretendes determinar se um código teu está funcionando por programas que perguntam os valores, escrever

$ ant clean test


é muito mais rápido!

O problema surge quando queremos fazer algo complexo, pois a dificuldade de testar mostra problemas na arquitetura adotada, por exemplo. Quanto temos objetos que tem objetos, herança, polimorfismo, tecnicas mais avançadas podem ser usadas como usar Mocks de objetos (e prover os mecanismos para injetar estes Mocks).

No caso desse exemplo, esta é uma solução:
public boolean ehPar(int numero){
return numero % 2 == 0;
}


Muitos alunos desconhecem as operações de divisão e módulo entre inteiros. O 1, inteiro, dividido por 2, inteiro, não é 0.5, (em java), e sim 0, pois este é o resultado da divisão inteira. O resto da divisão, simbolizado por %, retorna 1. Dessa forma, o resto da divisão de um numero par por 2 é 0, caso contrario é um número inteiro. São operações básicas que precisam ser dominadas. Repare que eu fiz um código que funcione, não tentei nada mais maquiavélico que dê 0.0001 milissegundos mais rápido. Evite a otimização precoce.

Programar profissionalmente é uma tarefa de muita responsabilidade. Desenvolver testes para garantir a qualidade provê excelentes resultados a longo prazo.

Trocar de Emprego

Completando 6 meses de globo.com, refleti sobre a opção que fiz quando resolvi trocar de emprego. Vi essa semana muitas pessoas com duvidas de como ou quando fazer uma opção parecida, por isso resolvi colaborar.

A primeira coisa que devemos pensar é na nossa carreira. As vezes chegamos ao limite na empresa onde estamos, ou não há perspectivas, ou a situação está ruim, etc. São muitas as coisas que podem acontecer. Com um mercado com falta de mão-de-obra qualificada, muito profissional é assediado por empresas, prometendo as vezes salário maior, ou então surge uma oportunidade fora do estado. O que fazer?

Todas as oportunidades devem ser vistas de forma crítica. Analise o futuro, a distância, o ambiente de trabalho e, também, a remuneração. Eu sempre escolhi o trabalho à remuneração, mas trabalho que paguem abaixo do esperado eu simplesmente não considero. Escolher um emprego vendo apenas o salário engana: imagine ganhar 20% a mais em um emprego mais longe, onde vais perder mais tempo no trajeto, será que compensa? Ou então sair de um ambiente legal para uma confusão absoluta, onde domingo é dia útil de trabalho? Pois é.

Feito isso, temos que pensar em coisas práticas: todas as exigências são atendidas? Tem empresa que só se preocupa com diploma e certificações, mesmo que a sua bagagem supere todas expectativas. Se a empresa é em outra cidade ou estado, temos que analisar o custo de vida, mudança, lugar aonde morar (em grandes centros urbanos é sempre caótico, veja isso com muito cuidado).

O currículo precisa estar atualizado. Ja leu isto aqui? E isso?

Nas entrevistas seja sincero e tenha confiança: tu és um produto, tens que te vender. E, se mentir, babau, vão descobrir mais cedo ou mais tarde... Pra isso, podes estudar bastante algum assunto (eu vim lendo as apostilas da Caelum na viagem de carro que fiz de PoA ao RJ).

Por fim, planeje bem a transição: vale a pena sair com as portas abertas, caso ocorra algum problema. Seguindo estes passos é relativamente fácil optar por trocar, ou não, de emprego.

O importante é se sentir bem aonde estás trabalhando e colaborar para que o ambiente evolua, caso contrario podes ficar fazendo o mesmo trabalho, da mesma forma, por muito tempo: até que um estágiario possa ficar no seu lugar ;-)

Ps: como vai o seu inglês?

segunda-feira, 4 de agosto de 2008

Voltas às Aulas e o Java

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, não se amedronte pelo tamanho do arquivo, o formato xml do ant é bizarro e verboso, sou muito mais um Makefile, porém uma vez com ele feito basta ir adicionando coisas "com cuidado". Sem falar que tudo tem documentação oficial cheia de exemplos, só não aprende quem não quer.

$ 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 }-)

Não perca a parte 2 aqui, e uma introdução ao TDD aqui.