Melhores Práticas com JUnit

Olá Pessoal,

    Recentemente desenvolvi um trabalho bem legal na atual empresa que trabalho relacionado a testes unitários, de um modo geral acredito que assim como aconteceu comigo, o mais natural ainda é ter na empresa diversos softwares que foram construídos na base do “vai ou racha”, ou seja, sem o mínimo de cobertura de testes possível. Dica-se de passagem existe até um sistema que trabalho hoje que possui testes unitários, mas que deixaram de funcionar e hoje servem apenas como empecilho na hora de executar o build do Maven, ou seja, sempre tenho que executar o comando abaixo :

     mvn install -DskipTests

   Claro que isso está completamente errado, acho até que o desenvolvedor inocente e recém graduado tinha uma esperança singela no fundo do coração de que isso iria servir de verdade um dia, o pior é é que gestores despreparados e sem o pingo de noção sobre a importância dos testes unitários acabaram dando mais valor a entrega do que a garantia da qualidade em si, o resultado disso hoje é que os testes unitários mais atrapalham do que ajudam.

    Meu querido amigo e leitor deste humilde blog, gostaria de dizer que ainda existe esperança no fim do túnel, mas exige preparo e paciência. A primeira coisa que devemos ter em mente é que testes unitários podem existir sozinhos, mas que ficam muito mais belos quando estão sendo utilizados pela empresa como uma ferramenta que faz parte da metodologia TDD, Test Driven Development, ou estão sendo utilizados como parte de um ciclo bem estruturado de ALM, Application Lifecycle Management. Sem querer prolongar muito o texto que hoje estou escrevendo, recomendo fortemente aos interessados a leitura do livro abaixo, escrito por Martin Fowler e que é tido por muitos como uma obra neste tipo de assunto.   

   O que de fato gostaria de passar neste post hoje é a importância dos testes unitários e como devemos construí-los, separei então algumas dicas que podem ajudar os desenvolvedores a construir testes uteis e que com certeza terão uma vida longa no build do projeto.

1.  Não realizar o SetUp do teste no construtor

    Jamais realize o set up do caso de teste no construtor, além de dificultar o tratamento de exceção do framework, você não estaria utilizando um método que foi criado especificamente para isso. Ao invés, considere sobrescrever o método  setUp().

Exemplo:

@Override
protected void setUp() throws Exception {
    super.setUp();
    //Realizar o setUp aqui…..
}

2.  Não depender da ordem de execução dos testes

    Evite construir os testes unitários pensando na ordem que eles devem ser executados, pois além de dificultar a inclusão de novos testes, com o tempo e sem o devido cuidado pode acarretar em um teste unitário sem uso prático Outro ponto importante é que a execução dos testes não é garantida pelo JUnit, além do fato de que pode variar bastante dependendo do ambiente e da JVMs que estiver sendo utilizada. Contudo, se a ordem for algo realmente importante para o teste em questão, você deve construir um método estático para forçar a ordem, semelhante ao exemplo abaixo:

Exemplo:

public static Test suite() {
   suite.addTest(new SomeTestCase (“testDoThisFirst”;));
   suite.addTest(new SomeTestCase (“testDoThisSecond”;));
   return suite;
}

3.  Cuidado com os Efeitos Colaterais

    Muito embora a construção de um teste unitário seja um processo autocontido, ou seja, sem depender de nenhum outro método ou recurso externo, é comum a construção de métodos que acabam por modificar uma variável global ou parâmetro de uso geral que tende a quebrar os testes atuais. Dessa forma, cabe sempre que o desenvolvedor estiver construindo um teste unitário realizar uma análise prévia em torno dos testes existentes para entendimento e com intenção de evitar a inclusão de novos componentes que irão afetar os já existentes.

4.   Chamar os métodos SetUp() e TearDown

    Além de ser perfeitamente comum, é recomendável que quando se estiver projetando os testes unitários seja feito uso de herança, a fim de evitar repetição de código fonte e garantir o reaproveitamento de funcionalidades. Não se esquecendo de chamar os métodos setUp() e TearDown() para fazer a configuração inicial e o fechamento de recursos, respectivamente.

5.    Não usar Hard-Coded

    Como dito anteriormente, o teste unitário deve ser autocontido e sem depender de qualquer recurso externo, mas quando isso for impreterivelmente necessário, deve-se evitar hard code, pois isso impede que este teste fique portável em diferentes ambientes. Imagine, por exemplo, o código abaixo que tenta carregar o arquivo data1.dat diretamente da unidade C do sistema operacional, pode-se imaginar que o criador deste código estava utilizando o sistema operacional Windows, mas o que aconteceria se por um acaso o desenvolvedor tentasse rodar este código no Linux, provavelmente não iria rodar! Dito isto, é importante lembrar-se de sempre usar caminhos relativos quando se estiver referenciando algum tipo de recurso, vide exemplos a seguir.

Exemplo de código errado:

    public void setUp ()  {      
     FileInputStream inp = new FileInputStream(“C:\\TestData\\data1.dat”);
}

Exemplo de código correto:

     public void setUp ()  {      
    FileInputStream inp = new FileInputStream(“data1.dat”);
}

6. Nomear os testes unitários cuidadosamente

    Outro ponto importante trata-se dos nomes dos testes unitários, nomeie-os com cautela e bom senso. Lembre-se de que este código pode ser lido no futuro por um programador de outra equipe, ou ainda pelo próprio criador anos mais tarde. Por exemplo, o nome do caso de teste que irá testar a classe MessageLog, deveria ser TestMessageLog, já o nome dos métodos deve sempre representar a real intenção daquele teste, nomes validos são:

    testLoggingEmptyMessage()
    testLoggingNullMessage()
    testLoggingWarningMessage()
    testLoggingErrorMessage()

7.   Não Incluir informação temporal

    Quando estiver construindo um teste unitário, deve-se a qualquer custo evitar colocar informação temporal, fazendo com que o teste unitário dependa de uma data especifica para sua execução ou ainda pare de funcionar por conta disso.

8.    Utilize Locale

    Como dito anteriormente, a execução dos testes unitários pode ocorrer em diferentes ambientes e sistemas operacionais, dessa forma quando se estiver trabalhando com informações que podem variar de região para região, como uma data, deve-se fazer uso de componentes internacionalizáveis. Conforme exemplo abaixo:

Uso incorreto:

Date date = DateFormat.getInstance ().parse (“dd/mm/yyyy”);

Uso correto:

Calendar cal = Calendar.getInstance ();
Cal.set (yyyy, mm-1, dd);
Date date = Calendar.getTime ();

9.   Utilizar JavaDoc

    Deve-se impreterivelmente colocar comentários do tipo JavaDoc logo acima da assinatura do método de teste, com intuito de ajudar nas futuras manutenções do código fonte.  Conforme exemplo abaixo:

/**
 * Teste unitário que verifica as quatro operações básicas
 * da calculadora criada.
 **/
@Test
public void testOperacoesBasicas() {

       // MyClass is tested
       MyCalc tester = new MyCalc();

       // Tests
       assertEquals(“10 x 0 must be 0”, 0, tester.multiply(10, 0));
       assertEquals(“0 x 10 must be 0”, 0, tester.multiply(0, 10));
       assertEquals(“0 x 0 must be 0”, 0, tester.multiply(0, 0));
}

Bem pessoal, espero que tenham gostado dessas pequenas dicas.

Um grande abraço.

Att.
Natanael Fonseca

Compuware DynaTrace

Ola pessoal,
    Na ultima semana de setembro de 2014 participei de um treinamento bem bacana na atual empresa que trabalho, tratava-se de uma ferramenta que seria utilizada para monitoramento de performance das aplicações em produção, e o mais legal de tudo, com suporte as principais plataformas do mercado: .Net, Java, Ruby e outras. Bem, apesar de já ter passado por vários problemas graves em produção com JEE, quase sempre eu recorria as ferramentas mais conhecidas como: JConsole, VisualVM, JProfiler ou ainda o YourKit, o que dica-se de passagem sempre resolvia meus problemas. Achei tao interessante os recursos que ela oferece que resolvi compartilhar um pouco sobre o treinamento.   
Primeiro dia

    O primeiro dia aconteceu de modo semelhante a outros treinamentos técnicos que participei, uma breve introdução e logo após aprendemos o passo a passo necessário para fazer a instalação do produto, um ponto interessante que gostaria de destacar neste primeiro dia é referente a aplicação exemplo que a compuware disponibiliza para fazer os testes, trata-se de uma aplicação web feita com as duas principais plataformas do mercado: .Net e JEE.
      Depois da instalação podemos conhecer um pouco mais sobre o funcionamento do produto, ele possui um conceito interessante, o de sensor !  Enquanto outras aplicações de mesmo fim existentes no mercado utilizam de um agente plugado diretamente na vm e que drena bastante recursos do computador alvo, o dynatrace por outro lado diminui bastante isso devido a sua arquitetura, primeiro que apesar de ter também um agente plugado na vm as informações coletadas são enviadas pela rede para um outro produto, chamado coletor, apos isso os dados são enviados para um servidor central que ira fazer a análise e deixar disponíveis para que a aplicação cliente, a que utilizamos para análise, possa ler e exibir de diversas formas.
Plataformas Suportadas

Arquitetura do Dynatrace
       Logo após uma análise sobre a arquitetura do produto podemos entender também um outro conceito importantíssimo chamado de “pure path”. Imagine ter a visão da requisição do usuário desde o browser até a consulta realizada no banco de dados, eu simplesmente fiquei maravilhado ao saber que isso era possível e que o dynatrace já fazia, conforme pode ser visto na imagem abaixo :

Pure Path
Segundo dia

     O segundo dia foi tão interessante quando o primeiro, neste podemos ver o que na minha visão é a principal função de um profiling, a instrumentacao ! Bem, como era de se esperar o dynatrace não só é fantástico nesse quesito como também deixa seus concorrentes comendo poeira.

    Por meio da visão de pure path, nos podemos chegar até a causa raiz do problema, seja ele um método que está demorando muito, pausas excessivas da garbage collector para fazer o full gc ou ainda um problema de hardware. Dito tudo isto, fica fácil saber o que fazer e ainda pensar numa tratativa em termos de escalabilidade, seja ela horizontal ou vertical.

Visão geral da Aplicação

 

   Visão por localidade do usuário
      Uma outra funcionalidade sensacional do dynatrace, mas que gera uma enorme polemica sobre sua real finalidade é a de relatórios, pois bem, é possível criar diversos dashboards e monitorar a saúde tanto do hardware quando das aplicações que estão sendo analisadas, até ai tudo bem, a polemica começa quando o dynatrace chega no nível de dizer, por exemplo, quantas transações de negocio o usuário fez por um determinado método, isso é uma mão na roda quando queremos ter a visão de negocio relacionada a aplicação, uma especie de BI.

Último dia

      O último dia foi para aplicar os conceitos aprendidos, dai podemos aproveitar a experiencia do instrutor e analisar uma aplicação de alta disponibilidade que possuímos no grupo, já com a visão melhorada sobre o que é a ferramenta e do que ela é capaz, diversos pontos puderam ser vistos e diversas melhorias já foram sugeridas.

Conclusão

     Em síntese,  posso dizer com um pouco da minha experiencia nesse tipo de software, que o dyantrace figura como uma das melhores ferramentas de APM existentes no mercado, altamente recomendável para empresas de grande porte que desejam aumentar a visão em torno dos problemas de performance que por ventura estejam passando.
    Por último, cabe ainda mencionar o fato de que esta ferramenta pode e deve ser utilizada em desenvolvimento, haja vista que existem problemas que podem perfeitamente serem resolvidos a contento, antes que se chegue em produção.
Abrcs
Natanael Fonseca

Você escolhe o caminho a seguir !

Ola pessoal,

        A semana que passou foi marcada por grandes desafios, confesso que teve horas em que pensei em desistir, sei la, quem sabe uma casa na praia ou uma viajem de dois anos pela Europa(SQN). O que fiz foi procurar um local vazio pra pensar, onde eu pudesse lembrar das coisas boas que eu ja fiz na minha carreira e tambem das pessoas em que ajudei. Depois de uma longa reflexão sobre alguns pontos cheguei a uma conclusão simples:   você escolhe o caminho a seguir !
        Não quero ser demagogo ou repetitivo, mas acontece que esses minutos de reflexão  me ajudaram a seguir em frente, pensar em coisas boas não só me fez resolver o problema que eu estava passando, como também me ajudou a ajudar outras pessoas. Não canso de falar, Deus existe !  Apesar de cada vez mais estarmos consumindo informação ou arrumando explicação pra tudo, existem coisas que simplesmente a nossa inteligencia não vai conseguir alcançar, sabe por que ?  porque esta no campo da f’e, da crença e também na experiencia de vida que cada um carrega.
      Para os que estão começando na área de tecnologia e ainda tem a chama da curiosidade e do amor por coisas novas, não deixem isso morrer,  algumas vezes o stress vai ser tao grande tao grande que apenas o amor pelo que você faz sera o combustível pra continuar.
       Aqui em São Paulo é ate comum ver profissionais que perderam esse amor pelo tecnologia e hoje são apenas pessoas que esperam o dia do pagamento. triste né ?
        Em resumo, o que mais simboliza o que quero passar neste post é a mensagem abaixo:

Moving Foward !

Abrcs e bons codigos.
Natanael Fonseca