© Casa do Código Todos os direitos reservados e protegidos pela Lei nº9.610, de 10/02/1998. Nenhuma parte deste livro poderá ser reproduzida, nem transmitida, sem autorização prévia por escrito da editora, sejam quais forem os meios: fotográficos, eletrônicos, mecânicos, gravação ou quaisquer outros. Casa do Código Livros para o programador Rua Vergueiro, 3185 - 8º andar 04101-300 – Vila Mariana – São Paulo – SP – Brasil Casa do Código Dedicatória Dedico este livro a duas pessoas: minha mãe e minha noiva. Sem o trabalho árduo e constante suporte da minha mãe, eu não estaria aqui hoje, escrevendo um livro. Ela é minha heroína e a pessoa mais batalhadora que já conheci. Obrigado Lilian Pessoa por me dar as oportunidades que tive na vida. Escrever um livro é uma empreitada bem mais trabalhosa que eu pensei. Centenas de horas de trabalho. Essas horas não foram um investimento apenas meu, foi também da minha noiva. Vários meses sem ter um �nal de semana tranquilo para passar ao lado dela. Obrigado Ana Raquel por segurar essa barra e por me apoiar até a última palavra deste livro. i Casa do Código Agradecimentos Primeiro eu gostaria de agradecer ao Adriano Almeida, da Casa do Código, pelo convite para escrever este livro. Sem esse primeiro empurrão é muito improvável que esse livro existiria. Escrevê-lo foi não só um excelente desa�o mas também uma grande oportunidade de aprendizado. Gostaria de agradecer também à Plataformatec e a todo mundo que trabalha comigo lá. São os melhores pro�ssionais com quem eu já trabalhei e me inspiram todo dia a ser um pro�ssional melhor. Não posso deixar também de agradecer a minha família e amigos como um todo. Ao fazer este livro, tive que abdicar de passar inúmeras horas com eles, decisão que não foi fácil de tomar e muito menos de manter. Por �m, gostaria de agradecer às pessoas que investiram seu tempo revisando as primeiras versões deste livro. Eles não tinham nenhuma obrigação de fazê-lo, �zeram pela boa vontade, amizade, por serem colaborativos e pela vontade de aprender algo novo. São eles: Bernardo Chaves, Erich Kist, Danilo Inacio e Anna Cruz. iii Casa do Código Sobre o autor Hugo Baraúna é cofundador e sócio da Plataformatec, empresa de consultoria em desenvolvimento de so�ware especializada em Ruby e Rails. A Plataformatec é referência nacional e internacional no mundo Ruby, devido principalmente a seus projetos open source e sua colaboração com a comunidade. Ele atua tanto na direção da empresa quanto como desenvolvedor, tendo participado de projetos de consultoria, coaching e desenvolvimento para startups e empresas da Fortune ����. Hugo se formou em Engenharia de Computação pela Politécnica da USP. Durante a faculdade, passou pelo laboratório USP-Microso� e por empresas como Procwork e IBM. Para ele, só é possível fazer produtos e serviços de qualidade quando se ama o que faz. v Casa do Código Apresentação Abordagem do livro Este livro não é um manual do Cucumber e de RSpec. Já existem diversos lugares listando as funcionalidades, classes e métodos do Cucumber e RSpec. Portanto, o objetivo não é repetir o que já existe pronto em vários outros lugares. A abordagem deste livro é apresentar como usar essas ferramentas, em vez de mostrar todos os detalhes de cada uma delas. Saber o que as ferramentas oferecem é diferente de saber como usá-las. Além da mostra do uso básico, várias boas práticas não documentadas previamente também são apresentadas, utilizando exemplos ao longo do livro inteiro. Estrutura do livro Este livro está estruturado em quatro partes: �) A primeira consiste em uma introdução ao conceito e histórico do TDD e BDD, assim como um primeiro contato com o RSpec e com o Cucumber. Ela é formada pelos capítulos � e �; �) A segunda é uma apresentação geral do RSpec. Passando pela estrutura básica de um teste de unidade feito com ele, pela organização de testes e pelo uso de test doubles como mocks e stubs. Ela é formada pelos capítulos � a �; �) A terceira parte consiste em uma apresentação do Cucumber e de como usá-lo para escrever especi�cações executáveis. Ela é formada pelos capítulos � a �; �) Por �m, na quarta e última parte, nós construiremos uma aplicação do zero seguindo o conceito de outside-in development do BDD, utilizando RSpec e Cucumber. Ela é formada pelos capítulos �� a ��. vii Casa do Código Para quem é este livro? Estou aprendendo ou já sei programar em Ruby mas nunca �z TDD Se você se enquadra no caso acima, este livro é perfeito para você. Você irá aprender como fazer testes automatizados e seguir o �uxo de TDD e BDD para fazer um código mais fácil de ser mantido e com mais qualidade. Aprender uma habilidade nova não é simples, mas pode ser mais e�ciente com a ajuda de uma apresentação estruturada e de um caminho de�nido. Este livro mostra passo a passo como usar o RSpec e o Cucumber para construir uma aplicação inteira seguindo o �uxo de TDD/BDD. Já faço testes automatizados mas não sei se estou fazendo do jeito certo Existem diversos fatores que in�uenciam o desenvolvimento de bons testes. O que testar? Como testar? Em qual camada testar? Por onde começo? Fazer testes do jeito certo não é apenas ter cobertura de testes em ����. Por exemplo, a maioria das pessoas não sabem que em um teste a clareza é muito mais importante do que o DRY (don’t repeat yourself ). A maioria das pessoas não sabem a diferença entre mocks e stubs e quando usar um ao invés do outro. Este livro responde todas as dúvidas acima e mais várias outras, que o ajudarão a estruturar seu conhecimento em testes automatizados e a escrever testes de qualidade. Já �z testes de unidade, mas não conheço Cucumber, nem o conceito de especi�cação executável Testes de unidade são uma parte muito importante na prática de TDD, mas existem outras camadas de teste, tal como a camada de testes de aceitação. Este livro mostra o que são testes de aceitação e como fazê-los utilizando Cucumber. Na explicação do uso de Cucumber, este livro vai além dos testes de aceitação. O Cucumber é, na verdade, uma ferramenta de documentação, que une especi�cação e testes automatizados, formando o que conhecemos por “especi�cação executável”. Este livro mostra como usar o Cucumber do modo certo, quando vale a pena usá-lo e como usá-lo em conjunto com o RSpec para fechar o ciclo de outside-in development. O que preciso ter instalado? Ao longo do livro veremos vários exemplos de código, e na última parte construiremos um projeto de � a ���. Para ir desenvolvendo o código junto com o livro, você precisará de algumas coisas instaladas. viii Casa do Código Você precisará ter instalado o Ruby �.� ou �.�. Qualquer uma das duas versões deve funcionar, mas dê preferência para a �.�. Além do Ruby, será necessário instalar o Bundler, RSpec e Cucumber. A versão do Bundler utilizada é a �.�.�. A versão do Cucumber é a �.�.��. As versões do RSpec e de seus componentes usadas são: • rspec: �.��.� • rspec-core: �.��.� • rspec-expectations: �.��.� • rspec-mocks: �.��.� Sobre o sistema operacional, você pode usar o Mac OS X, o Linux ou Windows. Dito isso, historicamente o Ruby funciona melhor no Linux e no Mac OS X do que no Windows. Portanto, se você for usuário de Windows e quiser programar em Ruby, uma boa opção é usar uma máquina virtual rodando Linux. Um último detalhe sobre o sistema operacional, ao longo do livro alguns comandos de shell Unix-like são usados, tal como o mkdir para criar diretório, o cd para entrar em um diretório e o touch para criar um arquivo. Apesar de serem usados comandos de um shell Unix-like, a intenção de cada comando será explicada ao longo do livro, de modo que você possa saber o que deve ser feito, caso não esteja usando um shell Unix-like, como no Windows. Você tem dúvidas ou achou algum erro no livro? Este livro possui um grupo de discussão de email com o seguinte endereço: [email protected]. Se você tiver dúvidas sobre o conteúdo do livro ou algo relacionado, você pode enviar um e-mail para o endereço acima. Caso você ache algum possível erro no livro, por favor o envie nessa lista de discussão. Por �m, se você tiver alguma dúvida sobre o código desenvolvido na quarta parte deste livro, a parte do projeto, você pode veri�car um repositório no Github com o código �nal como referência: https://github.com/hugobarauna/forca. ix Casa do Código Sumário Sumário � � � Visão geral sobre TDD � �.� TDD e sua história . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . � �.� E por qual motivo eu deveria usar TDD? . . . . . . . . . . . . . . . . . � Primeiros passos com RSpec e Cucumber � �.� Olá RSpec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . � �.� Olá Cucumber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� O que é BDD? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� Introdução ao básico do RSpec �� �.� Aprendendo a estrutura básica de um teste com RSpec . . . . . . . . . �� �.� Por que existem tantos matchers no RSpec . . . . . . . . . . . . . . . . �� �.� Conhecendo os RSpec built-in matchers . . . . . . . . . . . . . . . . . �� �.� Custom matchers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Entendendo o protocolo interno de matcher do RSpec . . . . . . . . . �� �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . �� � Organização, refatoração e reuso de testes com o RSpec �� �.� Reduzindo duplicação com hooks do RSpec . . . . . . . . . . . . . . . �� �.� DRY versus clareza nos testes . . . . . . . . . . . . . . . . . . . . . . . �� �.� A�er hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Around hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Organizando seus testes . . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Reuso de testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . �� xi Casa do Código Sumário � Mocks e stubs �.� Por que preciso de mocks? . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Conhecendo o conceito de test doubles . . . . . . . . . . . . . . . . . . �� �.� Usando stubs com RSpec . . . . . . . . . . . . . . . . . . . . . . . . . . �� �.� Escrevendo mock expectations com RSpec . . . . . . . . . . . . . . . . ��� �.� Quando usar mock e quando usar stub . . . . . . . . . . . . . . . . . . ��� �.� Usando o método double para fazer testes isolados . . . . . . . . . . . ��� �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . ��� � Conhecendo o Cucumber � � xii �� ��� �.� Por que usar cucumber? . . . . . . . . . . . . . . . . . . . . . . . . . . ��� �.� Cucumber como estímulo de conversa sobre os requisitos . . . . . . . ��� �.� Cucumber: especi�cação e testes juntos! . . . . . . . . . . . . . . . . . ��� �.� Cucumber para construir uma documentação viva . . . . . . . . . . . ��� �.� Visão geral de cucumber . . . . . . . . . . . . . . . . . . . . . . . . . . ��� �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . ��� Especi�cando funcionalidades com Cucumber ��� �.� Instalando e fazendo setup do Cucumber . . . . . . . . . . . . . . . . ��� �.� Estrutura de uma feature com cucumber . . . . . . . . . . . . . . . . . ��� �.� Escrevendo um cenário . . . . . . . . . . . . . . . . . . . . . . . . . . . ��� �.� Escrevendo cenários expressivos com Cucumber . . . . . . . . . . . . ��� �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . ��� Automatizando especi�cações com cucumber ��� �.� Escrevendo os primeiros step de�nitions . . . . . . . . . . . . . . . . . ��� �.� Escrevendo step de�nitions para cenários expressivos . . . . . . . . . ��� �.� Support code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ��� �.� Cucumber World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ��� �.� Usando Cucumber hooks . . . . . . . . . . . . . . . . . . . . . . . . . . ��� �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . ��� Casa do Código Sumário � Boas práticas no uso de Cucumber �.� Use e abuse das descrições da funcionalidade e dos cenários �.� Evite detalhes desnecessários . . . . . . . . . . . . . . . . . . . �.� Cenários imperativos VS cenários declarativos . . . . . . . . �.� Organizando os arquivos da minha especi�cação executável �.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . ��� ��� ��� ��� ��� ��� . . . . . . ��� ��� ��� ��� ��� ��� ��� . . . . . . . . . ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� �� Finalizando a primeira funcionalidade ��.� Deixando o segundo cenário no verde . . . . . . . . . . . . . . . . . . ��.� Finalizando a primeira funcionalidade . . . . . . . . . . . . . . . . . . ��.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . ��� ��� ��� ��� �� BDD na prática, começando um projeto com BDD ��.� De�nindo o escopo da nossa aplicação: Jogo da Forca ��.� Especi�cando uma funcionalidade com Cucumber . . ��.� Usando RSpec no nosso primeiro teste . . . . . . . . . ��.� Usando Aruba para testar uma aplicação CLI . . . . . ��.� Reutilizando step de�nitions de um modo melhor . . ��.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . �� Começando o segundo cenário ��.� De�nindo o segundo cenário . . . . . . . . . . . . . . . . . . . . . . ��.� Reduza duplicação através de support code . . . . . . . . . . . . . ��.� Implementando o �uxo do jogo no binário . . . . . . . . . . . . . . ��.� Modi�cando nosso cenário para receber o feedback correto . . . . ��.� Usando subject e let do RSpec para evitar duplicação nos testes . . ��.� Refatorando o código para poder implementar o segundo cenário ��.� Extraindo uma classe através de refatoração . . . . . . . . . . . . . ��.� Possibilitando ao jogador terminar o jogo no meio . . . . . . . . . ��.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . �� Refatorando nosso código ��.� Identi�cado os pontos a serem refatorados . . . . . ��.� Extraindo uma classe de um método privado . . . ��.� Distribuindo responsabilidades para outras classes ��.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ��� . ��� . ��� . ��� . ��� xiii Casa do Código Sumário �� Especi�cando a segunda funcionalidade ��.� Documentando especi�cação e critério de aceite com Cucumber ��.� De�nindo o teste de aceitação do primeiro cenário . . . . . . . . ��.� Melhore a testabilidade do seu so�ware . . . . . . . . . . . . . . . ��.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . . . �� Finalizando a segunda funcionalidade ��.� Refatorando nosso jogo para ter uma máquina de estados . . ��.� Refatorando o �uxo do jogo para usar a máquina de estados ��.� Organizando seus testes otimizando para leitura . . . . . . . ��.� Interface discovery utilizando test doubles . . . . . . . . . . . ��.� Finalizando a funcionalidade Adivinhar letra . . . . . . . . . ��.� Pontos-chave deste capítulo . . . . . . . . . . . . . . . . . . . �� Finalizando nosso jogo ��.� Especi�cando o �m do jogo ��.� Jogador vence o jogo . . . . ��.� Jogador perde o jogo . . . . ��.� Próximos passos . . . . . . . . . . . . . . . . . . . . . . . Bibliogra�a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ��� ��� ��� ��� ��� ��� ��� . . . . ��� ��� ��� ��� ��� ��� Versão: ��.�.�� xiv . . . . . . . . . . . . . . ��� ��� ��� ��� ���