Scaffolding para aplicações baseadas em Spring

Vejam a tradução da notícia que saiu no Infoq Brasil sobre o tema aqui

A nova funcionalidade de geração (scaffolding) do Spring MVC pela ferramenta  Skyway Builder Community Edition (CE) permite os desenvolvedores gerar os modelos de domínio (domain model) e uma aplicação CRUD em Java, baseado no Spring. Classes de Testes JUnit também são automaticamente gerados pela ferramenta. Skyway builder ajuda desenvolvedores Java nas seguintes areas da aplicação web.

Camada de dados:

  • Modelagem de dados
  • Queries Nomeadas (Named Queries)
  • Java Persistence API (JPA) incluindo Hibernate, JPQL and SQL.

Camada Service:

  • Modelagem de Serviços
  • Operação de Queries(Operation Queries)
  • Modelagem de Action
  • Composição de Serviços(Composite Services)

Camada Web:

  • Modelagem de Controllers Web
  • Modelagem de Conversação
  • Modelagem de Action
  • Desenvolvimento AJAX

Além de integração com o Maven.

Práticas de Testes – Parte 1

Alguns dias atrás fiz uma tecnical session na empresa que trabalho, Bluesoft, sobre práticas de testes para projetos java utilizando ferramentas em Ruby. Como existem desenvolvedores Java que não conhecem as ferramentas de teste do Ruby, essa sessão foi apenas para demonstrar o funcionamento básico de ferramentas como Cucumber e Rspec. Posteriormente pretendo apresentar coisas mais avançadas dessas ferramentas.

A apresentação se baseou nos tópicos:

  1. TDD
    • É uma prática de desenvolvimento que envolve escrever o código antes de ser testado. Escrevendo um pequeno teste de um código que ainda não exista. Rodar o teste e, naturalmente, falhar. Agora escreva apenas o suficiente para fazer o teste passar. Quanto estiverem passando, observe o resultado do design e refatore para remover alguma duplicação que você vê.
  2. BDD
    • O problema é testar o que o objeto é, e não o que ele faz. O que ele faz é significamente mas importante. Pense no nível de aplicação, como se você estivesse falando com uma pessoa de negócio. Exemplo:“Um cliente deve realizar um pedido” ou “o pedido deve ser guardado em um banco de dados relacional ANSI-compiant”
  3. Cucumber
    • Uma ferramenta BDD  que lê textos puros que descreve as caracteristicas da aplicação, com exemplos em cenários, e usa os passos desse cenário (step definitions) para automatizar a interação com o código sendo desenvolvido. Os cenários são parseados e tratados como códigos reais, proporcionando benefícios inestimáveis como acompanhar os passos pelos textos, e suporte a múltiplos idiomas.
  4. Rspec
    • Framework Behaviour Driven Development para Ruby. Foco no comportamento. Descreve o comportamento em um nível muito mais granular.
  5. Webrat
    • Teste de aceitação para aplicações Web em Ruby. Um simulador de Browser. 
  6. O que tem a ver?
    • Programadores Java devem estar se perguntando: O que todas essas ferramentas tem a ver comigo?
    • Conhecer várias linguagens nos torna melhores programadores.
    • As ferramentas em ruby podem ser utilizada em projetos Java graças ao JRuby.
    • Existem plugins do Maven para facilitar essa integração. E você pode ajudar a desenvolvê-los. Como esse aqui.
  7. JRuby
  8. Demo. A seguir os passos executados na apresentação:
  • Criar um projeto Maven no Eclipse chamada “biblioteca”
  • No diretório raiz do projeto digitar os comandos:
    • jruby -S rails .
    • jruby -S script/generate cucumber
    • jruby -S script/generate rspec
  • Como será utilizado Rspec, a pasta test pode ser removida
  • Criar o arquivo /features/funcionario_manipula_livros.feature
  • Editar esse arquivo com o conteúdo:


Feature: funcionario manipula os livros
   Como um funcionário
   Eu quero cadastrar um livro
   E quero relacionar livros do mesmo genero
   Scenario: cadastrar um livro
      Given um livro novo
      When eu entro no cadastro
      Then eu deveria cadastrar ele
      And o sistema deveria dizer "Livro cadastrado com sucesso"

  • Executar o comando  abaixo para mostrar os passos pendentes
    • jruby -S cucumber features -n
  • Observe o retorno. O que está em amarelo é um passo pendente para ser implementado:


Feature: funcionario manipula os livros
    Como um funcion#rio
    Eu quero cadastrar um livro
    E quero relacionar livros do mesmo genero
    Scenario: cadastrar um livro
        Given um livro novo
        When eu entro no cadastro
        Then eu deveria cadastrar ele
        And o sistema deveria dizer "Livro cadastrado com sucesso"

1 scenario
4 steps pending (4 with no step definition)

  • Executar comandos git
    • git init
    • git add -A
    • git commit -a -m “Importe inicial do projeto”

Por enquanto só foi preparado o ambiente para a Demo. Em breve colocarei a segunda parte desse post com a implementação do Sistema de Biblioteca usado na apresentação. Os slides apresentados podem ser visualizados aqui: RSpec-Cucumber

Test Driven Development com Javascript usando JsUnit e JSMock

Traduzi recentemente um artigo da Infoq sobre TDD com Javascript. Esse artigo é bem interessante porque ele usa um exemplo simples para demonstrar o TDD descomplicado, fazendo uso de duas bibliotecas chamadas JsUnit e JsMock para a linguagem Javascript. Algumas considerações importantes sobre o artigo:

  • Uma coisa que muita gente ainda confunde, a diferença entre stub e mock.
  • As diferenças e precauções para fazer teste em JavaScript em relação a outros xUnits.
  • Técnicas para fazer teste de códigos não determinísticos como se fosse inteiramente previsível, por exemplo Math.random
  • E por último, TDD!

Leiam o artigo aqui.

TDD é realmente necessário?

Antes de mais nada assistam esse video muito engraçado, que diz Test All the F***in Time! 

 

O TDD é fundamental para um time ágil por alguns motivos que vou citar agora. 
  • O desenvolvimento guiado a testes influencia o time a fazer design simples para desenvolver somente o que é realmente necessário para passar no teste.
  • Influencia o time a ter uma boa cobertura de testes, o que possibilita mudanças no código mais facilmente.
  • A equipe tem mais confiança para fazer refatorações, deixando o código mais simples e limpo.
As ferramentas que temos hoje facilita muito esse tabalho, como por exemplo a família xUnit, Selenium, Mocks, cobertura de testes etc. Porém as ferramentas são para auxiliar e não devem ser impedimento para fazer TDD. Por exemplo, mesmo que alguma linguagem ainda não tenha um suporte tão bom para testes, nada impede que a gente crie nossas próprias assertions. 
Na estimativa tem que ser considerado os testes, para a própria segurança do time. Porém acontece o caso que o cliente pede para deixar os testes para depois. Nesse caso podemos dizer ao cliente que estamos estimando a construção do comportamento do software. Reparem que os testes são parte do comportamento do software!
BDD = TDD + DDD. Behaviour-Driven Development (BDD) é o desenvolvimento de software dirigido ao seu comportamento. É a união de desenvolvimento guiado por testes(TDD) e Design dirigido ao domínio da aplicação (DDD). 

Testar é investir! Ou seja, se as pessoas não conhecem a sintaxe de xUnit, nunca usaram Selenium ou se deparam com a necessidade de criar mocks para eliminar a dependência de outras classes que não são interessantes para o teste de unidade, eles terão que considerar esse tempo de aprendizagem dentro do sprint. Porém depois de familiarizado com a ferramenta/framework, os testes podem ser executados sem mesmo precisar subir um servidor de aplicação, aumentando assim a produtividade da equipe. 

No livro do Vinícius Teles tem uma metáfora muito interessante com a saúde das pessoas. O que é melhor: prevenir ou remediar?

É interessante lembrar que os Testes estão muito ligados a outra prática ágil como a Integração Contínua.

Sei que todos concordam que os testes são imprescindíveis. Portanto o cerne da discussão desse tópico é fazer os testes antes ou não. Porém acredito que fazer teste antes traga mais valor ao cliente.

Conclusão, só não testa quem realmente não quer. 😉

Eu escrevi alguns posts sobre esse assunto, quem quiser pode dar uma lida e fiquem a vontade em comentar aqui e aqui

Quando Usar Objetos Mocks?

Precisei fazer alguns objetos mocks no trabalho e achei um artigo interessante sobre uso de frameworks de Objetos Mock. Segue o artigo do K Scott Allen:

 

Mocks – Esta é uma Questão de Quando.

Ross Neilson lembrou-me uma pergunta que me deixou enforcado: “Quando eu uso um Mock Framework?”

 

Se você perguntar “quando”, a resposta é provavelmente “não agora”. Eu sinto que framework de objetos de mentira (Mock Objects) é algo que você tem que evoluir.

Primeiro, nós podemos falar sobre Mocks em geral. Algumas pessoas tem a concepção que Objetos Mock são apenas útil se você precisa simular uma iteração com um recurso que é difícil usar em testes de unidade – como um objeto que comunica com um servidor SMTP. Isso não é verdade. Colin Mackay tem um artigo sobre mocks que demonstra outros cenários comuns.

 

  • O objeto real tem comportamento não determinístico
  • O objeto real é difícil de configurar
  • O objeto real tem comportamento que é difícil de acionar
  • O objeto real é lento
  • O objeto real é uma interface de usuário
  • O objeto real usa uma chamada de retorno (call back)
  • O objeto real ainda não existe

 

Se dermos um passo para trás e generalizarmos essa lista, diríamos que test doubles são úteis quando você quer isolar um código do seu teste. Digamos que estamos escrevendo testes para um componente de negócio. Nós não gostaríamos que o teste falhe quando alguém introduzir um código ruim de um serviço de auditoria usado pelo componente de negócio. Nós somente queremos testar a falha quando alguma coisa está errada com o próprio componente de negócio. Fornecer um mock para o serviço de auditoria nos permite isolar o componente de negócio e controlar qualquer estímulo que o componente pode receber desse serviço de auditoria. Quando você começar a sentir a dor de escrever vários test doubles na mão, você vai saber que necessita de um framework de Objetos Mock.

 

Mocks não são somente sobre isolamento, no entanto. Mocks tem também um papel no desenvolvimento orientado a testes (TDD), o qual se refere Colin no último ítem. O autor de Mock Roles, Not Objects” diz que mocks são:

“Uma tecnica para identificar tipos baseado em papéis que o objeto desempenha em um sistema… Em particular, nós agora sabemos que o maior benefício de Objetos Mock é aquilo que originalmente chamamos de descoberta de interfaces”

 

Usar um framework de Objetos Mock no TDD permite um contínuo, top-down desing de software. Muitos fãs de TDD sabem que necessitam de um framework de Objetos Mock um dia.

 

Mas frameworks de Objetos Mocks não são complexos?

 

 Essa é outra questão que eu fui questionado recentemente. Frameworks de Objetos Mocks são atualmente mais simples e expõem uma pequena API. Existe complexidade, porém, não no framework em si. Como eu disse anteriormente, eu penso que existe um caminho que você segue para evoluir no uso de frameworks de Objetos Mock. Um típico time de um projeto usando framework de Objetos Mock tem vivência com TDD e Containers de Inversão de Controle. Tentar ter velocidade com todos esses tópicos de uma vez pode ser esmagador. 

 

Existe também alguma complexidade no uso de mocks efetivamente. Em Mocks and the Dangers of Overspecified Software, Ian Cooper diz:

 

“Quando você muda a implementação de um método através de um teste, mocks podem quebrar porque você pode fazer chamadas adicionais ou diferentes para o componente dependente que está sendo mocado.  …  O mock começou a fazer nosso software mais resistente a mudança, mais lento, e isso aumentou o custo para refactoring. Como a mudança se tornou mais caro, nós ficávamos resistentes a fazer isso, e corremos o risco de começar a construir débitos técnicos (technical debt). As vezes um teste quebra, quando desenvolvedores mudam o domínio, ou mudou o modo de como fomos fazer a persistência, sem alterar o teste em primeiro lugar, porque eles ficaram frustados de como isso deixou mais lento o seu desenvolvimento. Os mocks se tornaram um impedimento ao progresso.”

 

Framworks de Objetos Mocks fazem fáceis interações baseada em testes, mas podem também levar a problemas que o Ian Cooper descreve acima. Aqui está mais algumas leituras para esse tópico:

 

Guidelines to Using Interaction Based Testing

Why Mock Frameworks Suck

 

Em resumo, frameworks de Objetos Mocks (por exemplo JMock, EasyMock, and NUnit) não são para tudo, Você deverá saber quando  necessitar de um.

Comportamento de Software

 Behaviour-Driven Development (BDD) é o desenvolvimento de software dirigido ao seu comportamento. É a união de desenvolvimento guiado por testes (TDD) e Design dirigido ao domínio da aplicação (DDD).

Para entender direito o que é BDD é necessário comentar sobre TDD e DDD. Nesse post quero focar no TDD. Um assunto tão importante como esse merece muita atenção!

Quando acontece um bug num software é bastante comum os desenvolvedores gastarem mais tempo tentando achar o erro do que consertar o erro em si, principalmente se o sistema não tiver testes automatizados.

O TDD é uma prática usada por times que seguem Extreme Programming. Desenvolvedores que não usam essa prática se encaixam em um dos itens abaixo:

  • Tem preguiça de fazer testes
  • Faz os testes no final
  • Não conhecem os benefícios de o TDD trás.
Existem desenvolvedores que confiam tanto no seu trabalho que deixam para outros testarem o que desenvolveu. Porém um bug pode não ser pego no teste de outros e ocorrer quando estiver em produção.
Os que deixam os testes para o final podem não lembrar de testar todos os cenários. E se ocorrer atrasos no projeto o primeiro que vai ser cortado são os testes.
Para quem não conhece os benefícios do TDD fale a pena comentar um pouco do assunto.

Iniciar essa prática pode parecer um pouco difícil e chato, mas para a equipe de XP isso se torna muito natural. Todo código implementado deve coexistir com um teste automatizado, para garantir o funcionamento do software com a entrada de novas funcionalidades. Esses testes automatizados garantem a qualidade do software pois, se uma nova codificação afetar alguma regra de negócio, o teste deve instantaneamente apontar o problema antes que o release seja entregue. Quando essa automatização existe, os desenvolvedores ficam com mais coragem de alterar uma parte do código que ele não desenvolveu e eles tem mais confiança de fazer refatorações necessárias para melhorar o código. A Refatoração é muito importante seja para facilitar a manutenção do sistema ou para melhorar a performance do código, mas que seja feira sem alterar a funcionalidade do software. Geralmente a gente refatora quanto encontramos códigos duplicados, pouco legíveis, mal codificados, sem padronizações, lentos etc.

Primeiro implemente o que (comportamento) você quer testar, e execute testes de sucesso que garantam falhas do sistema e testes de sucesso que garantam o bom funcionamento. Depois disso você implementa a funcionalidade em questão.

Uma boa prática de trabalhar com TDD é fazer o que o pessoal de XP chama de seguir “passos de bebê”. O benefício disso é que quando você faz um teste para um software que tem poucas linhas é bem mais difícil de você ter inserido um bug. E a medida que a funcionalidade vai crescendo os testes automatizados tem que continuar executando, tanto os de falha quanto os de sucesso.

Fazer TDD não é apenas testar a aplicação e sim fazer um design simples. Muitos problemas de acoplamento das suas classes serão percebidos quando escrever um teste. TDD é muito relacionado com refactoring, tornando o código fácil de ler. O fato das pessoas não saberem o que testar e como testar torna uma barreira para fazer os testes, mas depois de se conhecer os benefícios e começar a praticar, o desenvolvimento guiado por testes tente a ser uma maneira natural de pensamento. 

“Nos dias de hoje, é irresponsabilidade um desenvolvedor entregar qualquer linha de código sem que exista um teste unitário para comprovar o seu funcionamento” frase de Bob Martin

Existem basicamente dois tipos de testes, os testes de unidade e os testes de aceitação (integração). Os testes de unidade seriam para testar os métodos de uma classe. Já os de integração tem como objetivo validar a integração das classes que implementam uma funcionalidade, atendendo as necessidades de maneira correta. Os testes de integração, na maioria dos casos, são descritos pelos clientes, mas quem implementa são os desenvolvedores.

Para fazer testes automatizados temos muitas ferramentas disponíveis, basta usá-las.

Testes unitários, em Java, temos JUnit, UnitNG, JMock. Para testes de integração temos o Selenium, Fit, Fitnesse. Ferramentas de BDD JBehaveJDavebeanSpecInstinct.

Em Ruby on Rails temos autotest para automatização dos testes. Para BDD tem ótimas ferramentas como RSpec Shoulda.

Em Javascript, para o JQuery, temos o JQunit. Para BDD tem o JSSpec.

Para Integração Contínua tem o CruiseControl.

Para verificar a cobertura de testes temos o EmmaCloverJCover.

Precisei fazer uma refatoração num sistema que não tinha testes unitários e as classes eram bastante acopladas. Mas isso não foi problema para eu criar os testes. Usei o JMock e criei objetos de mentira para simular outras classes que não era minha intenção testar. O JMock pode ser usado para simular uma classe que faz acesso a banco, HTTPRequest ou qualquer outra classe do seu sistema. Um exemplo de uso nesse post.

Um excelente exemplo de TDD pode ser lido nesse post da Improve It.

Uma das ferramentas que mais gostei foi o Selenium. O Selenium-IDE funciona como um robozinho que grava as ações em uma tela. Por exemplo o click em um botão deve trazer uma lista de resultados. Se ao disparar o teste do botão a listagem não aparecer, o Selenium-IDE avisa que tem erro no sistema. A ferramenta pode disparar o mesmo teste em vários browsers diferentes.

Quando pensamos em qualidade no software devemos lembrar das ferramentas ideais para nos auxiliar em nosso ambiente. Pensar nos testes como sendo automatizados, pois são mais eficientes que qualquer teste de usuário, o qual também é importante.