Blog do Urubatan
msgbartop
Desenvolvedor, Palestrante, Escritor, Nerd Assumido e Pai do Marcus :D
msgbarbottom

17 Feb 10 Agile Brazil 2010 – A chamada para trabalhos está aberta!

Estou de férias, e eu não ia escrever nada aqui no blog antes de voltar ao trabalho, mas isto merece o post :D
A chamada de trabalhos para o Agile Brazil 2010 esta aberta.
Se você tem algo interessante sobre Agile para falar, envie sua proposta de palestra, tutorial ou workshop por este link.

A Agile Brazil 2010 é um evento nacional organizado por representantes das principais comunidades ágeis brasileiras. Junte-se a nós submetendo trabalhos, participando do concurso do logo e divulgando o evento.

Acompanhe as novidades do @agilebrazil pelo Twitter.

O evento vai acontecer em Porto Alegre de 22 a 25 de Junho 2010.

Espero ver alguns de vocês por lá!

Tags: , , , , , , , ,

06 Jan 10 Cucumber e BDD – Vantagens para a empresa (Argumentos para o gerente, para o arquiteto, para o presidente da empresa, …)

Desenvolvimento Guiado pelo Comportamento (BDD – Behaviour Driven Development)

Desenvolvimento guiado pelo comportamento da aplicação é o que todos deveriam fazer sempre, de forma bastante resumida é definir com o cliente como a aplicação deve se comportar, escrever um teste automatizado para verificar este comportamento e depois escrever código suficiente para fazer o comportamento da aplicação ficar de acordo com o que o cliente deseja.

A diferença básica do Behaviour Driven Development (de agora em diante simplesmente BDD) para o desenvolvimento orientado por testes, é que o BDD coloca em foco o valor para o negócio que o software vai adicionar. Parece ser uma diferença puramente conceitual mas não é, por exemplo:
A tela inicial deve listar todos os clientes
Não é a mesma coisa que
O método HomeController.index precisa popular a variável @clientes

  1. O primeiro é inteligivel para um leigo, o segundo é especifico para um sistema e apenas um programador entende
  2. O primeiro é um exemplo de uma definição de comportamento de uma tela, uma coisa que um cliente poderia dizer.
  3. O segundo é um exemplo de como um programador poderia ler uma linha de código fonte.

Claro que não são só estas diferenças, trabalhando mais com BDD percebe-se que ele poupa muito mais trabalho do que o TDD simples (Não que TDD seja simples de se adotar). BDD tem todas as vantagens de TDD e mais algumas, veja as duas listas abaixo:

Test Driven Development:

  1. O código gerado tem menor acomplamento e maior coesão.
  2. O código gerado tem uma maior qualidade por ser quase 100% testado.
  3. Refatoramentos podem ser feitos sem medo pois qualquer problema sera detectado pelos testes.
  4. É possível saber claramente quando uma tarefa foi concluida, pois o teste correspondente esta passando.
  5. Testes de regressão automatizados existem sem nenhum esforço adicional.
  6. A maior parte dos bugs é encontrada mais cedo o que torna mais barato corrigi-los.

Behavior Driven Development:

  1. Todos os anteriores
  2. Aumenta a integração entre o cliente, os testadores e os desenvolvedores pois todos falam a mesma lingua.
  3. Mesmo quando testadores e desenvolvedores são equipes diferentes eles podem trabalhar juntos para definir o design do que vai ser feito, escrever User Stories é uma ótima forma de fazer isto, pode ser feito com a ajuda do usuário ou pelo menos validada com o usuário que vai entender o que esta escrito.
  4. User Stories servem como Test Case, Código do teste automatizado, e Design tudo junto.
  5. As User Stories se tornam testes executáveis, o que quer dizer que o usuário pode escrever o código dos testes de aceitação (OK, isto é bem pouco provável, mas ele pode pelo menos ler)

Ou seja, alem de gerar um código com mais qualidade, o BDD poupa trabalho de toda a equipe e o principal, melhora a comunicação, que tanto para quem trabalha com metodologias ágeis quanto para quem não trabalha é extremamente importante e a falta dela é um problema gravíssimo que leva diversos projetos ao fracasso. Na minha opinião, só o fato de melhorar a comunicação já é motivo o suficiente para testar BDD.

Claro que alguns dos benefícios que eu citei dependem do suporte de ferramentas, para ser mais preciso, as User Stories serem o código executável dos testes de aceitação depende de uma ferramenta para ser verdade, e a ferramenta que eu escolhi para isto é o Cucumber, do qual eu vou começar a falar com mais freqüência aqui no blog.

Eu pessoalmente encaro o BDD como uma evolução do TDD, eu sempre tive dificuldades em escrever testes unitários antes do código da aplicação, claro que para bibliotecas é fácil, mas para a interface com o usuário que consome boa parte do código da aplicação é bem complicado escrever testes estilo XUnit, mas quando as user stories se tornaram o código executável dos testes de aceitação da UI (pelo menos os básicos desconsiderando o layout) um novo mundo se abriu para mim e tudo passou a fazer sentido.

Cucumber – Quem disse que pepinos seriam um problema?

para quem não percebeu este sub-titulo é uma brincadeira com a tradução da palavra cucumber que quer dizer pepino

Cucumber é uma ferramenta que torna possível executar histórias em texto puro, ele é uma ferramenta escrita em Ruby que veio para substituir o RSpec Story Runner, e tem diversas vantagens sobre este.

O Cucumber, utiliza Ruby e expressões regulares para definir o que qualquer expressão quer dizer, mas antes de entrar nestes pormenores vamos entender um pouquinho da estrutura básica que o Cucumber define para as User Stories.

Para que seja possível executar uma User Storie utilizando o Cucumber, ela precisa ter uma estrutura básica.

  1. Para o cucumber, todas as User Stories referentes a uma funcionalidade do sistema estarão agrupadas em um arquivo com a extensão .feature
  2. No início de cada arquivo existe um resumo da funcionalidade com um formato bem simples: um título, qual o problema a ser resolvido, qual ator trabalha nesta história e qual o resultado desejado.
  3. Logo depois são definidos os cenários, que são as histórias em si, cada arquivo tem pelo menos um cenário.
  4. Cada história, ou cenário é composto por uma descrição ou título, uma ou mais pré condições, uma ou mais ações e uma ou mais verificações.

Esta é uma forma de definir a estrutura básica de um arquivo .feature do Cucumber, claro que explicando desta forma estas definições se encaixam em muita coisa, então vamos ser um pouco mais especificos.

O Cucumber define algumas palavras chave para cada uma destas sessões, estas palavras chave podem ser traduzidas para diversas linguas, o primeiro exemplo eu vou colocar em ingês, depois vou mostrar o equivalente em portugues, mais adiante quando entrarmos na parte de configurações do cucumber vamos ver melhor como selecionar a lingua utilizada, e como customizar isto, mas por enquanto fiquemos com as configurações padrão.

	Feature: Simple math
		In order to avoid silly mistakes
		As a math idiot
		I want to be told the result of simple math operations

		Scenario: adition
			Given I have entered 50 into the calculator
			And I have entered 70 into the calculator
			When I press add
			Then I should see 120 on the screen

		Scenario: subtraction
			Given I have entered 60 into the calculator
			And I have entered 30 into the calculator
			When I press sub
			Then I should see 30 on the screen

Este é o exemplo de uma história bem simples que o cucumber pode interpretar, as palavras chave apresentadas são:

  • Feature
  • Scenario
  • Given
  • And
  • When
  • Then

Estas mesmas palavras podem ser traduzidas para o portugues como:

  • Funcionalidade
  • Cenário
  • Dado
  • E
  • Quando
  • Então

Utilizando estas palavras chave, seria possível escrever esta história assim em portugues:

	Funcionalidade: Matemática Simples
		Para evitar erros idiotas
		Como um completo ignorante em matemática
		Eu quero que operações simples de matemática sejam resolvidas para mim

		Cenário: adição
			Dado que eu digite 50 na calculadora
			E que eu digite 70 na calculadora
			Quando eu precionar "Adicione"
			Então eu devo ver 120 na tela

		Cenário: subtração
			Dado que eu digite 60 na calculadora
			E que eu digite 30 na calculadora
			Quando eu precionar "Subtraia"
			Então eu devo ver 30 na tela

O legal é que esta histórinha poderia ser escrita por um usuário, as únicas regras reais são:

  1. Começar as frases com as palavras chave definidas
  2. Tentar utilizar as mesmas frases sempre que possível, isto vai facilitar na tradução do dialeto utilizado para Ruby

A estrutura que utilizei na descrição da funcionalidade não esta descrita em palavras chave por que ela não é interpretada pelo cucumber, é apenas uma descrição e o formato pode variar um pouco.

Mas por que utilizar esta ferramenta para testes em vez de qualquer outra?
Por que utilizar o cucumber como ferramenta de testes vai viabilizar uma abordagem BDD no desenvolvimento do seu sistema, e que isto vai te poupar muito dinheiro.

Seguem agora alguns argumentos (fora os que você pode retirar do texto)

  • Presidente da empresa
    • Esta metodologia de desenvolvimento em conjunto com as ferramentas corretas vão poupar bastante dinheiro no desenvolvimento de sistemas
  • Gerente
    • A integração entre as equipes de desenvolvimento e os clientes vai melhorar muito, isto vai fazer com que os clientes fiquem mais felizes com as entregas, possam acompanhar o progresso do desenvolvimento e entendam se o que esta sendo testado é o que realmente importa para eles melhorando a qualidade do que é entregue
  • Arquiteto
    • Esta metodologia vai melhorar o entendimento da equipe sobre o que deve ser desenvolvido
  • Desenvolvedores e Testadores
    • É legal trabalhar desta forma, e você vai trabalhar menos no final das contas o que é bom e ermite que você exercite a sua preguiça :D

Acho que era isto, falei um pouco de BDD, um monte de Cucumber e acho que consegui mostrar a idéia geral, mas isto vai ficar um pouco mais claro nos próximos posts sobre o Cucumber.
PS.: parabéns pela paciência se você leu até aqui :D

Tags: , , ,

26 Mar 09 Porto Alegre Agile Weekend 2009

guma-rs

Este post tem dois motivos.
O primeiro é para fazer um pouquinho de propaganda do Porto Alegre Agile Weekend 2009, evento realizado pelo GUMA-RS.

O ano de 2009 é especial para o Grupo de Usuários de Métodos Ágeis do RS
(GUMA) pois é nele que completamos nossos primeiros 5 anos de vida vinculados
à Sociedade dos Usuários de Informática e Telecomunicações do RS (SUCESU-RS). Para comemorarmos esta data, tão especial para nossa comunidade de agilistas,
preparamos um evento especial em parceria com o Software Process Improvement Network de Porto Alegre (SPIN-POA) que reúne colegas e convidados em dois dias de palestras, mini-tutoriais e debates: o Porto Alegre Agile Weekend 2009!

E o segundo motivo é para avisar que vou fazer um mini tutorial no evento, o título vai ser: Implementando com Rails as Histórias de Usuários
A idéia básica do tutorial é chegar com uma “User Story” em texto, passar ela pro Cucumber, escrever alguns testes e depois implementar o sistema para fazer os testes passarem. E depois disto tudo, utilizar a própria “User Story” transcrita para o Cucumber como aceptance test.
Basicamente um exemplo de BDD com Rails.
E aproveitando a palestra no evento, vou sortear duas copias do livro “Ruby On Rails : Desenvolvimento fácil e rápido de aplicações web“. Uma no final da minha palestra e uma no final do evento (se tiver bastante gente na minha palestra de repente sorteio 3 copias em vez de duas).

É issai galera, espero vocês no Agileweekend.

Tags: , , ,

03 Jul 08 RSpec Stories – Ruby gerado a partir do texto!

Não, eu não quero que vocês gerem o código dos testes, isto iria apenas criar testes inúteis!
Mas eu acho muito chato ter certeza de que todos os possíveis passos de um arquivo txt com a user story estão presentes nos passos definidos no arquivo .rb
Claro que isto não esta considerando reutilização de passos através de Mixins ou outras técnicas semelhantes, mas este script me ajudou bastante ja, então resolvi compartilhar ele para quem estiver interessado :D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
name=ARGV[0]
all = []
last = ""
f = File.new(name)
f.each_line do |l|
  l.strip!
  l,command,params = *(/^(When|Then|Given|And) (.*)/.match l)
  if l
    command = last if command == "And"
    last = command
    params = params.gsub /"/, '\"'
    all << "#{last} \"#{params}\" do\n    pending\n  end"
  end
end
all.uniq!.sort!
sym_name = name[File.dirname(name).length+1..-5]
puts %Q{require 'stories/helper'
steps_for(:#{sym_name}) do
}
all.each { |l| puts "  #{l}"}
puts %Q{end 
 
with_steps_for :#{sym_name} do
  run "\#{dir = File.dirname(__FILE__)}/#{sym_name}.txt"
end
}

eu salvei este código em um arquivo txt_to_steps.rb, e para utilizar basta executar:
ruby txt_to_steps.rb

Um exemplo de user story (utilizando o formato do RSpec) seria este texto:

Story: new user
  As a company employee
  I want to register in the CRM
  So that I can see and manage company contacts

Scenario: user with no access to the system
  Given the username user1
  And the password mypassword
  When the login form is submited
  Then the login form should be shown again

Scenario: user registration
  Given the username user1
  And the password mypassword
  And the email user1@company.com
  When the registration form is submited
  And there is no other user with the same e-mail or email
  Then the registration should be OK
  And the user should be redirected to /

Scenario: repeated user registration
  Given the username user1
  And the password mypassword
  And the email user1@company.com
  When the registration form is submited
  And there is already another user with the same name or email
  Then the registration should fail
  And the registration form should apear again

Scenario: existing user login
  Given the username user1
  And the password mypassword
  When the login form is submited
  Then the user should be redirected to /


O txt_to_steps pode ser melhorado para tentar identificar alguns padrões, mas como esta agora ja me poupou bastante trabalho :D
Sei que não é o código ruby mais limpo que vocês ja leram, mas para algo escrito em 5 minutos até que ficou legal :D

Se ajudar mais alguem, a única exigência é deixar um comentário aqui dizendo o que poderia ser melhorado no script :D

PS.: sei que o blog anda meio parado demais, mas é por um bom motivo, acho que daqui a um mes aproximadamente volta tudo ao normal e eu posso contar aqui o motivo deste tempo quase sem posts :D

Tags: , , , ,

28 Apr 08 Plugins para rails e grails

Publiquei eles só no meu blog em ingles, mas acho que vale o link aqui pelo menos …

Para quem é tão preguiçoso quanto eu, eu criei um plugin para o rails que reutiliza tudo (ou quase) o que você ja definiu na migration para gerar o model, o nome do plugin é mydry.

E para quem trabalha com Grails, e estava triste até agora por não poder utilizar BDD de forma fácil, eu criei o plugin easyb-test que permite utilizar o easyb para escrever testes para a sua aplicação Grails.

Se quiserem um exemplo de como usar este plugin do easyb, é só olhar o material da minha palestra do FISL deste ano.

Tags: , , , , , , ,

24 Mar 08 Pare de perder tempo escrevendo documentação do código que você escreveu (parte 1)

time_graphic.jpg

Não, eu não estou completamente louco, e não acho que documentação para o código escrito seja uma coisa completamente inútil.
Mas eu acredito que documentação desatualizada é pior do que nenhuma documentação …
E não estou incentivando a escrita de código completamente sem documentação …
E por último, só para constar, eu estou falando de documentação da regra de negócio implementada e não o manual do usuário …

Ok, mas como deixar de perder tempo escrevendo a tal da documentação?
A solução que me vem a cabeça é BDD, ou seja, Behavior Driven Development, junto com a tão falada, documentação executável …

Mas isto existe?
Sim existe, e o pessoal doRuby On Rails já esta bastante acostumado com isto, utilizando o RSpec.
Mas este post não é sobre Ruby On Rails e nem sobre RSpec, e sim sobre o Easyb, que é uma biblioteca para escrita de “Documentação Executável” utilizando Groovy, muito fácil de utilizar para testar código Java …

Para começar com a brincadeira, vou ir ao site do projeto e fazer o download do último release (atualmente 0.7)
criar um projeto java novo no eclipse.
criar uma pasta de nome lib e copiar os seguintes jars para a pasta:commons-cli-1.1.jar easyb-0.7.3.jar groovy-all-1.5.0.jar (todos vem no zip do easyb)
criar mais uma source folder de nome behavior
(O meu eclipse esta com o plugin para edição de código groovy instalado)

Crio um build.xml para executar os testes (ainda não existe um plugin para o eclipse, mas sinceramente, não achei necessário)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="run_tests">
	<path id="all.path">
		<pathelement location="${basedir}/bin" />
		<pathelement location="${basedir}/bin-groovy" />
		<fileset dir="${basedir}/lib" includes="**/*.jar" />
	</path>
	<taskdef name="easyb" classname="org.disco.easyb.ant.BehaviorRunnerTask" classpathref="all.path" />
	<!-- ================================= 
          target: default              
         ================================= -->
	<target name="run_tests" description="--> description">
		<easyb failureProperty="easyb.failed">
			<classpath>
				<path refid="all.path" />
			</classpath>
			<behaviors dir="${basedir}/behavior">
				<include name="**/*Story.groovy" />
				<include name="**/*Specification.groovy" />
			</behaviors>
			<report location="story.txt" format="txtstory" />
			<report location="behavior.txt" format="txtbehavior" />
			<report location="easyb.xml" format="xmleasyb" />
		</easyb>
	</target>
</project>

Este build.xml declara a tag do easyb e executa todos os testes, alem de gerar os relatórios, que vocês vão gostar bastante …
Os tipos de relatórios variam bastante de acordo com a versão do easyb, a equipe de desenvolvimento esta melhorando bastante isto, eu estou utilizando aqui a versão do trunk do subversion, se quiserem baixar a mesma versão que uso aqui, podem baixar via git deste repositório : git clone git://github.com/urubatan/easyb.git
(Eu fiz um fork do projeto para adicioar algumas features, e ja estou enviando os patches para os desenvolvedores)

Agora vamos começar a brincadeira :D
Dentro do diretório behavior vou criar um diretório de nome users e um arquivo de nome PermitirRegistroDeUsuariosStory.groovy dentro deste último.
Ou seja, este arquivo vai conter os testes, e a documentação das regras de negócio sobre a criação de novos usuários no sistema …

Quero ter uma breve descrição da história nos meus relatórios, então adiciono uma tag description no inicio do arquivo (esta tag por enquanto só existe no meu fork).

1
2
3
description """Qualquer novo visitante do site deve poder se registrar no sistema, 
desde que as regras de validação definidas sejam atendidas.
Um usuário registrado podera alterar a sua senha sempre que desejar, mas a senha devera atender aos padrões minimos de segurança"""

As histórias são compostas basicamente de 4 comandos:
scenario – define um cenário da história, ou seja, um bloco contendo os outros 3 comandos
given – define a situação inicial
when – define um gatilho, uma ação do usuário que ira disparar alguma ação do sistema, este comando é opcional
then – define o que o sistema deve fazer, e o que vai ser testado

alem destes existe o “and” que atualmente é um comando que não executa nada, serve apenas para deixar o código mais legivel, mas isto vai mudar na próxima versão, o and vai repetir o comando anterior, semelhante ao que acontece no RSpec.

Conhecendo estes comandos podemos começar a escrever a nossa documentação :D
Vou adicionar alguns cenários a minha história e alguns detalhes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
scenario "Um novo usuário precisa confirmar a senha", {
	given "Um novo usuário", {
	}
	when "O usuário preenche o nome de usuário e a senha, mas sem confirmar a mesma", {
	}
	then "A validação do usuário deve falhar", {
	}
	when "O usuário preenche o nome de usuário e confirma a senha corretamente", {
	}
	then "A validação do usuário deve passar",{
	}
}
scenario "Um nome de usuário deve ser único no sistema", {
	given "Um usuário com o formulário preenchido corretamente", {
	}
	then "O registro deve criar o usuário no sistema", {
	}
	when "O nome de usuário ja existe no sistema", {
	}
	then "O registro do usuário deve falhar",{
	}
}
}

Com isto, podemos ver no diretório do projeto os seguintes arquivos criados:
behavior.txt que até o momento esta em branco

story.txt que contem o seguinte texto:

  Story: permitir registro de usuarios
    Qualquer novo visitante do site deve poder se registrar no sistema,
desde que as regras de validação definidas sejam atendidas.
Um usuário registrado podera alterar a sua senha sempre que desejar, mas a senha devera atender aos padrões minimos de segurança

    scenario Um novo usuário precisa confirmar a senha
      given Um novo usuário
      when O usuário preenche o nome de usuário e a senha, mas sem confirmar a mesma
      then A validação do usuário deve falhar
      when O usuário preenche o nome de usuário e confirma a senha corretamente
      then A validação do usuário deve passar

    scenario Um nome de usuário deve ser único no sistema
      given Um usuário com o formulário preenchido corretamente
      then O registro deve criar o usuário no sistema
      when O nome de usuário ja existe no sistema
      then O registro do usuário deve falhar

e easyb.xml que contem uma versão XML dos dois relatórios combinados …
Se você prestar atenção no story.txt, substituindo as palavras em ingles que fazem parte da DSL do easyb, por palavras em portugues, esta é uma ótima documentação para ser validada com o cliente, e com a garantia de que não vai ficar desatualizada por que este é o código fonte dos testes, por tanto sera alterado sempre que a regra de negócio for alterada …

Como assim?
Vamos seguir trabalhando no sistema, agora que ja temos o “behavior”, ou seja, o comportamento definido, vou adicionar algum código a esta história que devera ser testada sempre junto com o build automatizado do sistema:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package users;
 
description """Qualquer novo visitante do site deve poder se registrar no sistema, 
desde que as regras de validação definidas sejam atendidas.
Um usuário registrado podera alterar a sua senha sempre que desejar, mas a senha devera atender aos padrões minimos de segurança"""
 
scenario "Um novo usuário precisa confirmar a senha", {
	given "Um novo usuário", {
		user = new User()
	}
	when "O usuário preenche o nome de usuário e a senha, mas sem confirmar a mesma", {
		user.setName "validName"
		user.setPassword "aPassword"
	}
	then "A validação do usuário deve falhar", {
		ensureThrows(PasswordValidationException){
			user.validate()
		}
	}
	when "O usuário preenche o nome de usuário e confirma a senha corretamente", {
		user.setName "validName"
		user.setPassword "aPassword"
		user.setPasswordConfirmation "aPassword"
	}
	then "A validação do usuário deve passar",{
		user.validate()
	}
}
scenario "Um nome de usuário deve ser único no sistema", {
	given "Um usuário com o formulário preenchido corretamente", {
		user = new User('userName','password','password')
		userManager = UserManager.getInstance()
	}
	then "O registro deve criar o usuário no sistema", {
		userManager.create(user)
	}
	when "O nome de usuário ja existe no sistema", {
		user = new User('userName','otherPassword','otherPassword')
	}
	then "O registro do usuário deve falhar",{
		ensureThrows(UserAlreadyExistsException){
			userManager.create(user)
		}
	}
}

Pronto, este é todo o código desta história, e foi apenas o que eu escrevi até agora.
Agora preciso criar as classes User, UserManager e implementar os métodos corretamente, para que os testes passem., por que no momento os testes não estão nem rodando, ja que estas classes não existem ainda …

Criada a classe User:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package users;
 
public class User {
	private String name;
	private String password;
	private String passwordConfirmation;
 
	public User() {
		super();
	}
 
	public User(String name, String password, String passwordConfirmation) {
		super();
		this.name = name;
		this.password = password;
		this.passwordConfirmation = passwordConfirmation;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String userName) {
		this.name = userName;
	}
 
	public String getPassword() {
		return password;
	}
 
	public void setPassword(String password) {
		this.password = password;
	}
 
	public String getPasswordConfirmation() {
		return passwordConfirmation;
	}
 
	public void setPasswordConfirmation(String passwordConfirmation) {
		this.passwordConfirmation = passwordConfirmation;
	}
 
	public void validate() {
		throw new RuntimeException();
	}
}

E a classe UserManager:

1
2
3
4
5
6
7
8
9
10
11
package users;
 
public class UserManager {
	private static UserManager instance = new UserManager();
	public static UserManager getInstance(){
		return instance;
	}
	public void create(User user){
		throw new RuntimeException();
	}
}

Os testes agora executam mas falham.

Implementando corretamente o método “validate” da classe User, ja temos 2 testes passando:

1
2
3
4
	public void validate() throws PasswordValidationException {
		if(password==null || passwordConfirmation==null || !password.equals(passwordConfirmation))
			throw new PasswordValidationException();
	}

E agora, finalizando a implementação do método create da classe UserManager.

1
2
3
4
5
6
7
8
	public void create(User user) throws InvalidUserException, PasswordValidationException, UserAlreadyExistsException{
		if(user==null)
			throw new InvalidUserException();
		user.validate();
		if(users.containsKey(user.getName()))
			throw new UserAlreadyExistsException();
		users.put(user.getName(), user);
	}

Todos os testes passam, e o nosso código funciona perfeitamente.

Claro que a DSL do easyb é bem mais completa que isto, é possível testar apenas a especificação de uma classe em vez de uma história completa (eu uso histórias para as regras de negócio importantes para o cliente, e especificações para classes internas do sistema), existem diversos “ensure” para validar o estado desejado, tudo isto vocês podem ver na página do projeto: http://www.easyb.org

E como eu falei antes, este é o código dos testes do sistema, desta forma, quando o usuário solicitar uma alteração, se altera o teste, depois se altera o código.
Quando o seu chefe pedir para você documentar o código escrito até agora, você executa os testes, e copia os txts gerados e envia para ele por e-mail.
Os testes você seria obrigado a escrever de qualquer forma, ja que acredito eu que se você leu até aqui, você acredita que testes de código são importantes.
Como você iria escrever os testes de qualquer forma, agora você precisa fazer uma coisa a menos, que é documentar aquilo que escreveu, por que algum dia você vai querer tirar férias, e outro desenvolvedor vai precisar alterar o código que você escreveu :D

Depois de ler até aqui, o que você acha do easyb?
O que você acha de Behavior Driven Development?
Você concorda comigo, quando digo que o easyb tornou possível BDD em Java? (Sim eu sei que existe o JBehave, mas eu acho o trabalhoso demais, e sei que é possível trabalhar com BDD utilizando qualquer xUnit, mas ai eu perco muito da vantagem da documentação executável)
Você vai pelo menos testar isto no seu próximo projeto?

Eu estou escrevendo alguns pequenos patches e enviando para eles sempre que sinto falta de alguma coisa, e fora isto o projeto vai ter diversas melhorias bastante significativas em pouco tempo!
Parabens aos desenvolvedores, e viva o Groovy, tornando o desenvolvimento Java mais divertido e menos trabalhoso!

Tags: , ,