Arquivo

Textos com Etiquetas ‘TDD’

[POG] Deveria lançar uma “excessão”

24 de fevereiro de 2012

Não preciso falar nada, o nome do teste diz tudo:

[TestMethod]
public void Deveria_lancar_uma_excessao_ao_obter_para_recusa_com_id_igual_a_zero()
{
    try
    {
        Transacao transacao = this.transacaoBO.ObtemParaRecusa(Guid.NewGuid(), 0);

        Assert.Fail("Deveria ser lançada uma ArgumentException.");
    }
    catch (ArgumentException ex)
    {
        Assert.AreEqual<string>(ex.Message, "ID da conta não pode ser menor ou igual a zero." + Environment.NewLine + "Parameter name: idComprador");
    }
}

Exceção mesmo é escrever código em português. Se fosse em inglês, esse atentado à lingua portuguesa teria sido evitado.

Se você não conhece POG (Programação Orientada a Gambiarras), leia esse artigo para entender melhor.

POG , ,

Porque não gosto de usar “should” nos testes de RSpec

23 de outubro de 2011

Desde que li o post RSpec Best Practices de Jared Carroll (post o qual David Chelimsky prefere citar como Good Guidelines) eu prefiro não mais utilizar o termo should para todos os exemplos (testes) de RSpec.

Primeiro que concordo com Jared sobre a redundância da palavra should e como o resultado dos testes ficam mais claros quando rodamos no formato de documentação.

Abaixo dois exemplos (extraídos do post de Jared).

O primeiro usa should:

$ rspec spec/controllers/posts_controller_spec.rb --format documentation

PostsController
  #new
    when not logged in
      should redirect to the sign in page
      should display a message to sign in

Agora eliminando o should e usando o verbo na terceira pessoa:

$ rspec spec/controllers/posts_controller_spec.rb --format documentation

PostsController
  #new
    when not logged in
      redirects to the sign in page
      displays a message to sign in

A segunda razão é a questão gramatical e do sentido dos testes.

O verbo modal should, entre outros significados, pode ser considerado uma obrigação, mas é uma obrigação gentil, cuidadosa, sem muita firmeza.

When not logged in, should redirect to the sign in page.
Quando não logado, deveria redirecionar para a página de login.

Deveria ou deve? Para o teste passar tem que redirecionar para a página de login. Se não redirecionar, o teste falhará. Nessa caso, gramaticalmente, não é melhor usar o verbo modal must, que expressa uma obrigação impreterível?

Então, para ficar simples, uso o verbo na terceira pessoa, evito verbos modais repetitivos e deixo explícito o que o teste está assegurando.

When not logged in, redirects to the sign in page.
Quando não logado, redireciona para a tela de login.

Ruby , ,

2010 em livros

5 de janeiro de 2011

Estou a “plagiando” uma idéia de Phillip Calçado que fez um post em seu blog mostrando os livros lidos no ano de 2010, com um pequeno comentário sobre cada um.

Com certeza minha lista é muito mais modesta e curta, mas a idéia de compartilhar conhecimento é a mesma.

Esse post também serve para me alertar a ler mais, mesmo com toda a correria de trabalho, família, estudo e prática de esportes, gostaria de ter lido mais que 7 livros durante 2010.

Os livros são apresentados na ordem que foram lidos:

Clean Code: A Handbook of Agile Software Craftsmanship

Clean Code: A Handbook of Agile Software Craftsmanship

Robert C. Martin
Prentice Hall
August 2008

Muito bom

Todo programador deveria ler. Uncle Bob nos concede um pouco de sua vasta experiência em desenvolvimento de software, mostrando como deixar seu código mais enxuto, legível e simples. Esse livro serviu de inspiração para várias palestras e apresentações por aí sobre como escrever código de melhor qualidade.

The RSpec Book: Behaviour-Driven Development with RSpec, Cucumber, and Friends

The RSpec Book: Behaviour-Driven Development with RSpec, Cucumber, and Friends

David Chelimsky, Dave Astels, Zach Dennis, Aslak Hellesøy, Bryan Helmkamp, Dan North
The Pragmatic Programmers
December 2010

Ótimo

Essencial para quem quer aprender RSpec. Explica como seria o ciclo ideal de BDD. Também traz exemplos práticos de utilização de RSpec e Cucumber com Ruby e Ruby on Rails.

JavaScript: The Good Parts

JavaScript: The Good Parts

Douglas Crockford
O’Reilly
May 2008

Muito bom

Quem curte JavaScript irá gostar bastante. Fiz anotações sobre esse livro nesse post.

Design Patterns in Ruby

Design Patterns in Ruby

Russ Olsen
Addison-Wesley Professional
December 2007

Bom

Traz uma boa parte dos design patterns apresentados pela GoF utilizando Ruby. O que eu achei mais interessante foi a abordagem utilizada pelo autor: dado um design pattern, o mesmo é implementado de uma maneira clássica e depois reimplementado usando os recursos que o Ruby oferece, como por exemplo, metaprogramação, tornando alguns patterns totalmente diferentes de sua implementação original.

Professional ASP.NET MVC 2

Professional ASP.NET MVC 2

Jon Galloway, Scott Hanselman, Phil Haack, Scott Guthrie, Rob Conery
Wrox
June 2010

Muito bom

Sempre gostei da séria Professional da Wrox e esse livro mantém a linha de qualidade. Logo no primeiro capítulo tem um passo a passo da construção de uma pequena, mas completa, aplicação ASP.NET MVC 2. Os demais capítulos cobrem os demais recursos do framework. Só pelos autores já vale a leitura.

ASP.NET MVC 2 in Action

ASP.NET MVC 2 in Action

Jeffrey Palermo, Ben Scheirman, Jimmy Bogard, Eric Hexter, Matthew Hinze
Manning
June 2010

Regular

Talvez se eu não tivesse lido o livro da Wrox antes teria classificado melhor este. Em algumas vezes os autores focam demais no uso de ferramentas extras, auxiliares ao desenvolvimento de aplicações ASP.NET MVC 2. Isso é bom para quando você já tem conhecimento e/ou vivência do framework.

Test-Drive ASP.NET MVC

Test-Drive ASP.NET MVC

Jonathan McCracken
The Pragmatic Programmers
June 2010

Regular

Eu esperava bem mais desse livro por se tratar de TDD. Havia imaginado vários passos práticos de desenvolvimento orientado a testes no melhor estilo Kent Beck ou Uncle Bob. Para quem já conhece TDD, não irá ver grandes novidades.

Eu uso o Shelfari como prateleira virtual para organizar os livros que li, estou lendo e pretendo ler.
É bem legal e tem vários recursos. Por exemplo, esse endereço lista os livros que li no ano de 2010.

.NET, Arquitetura, JavaScript, Livros, Ruby, TDD , , , , , , , , , , , ,

Como testar gravação de log em Ruby on Rails

17 de novembro de 2010

Em uma aplicação Ruby on Rails, quando você precisa assegurar nos seus testes que a gravação de logs está sendo realizada com sucesso, não há a necessidade de abrir o arquivo físico de log, ler seu conteúdo e verificar se a informação que você deseja está lá.

Ao invés disso, você pode substituir a saída de escrita padrão do log por outra classe de stream, como a StringIO, onde você terá fácil acesso ao que for gravado no log durante o teste.

Log em inglês também é tronco, lenha.

Log em inglês também é tronco, lenha.

Vamos ver um exemplo utilizando RSpec para testar a gravação de log de um método chamado do_something em uma classe modelo SomeModel.

require 'spec_helper'

describe SomeModel do
  before(:each) do
    @some_model = SomeModel.new

    @log_stream = StringIO.new
    @some_model.stub(:logger).and_return(Logger.new(@log_stream))
  end

  describe "#do_something" do
    it "logs info" do
      @some_model.do_something
      @log_stream.string.should include("I am logging something")
    end
  end
end

Na linha 7, criamos uma instância de StringIO atribuindo à variável @log_stream. É nesse objeto que serão gravados todos os logs do nosso teste. Para isso, na linha 8, substituímos o logger original por um stub de Logger que faz referência à instância da classe StringIO que criamos.

Já na linha 14, a asserção do nosso teste verifica se o texto correto foi gravado no stream do log. O método StringIO#string retorna a string bruta, ou seja, o texto que foi gravado no stream.

A seguir está a implementação do método do_something:

class SomeModel < ActiveRecord::Base
  def do_something
    # some implementation

    logger.info "I am logging something"
  end
end

Para fazer testes de gravação de logs em controllers, a idéia é a mesma, basta apenas usar o stub no método logger do controller (linha 6):

require 'spec_helper'

describe SomeModelsController do
  before(:each) do
    @log_stream = StringIO.new
    controller.stub(:logger).and_return(Logger.new(@log_stream))
  end

  describe "GET index" do
    it "logs info" do
      get :index
      @log_stream.string.should include("Now logging in a controller")
    end
  end
end
class SomeModelsController < ApplicationController
  def index
    # implementation

    logger.info "Now logging in a controller"
  end
end

Se você precisa usar log em uma classe que não seja um modelo ou controller, não vai poder chamar o método logger diretamente. Por exemplo, a classe a seguir, foi criada dentro da pasta lib de uma aplicação Rails.

class CoolClass
  def cool_method
    logger.info "Cool log!"
  end
end

Chamando o método cool_method teremos o seguinte erro:
> c = CoolClass.new
> c.cool_method
NameError: undefined local variable or method `logger’ for #<CoolClass:0×1e81bf0>

Resolver isso é simples, basta utilizar Rails.logger:

class CoolClass
  def cool_method
    Rails.logger.info "Cool log!"
  end
end

E no teste para gravação de log o stub é feito na classe Rails (linha 8):

require 'spec_helper'

describe CoolClass do
  before(:each) do
    @cool_class = CoolClass.new

    @log_stream = StringIO.new
    Rails.stub(:logger).and_return(Logger.new(@log_stream))
  end

  describe "#cool_method" do
    it "logs info" do
      @cool_class.cool_method
      @log_stream.string.should include("Cool log!")
    end
  end
end

Ruby, TDD , , , , ,

Entrevista com Fabio Akita

25 de maio de 2010

Geralmente o entrevistado em questão é que faz as entrevistas, mas dessa vez ele fez o papel inverso.

O blogueiro, programador e evangelizador de Ruby e Ruby on Rails fala sobre:

  • Adoção de Ruby on Rails no Brasil
  • O futuro próximo do Ruby e do Rails
  • Ruby on Rails em grandes corporações
  • O melhor ambiente para um equipe de desenvolvimento
  • Sua rotina de estudo e absorção de conhecimento
  • Os atrativos do Ruby para programadores de outras linguagens
  • Dicas para quem está começando com Ruby

Fabio Akita é um conhecido blogueiro e evangelista da comunidade Ruby on Rails
e Agile. Foi Gerente de Projetos na Locaweb, onde também fez parceria na concepção da conferência anual Rails Summit. Já trabalhou como Brazil Rails Practice Manager para a consultoria americana Surgeworks LLC. Antes disso era consultor de integração e desenvolvimento no mundo SAP. Tem mais de 10 anos
de experiência nas áreas de desenvolvimento de software e gestão de projetos.

Atualmente ele mantém os seguintes blogs:

-

Prodis: Quando se engajou no caminho de evangelizar Ruby on Rails, você imaginava a adoção de Rails no Brasil como está hoje? Você se sente realizado com os resultados que conseguiu?

Fabio Akita: Não, não imaginava. Claro, gostaria que tivesse crescido muito mais, mas dadas as circunstâncias do nosso país, acho que a comunidade foi bastante resiliente e persistente, o que foi muito bom. Eu gosto muito da comunidade que se juntou ao redor de Rails e sim, estou bastante contente com o que conquistamos até agora.
-

Prodis: O que você acha que vem pela frente com as grandes mudanças e aprimoramentos do Ruby on Rails 3.0 + Ruby 1.9? O que você espera desse grande passo que o Rails está dando?

Fabio Akita: É um passo natural, tanto o Ruby 1.8 quanto o Rails 2.3 já estão mostrando sua “idade”. O lançamento do Ruby 1.9.2 e Rails 3.0 limpa o ambiente e força a comunidade e levar seus projetos um passo à frente. A comunidade Ruby não é de ficar parada, então em poucos meses a maior parte dos projetos mais importantes já deve se tornar compatível e até o ano que vem projetos novos já devem começar inteiramente nas novas plataformas. Isso trás mais performance de graça pra nós e oferece mais oportunidades de integração e extensão do framework. Será legal.
-

Prodis: Atualmente muitas grandes corporações no Brasil utilizam o modelo Waterfall de desenvolvimento de software. Você imagina que seja possível a adoção do Rails por essas grandes corporações sem utilizarem Metodologias Ágeis ou o desenvolvimento em Rails está intimamente ligado à cultura ágil?

Fabio Akita: A solução nunca é tecnologia e nem metodologia. Particularmente eu não consigo imaginar grandes corporações adotando agilidade nem se elas quisessem. Não se trata de implementar procedimentos e rituais, isso não é ser ágil. Um programador só é sênior se, independente de onde trabalha, ele já segue as disciplinas de engenharia ágil, como TDD, code review, integração contínua, etc, mas mais do que isso: ele entende “porque” elas são necessárias, quando devem ser usadas, e se importa com elas.

A mesma coisa com tecnologia: um programador sênior saberá tirar muita vantagem dela, mas um programador que apenas segue procedimentos, nunca vai entender quais são as vantagens. E por consequência uma grande corporação - que se importa mais com o preço da hora do que com a qualidade dos profissionais - nunca vai conseguir realmente tirar vantagem de quaisquer novas tecnologias e técnicas, incluindo Rails, incluindo Ágil.

Rails não exige ágil, mas software de qualidade exige as técnicas de engenharia do mundo Ágil, por consequência, projetos Rails de qualidade vão exigir as mesmas técnicas.
-

Prodis: Com sua experiência em desenvolvimento e liderança, qual o seria o ambiente ideal para execução de um projeto de curto/médio prazo? Equipe no mesmo local ou home office, pareamento ou não, programadores sêniors ou diversos níveis de conhecimento?

Fabio Akita: Não existe ambiente ideal. A somatória de todos os fatores que compõe qualquer projeto são tantas e tão granulares que não dá para reduzir a poucos elementos. Vai desde o objetivo final do projeto, até o objetivo pessoal de cada indivíduo do grupo, até se a cadeira é confortável.

Mas se me perguntarem minha preferência, com certeza, eu prefiro uma equipe toda de sêniores. Foi assim que entreguei os melhores projetos até agora. Não importa as metodologias, sêniores não precisam delas porque as técnicas já estão incorporadas. Sêniores não são os que “cospem código”, são os que se “importam com o código”. Não é preciso discutir com um sênior se precisa de um repositório de código. É como perguntar pra um motorista se precisa de cinto de segurança. Rituais não fazem sentido nessa etapa, pulamos as cerimônias e vamos direto ao ponto. Mas cuidado: ser um sênior não é nem de longe simplesmente ter “muitos anos de casa”, mas sim muitos “anos de prática real”, fazendo muitas coisas muito diferentes - quem fez 10 anos a mesma coisa não é um sênior, é um júnior de 10 anos.

Se o projeto permitir, é sempre bom colocar alguns júniores como “sombra” de alguns sêniores. Não adianta colocar a metodologia que for: o código de um júnior sempre será pior porque ele ainda não teve oportunidades para praticar. É como qualquer esporte: se o jogador pisou pela primeira vez num campo de futebol, não dá pra esperar que faça gol. Portanto se a empresa preza por seus funcionários ela precisa entender que júniores vão precisar de mais espaço por um período de 1, ou 2 anos de muita prática em diferentes tipos de projetos e sempre acompanhados por sêniores. Ou seja, é um investimento e nunca uma economia de custos. Se o fator for puramente econômico de curto prazo, não faz sentido ter júniores.
-

Prodis: Em um post do seu blog de 2007 “Off Topic: Seja Arrogante!” você fala, entre outras coisas, como aprendia as coisas sozinho sendo pró-ativo e aproveitando seu tempo livre. Conte-nos um pouco sobre sua rotina atual de estudo e absorção de conhecimento. Tem gente que até brinca dizendo que você não dorme, fica programando, lendo ou escrevendo movido a RedBull.

Fabio Akita: Não é brincadeira, eu não durmo mesmo :-) Mas pra esclarecer: não, pra estudar muito não precisa deixar de dormir, isso é excentricidade minha mesmo.

Por mais que se fale em organização pessoal, disciplina e tudo mais, ninguém é 100% disciplinado o tempo todo. Eu particularmente divago bastante, e mudo o foco o tempo todo de assunto pra assunto. Tudo vai depender do que eu acabei de ler ou com quem acabei de falar.

Minha fonte principal de informações diárias é meu Google Reader. De lá eu passo o olho em cerca de 1000 posts por dia. Desses eu devo selecionar para ler cerca de 1 dúzia de artigos. Finalmente 1 ou 2 realmente eu páro para destilar mais a sério. Isso não é uma regra, apenas uma constatação. Dependendo do artigo, ele vai me levar a outras leituras para aprofundar, daí vai desde outros sites, até wikipedia, até a Amazon pra comprar algum livro.

Por exemplo, escrevi recentemente no meu blog uma constatação de que o mercado de apps pra iPhone/iPad vai crescer muito. Logo em seguida comprei os livros de Objective C e Cocoa Programming da O’Reilly em formato eBook e já coloquei no meu iPad. Fui para Salvador dar palestra lendo metade de um deles.

E todo tempo em que não estou no computador é “perdido” pra mim, por exemplo, quando eu preciso sair de carro para ir ao trabalho ou coisa parecida. Meia hora de carro todos os dias pra ir e voltar é 1 hora por dia jogada fora. É o tempo ideal pra carregar meu iPhone com audiobooks e ler nesse período. “Li” (escutei) dezenas de livros dessa forma.

Além disso precisa existir tempo pra networking. Ir em eventos, participar de comunidades, grupos, nem que seja para um simples happy hour. Muitas idéias saem dali e que depois viram temas pra eu continuar estudando ou perseguindo de alguma forma. Sozinho só dá para ir até um certo ponto. Com outras pessoas dá para extrapolar isso, e é importante se acostumar a participar mais de grupos de pessoas.

Mas como falei, eu divago. Ainda estou começando nos estudos de Objective C, mas li um artigo sobre Scala que me deixou curioso pra ir mais a fundo em Scala, e lá vou eu começar outra coisa. A parte difícil é ir até o fim mesmo em algum dos assuntos, e isso eu também não sou perfeito. Muita coisa eu começo e vai ficando pra trás, meses depois eu retomo e vai indo. Não é uma receita de bolo, vai depender muito das circunstâncias, da vontade, das tendências, etc. O importante é começar, como vai acabar é consequência.
-

Prodis: Tenho notado que muitos programadores bons (eu disse bons) de Java e/ou .NET e que experimentam Ruby não querem mais voltar a programar na antiga linguagem. Na sua opinião, qual é o grande atrativo e diferencial do Ruby que faz com que programadores experientes dessas plataformas se interessem cada vez mais pelo Ruby?

Fabio Akita: Isso é uma hipérbole :-) Ruby é uma linguagem de mais alto nível que Java ou .NET. Por consequência, o nível de abstração é muito maior, o que diminui consideravelmente muitas burocracias e cerimônias. Mas isso é verdade para quaisquer outras linguagens de alto nível vs. as de baixo nível. Java era mais alto nível que C. C# é um pouco mais algo nível que Java (a linguagem). Python, Perl, Javascript são tão alto nível quanto Ruby - onde a discussão é mais em “estilos”. Alto nível sempre será mais agradável para alguns tipos de projetos do que os de baixo nível, é um fato da programação. Fazer aplicativos Web com Java é tão tedioso quanto se fosse usar C/C++. Por outro lado não dá para fazer drives de hardware com Ruby, daí preciso de C/C++.

Tipagem dinâmica, envio de mensagens para objetos, blocos de código encapsulados em objetos, só isso tornaria qualquer uma dessas linguagens mais “amigáveis”. Scala é algo parecido: a grosso modo, um Java menos burocrático. Mas ver somente as partes não é suficiente, o pacote todo do Ruby é muito simples e elegante, por isso é difícil largar. Mas ele não é perfeito, assim como nenhuma linguagem. É necessário - e obrigatório - aprender outras linguagens e inclusive não abandonar nem Java e nem C#. Algumas coisas só fazem sentido nessas linguagens.
-

Prodis: E para quem está começando agora com Ruby e Ruby on Rails, sejam vindos de outras linguagens ou como primeira linguagem, qual o conselho que você dá?

Fabio Akita: Entrem na comunidade, acompanhem as listas de discussão, leiam os blogs dos principais Rubistas, encontrem os projetos open source mais discutidos, baixe os códigos, comece a dissecá-los. Isso muito antes de você pensar em escrever seu primeiro programa do zero: vai demorar muito mais tempo se não fizer dessa forma. Livros, Cursos, Tutoriais, Screencasts, tudo ajuda, mas não são completos sem contexto e contexto você consegue só se inteirando e investindo seu tempo pessoal na comunidade. Novamente, não tem receita de bolo: algumas pessoas tem mais facilidade do que outras, e isso é um fato também.
-

Prodis: Para finalizar, fique à vontade para mandar algum recado, mensagem ou comentário para os leitores.

Fabio Akita: O mais importante é n?o se limitar. Eu sou um evangelizador de Ruby e Ruby on Rails, mas antes disso sou um programador que gosta de tecnologia. Nos últimos 20 anos já usei diversas plataformas, muitas delas já extintas, mas cada uma contribuiu para que eu ficasse cada vez melhor. Pouco antes de Ruby eu estava em Java, e .NET. 10 anos atrás estava em ASP e PHP, e assim por diante. Mesmo que você n?o pretenda usar Ruby, o simples fato de aprender contribuirá com sua formaç?o. Portanto o recado é: fique antenado e continue experimentando coisas novas. N?o lembro de quem foi essa frase, mas bons julgamentos vem com experiência, e experiência é formada também fazendo maus julgamentos.
-

Prodis: Obrigado pela entrevista.

Ruby, TDD , , , , , , ,

Jim Webber faz consultoria na Locaweb

5 de maio de 2010

Jim Webber possui uma vasta experiência em arquitetura e desenvolvimento de Web Services. Atualmente está trabalhando na ThoughtWorks de Londres e finalizando seu novo livro REST in Practice: Hypermedia and Systems Architecture, que tem previsão de publicação para setembro desse ano.

Durante toda essa semana, ele está na Locaweb prestando consultoria para as equipes de tecnologia da empresa.

Eu e Jim Webber na Locaweb

Ontem foi a vez da equipe de SaaS, a qual eu faço parte. Mostramos a ele nossos sistemas, arquiteturas, tecnologias, formas de trabalho, desafios, etc. Também falamos dos nossos problemas atuais e, é claro, fizemos um monte de perguntas.

O Jim nos ajudou com algumas dúvidas e nos propos vários soluções e caminhos que podem ser tomados. Ele é um cara bastante extrovertido e simpático. Passamos o dia todo conversando e foi uma experiência muito boa para toda a equipe.

Eu particularmente tive um desafio pessoal, pois apresentei ao Jim o atual projeto de Comércio Eletrônico que estamos desenvolvendo. Foi minha primeira apresentação em inglês e logo para um renomado expectador. Bom, pelo feedback dos meus companheiros de equipe, e do próprio Jim, tudo ocorreu bem.

Arquitetura, Ruby, TDD , , , , , , , , ,

Não escreva código novo sem antes ter um teste falhando

16 de fevereiro de 2010

O título desse post é uma frase de Kent Beck, autor do livro Test Driven Development: By Example. A idéia é que você sempre escreva testes antes de implementar qualquer código. Após o teste escrito falhar, você implementa o suficiente para fazer o teste passar. Com os testes passando, você está livre para refatorar (tanto implementação, quanto teste). A partir daí você cria um novo teste e segue o mesmo fluxo. Esse ciclo se repete até você ter toda a funcionalidade deseja implementada, ou seja, ter testes para todas as possibilidades da sua implementação.

Este é o “bê-a-bá” de TDD, mas na prática isso dificilmente acontece. Não porque não queremos fazer testes (se você não quiser escrever testes, o problema é todo seu), mas porque somos exímios programadores, desenvolvemos orientados a testes por anos, e não precisamos mais seguir os baby steps (passos de bebê), afinal somos programadores maduros.

Sendo assim, pulamos etapas: codificamos primeiro para depois escrever os testes, refatoramos mesmo com testes ainda não passando, escrevemos mais testes mesmo tendo testes anteriores falhando, e por aí vai.

Cuidado! Por mais que você seja um programador “fodão”, ainda sim você pode deixar de testar alguma coisa. Uma lógica de negócio, uma alternativa de fluxo ou uma condição de erro podem passar desapercebidas ao se pular as etapas básicas de TDD. Esse teste faltando, por mais simples que seja, pode causar um erro em ambiente de produção e causar transtornos para o cliente e/ou usuário final da sua aplicação.

Vamos utilizar como exemplo uma simulação de pareamento, onde uma dupla de desenvolvedores irá criar um método chamado positive_balance? para dizer se uma conta bancária, representada pela classe BankAccount, possui saldo positivo.

A linguagem utilizada será Ruby e o framework para testes será RSpec.

Os programadores são Félix (piloto do pareamento) e Péricles. Os dois concordam em iniciar criando a classe BankAccount com a declaração do método positive_balance? sem nenhuma implementação:

class BankAccount
  def positive_balance?

  end
end

- Legal, agora vamos escrever nosso teste. - diz Péricles.
- Para uma conta bancária possuir fundos é nessário que seu saldo seja maior que zero.

describe BankAccount do
  it "should have positive balance" do
    account = BankAccount.new
    account.value = 100.00
    account.positive_balance?.should be_true
  end
end

Eles rodam o teste:

F

1)
NoMethodError in 'BankAccount should have positive balance'
undefined method `value=' for #
./spec/bank_account_spec.rb:6:

Finished in 0.010015 seconds

1 example, 1 failure

E o resultado com erro diz a eles que não existe um atributo value na classe BankAccount. Félix e Péricles o criam:

class BankAccount
  attr_accessor :value

  def positive_balance?

  end
end

E executam o teste novamente:

F

1)
'BankAccount should have positive balance' FAILED
expected nil to be true
./spec/bank_account_spec.rb:7:

Finished in 0.010605 seconds

1 example, 1 failure

O teste falha. Então chegou a hora de escrever código novo, a implementação da funcionalidade que eles querem. Félix implementa o suficiente para o teste passar.

class BankAccount
  attr_accessor :value

  def positive_balance?
    true
  end
end

Péricles discorda totalmente.
- Cê tá louco, mano?! Vai retornar true para tudo?! O cara vai ter sempre saldo na conta?

Félix argumenta.
- A gente não precisa escrever código suficiente para o teste passar? Isso é suficiente.

E roda o teste:

.

Finished in 0.009987 seconds

1 example, 0 failures

- Viu? Passou. - finaliza Félix.
- Mas isso é muito baby step. - reclama Péricles - Vamos implementar o código real, ou seja:

class BankAccount
  attr_accessor :value

  def positive_balance?
    self.value > 0
  end
end

- Mas por que vamos implementar isso agora? Afinal nossos testes estão passando. - Félix rebate.
- Porque está na cara que esse código retornando true sempre não funciona.

Félix continua forçando a discussão.
- Como não funciona? Funciona sim, os testes estão passando.
- Funciona, mas a implementação está errada. - diz Péricles.
- Errada? Mas atende os requisitos até o momento. Afinal, os testes são para assegurar que a lógica do negócio está sendo cumprida.

Péricles fica pensativo.
- Mas o único teste que fizemos não está cobrindo todos os casos da lógica.
- Concordo com você, Péricles. E o que devemos fazer agora então?
- Devemos escrever um teste em que a conta bancária não irá ter fundos.
- Exatamente! - confirma Félix.

E eles continuam nesse linha de raciocínio até o final do pareamento.

Não estou aqui dizendo que você tem que sempre seguir à risca o Red Green Refactor do TDD, muito menos usar baby steps toda vez que você codificar (afinal, a vida não é um dojo), mas que você tenha atenção e controle do que está fazendo, tento o domínio da funcionalidade que está implementando.

Uma das maneiras de se conseguir isso é com pareamento. Seu par irá lhe ajudar a não deixar escapar nenhum teste. Outra maneira é com inspeção de código. De repente, outro desenvolvedor que não participou da implementação pode enxergar algo que você (e/ou seu par) não viu.

De qualquer forma, seja humilde. Use as etapas de TDD para funcionalidades ou lógica mais complexas. E também fique livre para burlar as regras para implementar coisas simples e funcionalidades básicas, ou quando estiver bastante à vontade e seguro do que está fazendo. Mas nunca, eu disse nunca, deixe de escrever os testes.

TDD , , ,

Desprenda-se de convenções de nomenclatura em nome de testes

21 de novembro de 2009

Eu compartilho da opinião de Jimmy Bogard, que diz que os nomes dos testes precisam descrever o que e o porque, a partir da perspectiva do usuário, onde o desenvolver possa ler o nome do teste e claramente entender o comportamento que é esperado.

Um teste unitário nada mais é que um método em uma classe, e tanto em C# como Java, existem convenções de nomenclatura de métodos.

Em C#, nome de métodos são declarados utilizando Pascal Case:

[TestMethod]
public void ProductShouldHaveAtLeastOneCategory()
{
  //Test implementation.
}

Já em Java, convencionou-se escrever métodos utilizando Camel Case:

@Test
public void productShouldHaveAtLeastOneCategory() {
  //Test implementation.
}

Muitas vezes, o nome desses testes (métodos) ficam um tanto longos, como os exemplos acima. Dessa forma, a legibilidade não é muito boa.

Seguindo um dos conselhos de Neal Ford, em sua apresentação 10 Ways to Improve Your Code, você pode deixar de lado as convenções de nomenclatura da linguagem em favor da legilidade dos nomes dos seus testes. Escreva o nome do teste como se fosse uma frase, nada de letras maiúsculas para cada palavra, e use “_” (underscore) para separar as palavras.

Veja como fica o exemplo acima em C#:

[TestMethod]
public void Product_should_have_at_least_one_category()
{
  //Test implementation.
}

E agora em Java:

@Test
public void product_should_have_at_least_one_category() {
  //Test implementation.
}

Não há nenhum mal em se desprender das convenções de nomenclatura de C# e Java em prol da legibilidade dos nomes dos testes. Afinal, testes são uma documentação executável e nós queremos uma documentação clara para nosso código.

TDD , , , , , , ,

fisl10 - TDD e Rails: Mais rápido, mais forte e melhor

30 de junho de 2009

A primeira apresentação que assisti no fisl10 foi muito boa. Lucas Húngaro mostrou formas de criar aplicações Ruby on Rails com testes, passando um pouco da sua experiência em desenvolvimento Web.

Lucas Húngaro

A palestra foi dividida em quatro partes: Fundamentos, Abordagens, Como eu desenvolvo com testes no Rails e Dicas. Mas separei aqui em mais duas: Boas Práticas e Maus Sinais.

Leia mais…

Eventos, Ruby, TDD , , , , , , , , , , , , ,

.NET Architects Day 2009

13 de junho de 2009

No próximo dia 27 de junho vai rolar o primeiro evento do grupo de discussão sobre arquitetura de software .NET Architects.

Eu infelizmente não vou, pois estarei em outro evento. Mas Luciano Coelho e Rodrigo Ortiz, que trabalham comigo, irão e poderão nos contar tudo que aconteceu.

Algo interessante é que exatamente todos os assuntos que serão abordados, estaremos utilizando em um novo projeto que irá iniciar no segundo semestre.

Veja o conteúdo das palestras:

Programando com prazer com Domain Driven Design (DDD)
Giovanni Bassi
O Domain Driven Design é uma nova abordagem para desenvolvimento de software. Mas não é tão nova assim. Ela reune melhores práticas de OO e traz uma nova visão a velhos conceitos. Entenda nesta palestra a proposta do DDD, e porque ele pode mudar sua maneira de programar.

Utilizando Injeção de Dependência com Unity (Enterprise Library)
Leandro Daniel
Nessa palestra veremos o padrão de Injeção de Dependência como uma alternativa técnica na construção de aplicações plugáveis, onde se deseja manter a flexibilidade para troca de componentes com menor impacto de manutenção, maior reusabilidade e facilidade na aplicação de testes.

ASP.NET MVC: tome seu HTML de volta
Victor Cavalcante
Nessa palestra veremos o que é o ASP.NET MVC e o que ele não é, como ele funciona, diferenças entre ASP.NET MVC e Web Forms, extensibilidade, testabilidade, criação de templates com T4 e jQuery. A intenção desta palestra é dar informações suficientes para que o arquiteto decida utilizar ou não ASP.NET MVC.

ORM - Sendo preguiçoso com NHibernate
Juliano Oliveira
Nessa palestra você verá os principais pontos que fazem dos frameworks de ORM e do NHibernate ferramentas tão importantes nos projetos, desmistificar seus maiores mitos, os principais recursos, ferramentas de análise (NHProof) e verá também como ser produtivo com o NHibernate.

Testes: garantindo que seu código faz o que você quer
Mauricio Aniche
Entenda porque testes automatizados de software são importantes e quais as vantagens que ele traz para a equipe de desenvolvimento. Veja também na prática que criar testes automatizados é simples, rápido e realmente útil.

O valor da inscrição é de R$ 50,00 e o evento terá aproximadamente 9 horas de duração.
Mais informações você pode ter diretamente na página do evento.

.NET, Arquitetura, Eventos, TDD , , , , , , , , , , , ,