Como utilizar AgileUnit - Exemplo simples com comentarios

Porque você num deve deixar de provar e utilizar AgileUnit nos seus projetos? Por causa disso aqui:

Para familiarizar vocês com este extraordinario framework, descidi postar este exemplo aqui apontantdo detalhes para que vocês vejam as vantagens desta innovativa forma agil de testar unidades (classes). Caso o leitor ainda não tenha escutado nada sobre o tema, num faz mal algum. accesse ao seguinte site e veja o guia de beneficios e em seguida faça o download. É gratuito e é um projeto open source situado no source forge. Aqui o endereço: http://sourceforge.net/projects/agileunit/files/ A installação é super simples e é feita em apenas 6 pasos com o arquivo de text chamado quick_start_readme.txt num leva nem 5min. IMPORTANTE: para poder entender este exemplo você devera installar AgileUnit antes de iniciar.

A ideia de AgileUnit é de simplificar tanto o processo de testes como tambem reduzir o tempo com desenvolvimento de padrões de testes como tambem assegurar estabilidade e continuidade dos seus projetos usando agilidade. AgileUnit aproveita toda a sinergia do requirement engineer reduzindo o prazo de desenvolvimento.

OK - agora vamos la ao exemplo: Neste exemplo simularemos alguem que queira desenvolver uma classe que faça a adição de dois numeros. O Cliente descide que para aprovar o resultado, a classe deve comprovar as seguintes funcionalidades (criterios de aprovação fictivos neste exemplo):

  • so aceita adições positivas (ou seja adições que resultem em menos que zero não devem ser somadas)
  • o resultado da adição não deve ser menor que meio milhão (>500.001 )
  • o resultado da adição não deve ser maior que um milhão (<999.999)

Agora vamos desenvolver a classe. (eu trabalho com eclipse como ferramenta de desenvolvimento)
aperte em novo projeto Java e adicione um projeto novo: em eclipse file > new > java project > digite o nome como “exemplo” a aperte finish.
na pasta chamada “scr” adicione um “package” com o nome de "sample"
na pasta chamada “scr/sample” aperte Ctrl + N para abrir a janela dos wizards e procure o wizard chamado: AgileUnit Wizard > Create new Agile Unit Class
digite o nome da sua classe como “PositiveSum” e aperte em “browse” para localizar a pasta “scr/sample” e aperte finish. o wizard vai criar uma nova classe como a que podemos ver abaixo:

[code]public class PositiveSum implements Rule{
private Object input;
private final Map<String, Object> rule;

public PositiveSum(){
	super();
	this.input = new Object();
	this.rule = new HashMap<String, Object>();
	defineRules();
}
@Override public final void defineRules() {
	rule.put( "zero" , new Integer( 0 ) );
	rule.put( "plusOne" , new Integer( 1 ) );
	rule.put( "minusOne" , new Integer( -1 ) );
}
/** method for local speed development tests */
public final static void main( String[] args ) {
	PositiveSum.continuousUnitTest();
}
/** method for continuous integration tests */
public final static void continuousUnitTest() {
	PositiveSum startContinuousTest = new PositiveSum();
	// define your continuous integration tests here...
	// startContinuousTest.yourMethod();
}
@Override public final void regulateInput() {
	// write your regulation code here...
}

}[/code]

OK - como vocês podem ver o wizard me ajuda muito e o unico que tenho que fazer agora é digitar meus requirimentos e aplicar as regras de aprovação solicitadas pelo cliente. NOTE que ate aqui eu num digitei nenhuma linha de codigo java por minha propria conta ganhando um montão de tempo. Vamos paso a paso. Vamos primeiro definir as regras do cliente e logo apos vamos aplicar as regras do cliente (requirement and test first approach)

para definir as regras agileunit oferece a função defineRules() a qual ja vem com valores default para me ajudar. vamos trocar esses valores pelos valores que desejamos:

rule.put( "zero" , new Integer( 0 ) );
rule.put( "RangeOneMillion" , new Integer( 1000000000 ) );
rule.put( "RangeHalfMillion" , new Integer( 500000 ) );

Agora vamos aplicar as regras. para isso nossa classe nescessita de uma propria função a qual sera chamada pelo cliente quando a classe for distribuida. vamos definir uma função com o nome de sum(int a , int b). Nesta função aplicamos nossas regras (test first approach) e veja bem que ate aqui num foi esforço algum, nem tive que inventar nada novo. Estou trabalhando apenas com a ajuda de AgileUnit ate agora. e nesta sessão tambem não sera diferente. Para aplicar as regras AgileUnit oferece um snippet. digite agileU… + tecla espaço e você vera o snippet no seu eclipse. adicione o snippet agileUnit ela dentro da função e você vera o seguinte:

public int sum( int a , int b ) {
		regulateInput();
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.EQUAL ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.NOT_EQUAL ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.TRUE ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.FALSE ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.BIGGER ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.SMALLER ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.EQUAL_OR_BIGGER ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.EQUAL_OR_SMALLER ).as( rule.get( "zero" ) );
}

AgileUnit é agil em muitos setores e ate aqui oferece apoio adicionando todas as possibilidades com valores default que são limitadas a apenas 8, porem lhe permite fazer qualquer tipo de combinação desejada. No nosso caso apenas desejamos 3. Assim que podemos apagar as outras. A unica coisa que temos que ajustar no caso seria os valores das regras que definimos acima. No caso: “zero”, “RangeOneMillion” e “RangeHalfMillion”.

AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.BIGGER ).as( rule.get( "zero" ) );
AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.BIGGER ).as( rule.get( "RangeHalfMillion" ) );
AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.SMALLER ).as( rule.get( "RangeOneMillion" ) );

Pronto! Agora definimos os requirimentos e aplicamos as regras. (requirement and test first approach). Depois disso vamos agora desenvolver a logica da classe. comoça a ficar interessante agora. Para isso AgileUnit tambem oferece uma função chamada: regulateInput(). Aqui vamos definir nossa logica para a função sum(). Para isso definimos 3 variaveis como mostramos abaixo:

public class PositiveSum implements Rule {
	private Object				input;
	private Map<String, Object>	rule;
// nossas variaveis definimos aqui:
	private int				summandOne;
	private int				summandTwo;
	private int				sumResult;

Agora fazemos um pequeno ajuste na nossa função sum() adicionando as novas variaveis e retornando o resultado:

	public int sum( int a , int b ) {
		this.summandOne = a;
		this.summandTwo = b;
		regulateInput();
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.BIGGER ).as( rule.get( "zero" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.BIGGER ).as( rule.get( "RangeHalfMillion" ) );
		AgileUnit.clazz( PositiveSum.class ).method( "sum" ).output( input ).shall( Be.SMALLER ).as( rule.get( "RangeOneMillion" ) );
		return this.sumResult;
	}

So agora definimos a logica da função sum() atraves da função regulateInput() que AgileUnit oferece. Es padrão de teste nos facilita muito tempo de desenvolvimento porque ele sempre se repete e é sempre igual. Nos facilita muito para entender o contexto das classes, porque contem todos os requirimentos e testes. Nos insentiva a programar com o principio de responsabilidade unica (Single Responsability Principle):

	@Override public final void regulateInput() {
// intencionamente apenas vamos codificar o caso que a função não pode adquirir zero
// para mostrar de melhor forma como AgileUnit funciona
		if ((this.summandOne + this.summandTwo) < 0) {
			System.out.println( "Sorry, only positive sum possible!" );
		}
// os outros requirimentos deixarei passar, pra que agente possa ver o que AgileUnit vai nos dizer
// apos efetuar o test.		
		else {
			this.sumResult = (this.summandOne + this.summandTwo);
			// não esqueça de dispor o resultado para agileunit na variavel input
			this.input = this.sumResult;
		}
	}

Agora no nescessitamos simular algumas situações nas quais o cliente ou usuaria digita valores no seu display. Para isso AgileUnit tambem nos ajuda com a função continuousUnitTest(). Nela nos simulamos o usuaria. TIP: todos estes valores tanto aqui como nas regras ou na aplicação das regras em sum() podem ser externalizadas em property-files. Assim nunca temos que recompilar o programa para mudificar nossos testes ganhando muito tempo. surprienda seu chefe! Agora vamos simular um usuaria digitando uns valores:

	public final static void continuousUnitTest() {
// definimos uma instancia da nossa classe aqui
		PositiveSum positiveSum = new PositiveSum();
// simulamos alguns valores -  quantos forem nescessarios
		int a = Integer.valueOf( "1000000" );
		int b = Integer.valueOf( "-600000" );
// chamamos a nossa função sum().
		positiveSum.sum( a , b );
	}

	public final static void main( String[] args ) {
		PositiveSum.continuousUnitTest();
	}

Terminamos! agora so nescecitamos fazer o test. AgileUnit tambem pensou nisso e oferece a classe main() para testes rapidos locais. Com este methodo você pode testar todas suas classes autonômicamente apartir de agora. Vamos testar nossa classe. Para isso aperte em eclipse em: Run > Run As… > Java Applicação e veja o resultado na sua consola:

Genial! Apenas uma linha me indicando o QUE ACONTECEU, ONDE, PORQUE, RAZÃO, VALORES e TIMESTAMP. Nada de Exceptions que para meu codigo ou meu codigo produtivo. Mais isso num é tudo não! AgileUnit ainda oferece um archivo log. Veja no seu user.home onde você colocou or arquivos de properties de AgileUnit. no nosso caso qui neste exemplo eu encontro la uma pasta com o mesmo nome da minha classe. dentro dele encontro um arquivo de texto no qual eu vejo a mesma linha que vejo na minha consola. Ideal para problemas de maintenance. ganhando tempo, agilidade e sastisfação para o cliente.

Bom espero que esse exemplo ajude e caso desejem mais informações entrem em contato comigo. AgileUnit tambem tem um twitter que aconselho acompanhar. se chama: www.twitter.com/@algoritmo4j

comentem por favor as experiências de vocês la no sourceforce http://sourceforge.net/projects/agileunit/files/ ou aqui para ajudar o desenvolvimento ou colaborem se desejam atingir outros niveis, ser inovativos e participar de uma nova era nos testes de unidade.

abraço,
Ricardo

Boa iniciativa.

Movi seu tópico para o fórum de Frameworks Ferramentas e Utilitários.

O primeiro release de AgileUnit oferece separação de tests, ficou mais simples e dispõe agora tambem de mais properties tornando tudo ainda muito mais agil e facil.

Speed video (apenas 2min.) [youtube]http://www.youtube.com/watch?v=BGb2f9XadmI[/youtube]

Sourceforce: http://sourceforge.net/projects/agileunit/files/

novos features: separação de testes, varios snippets, logger e tracer ao mesmo tempo, user’s guide, javaDoc e muito mais.

abraço,
Ricardo