Iniciando com TDD

Post publicado em 13/06/2013 23:56 Última atualização em 04/08/2019 20:38

[vc_row][vc_column][vc_column_text]Atenção! Este post é de Junho de 2013, muitas coisas evoluíram desde então, procure aqui no blog mesmo por conteúdos mais atualizados. A um bom tempo que venho bolando praticar TDD fora do framework que utilizo, o CakePHP. Dias atrás "brinquei" um pouquinho e percebi que realizar testes fora do ambiente do framework é mais simples do que eu imaginava, aqui vai um pequeno exemplo de como você também pode fazer para iniciar desenvolver com orienteação a testes.

Do que precisamos?

  • PHP >= 5.3.*
  • PHPUnit
  • Xdebug
Os exemplos foram todos codados em ambiente Linux  (Debian 7) utilizando a IDE Netbeans. Primeiramente você deve instalar o PHP, espero que pelo menos isso você já tenha em sua máquina, não me envergonhe... Em seguida o PHPUnit que não vou fornecer o procedimento de instalação por ser muito simples e está muito bem documentado em português inclusive no site oficial www.phpunit.de e por último o xdebug pra gente gerar o coverage de nossos testes. O coverage é opcional mas é uma ferramenta excelente para que você possa analisar qual o percentual de seu código está coberto por testes além de um ótimo debugger para o PHP. Para instalar o xdebug no Linux Debian-like basta um comando #apt-get install php5-xdebug, já para Windows siga os passos descritos na página oficial www.xdebug.org.  

 Iniciando

Primeiramente crie um arquivo em PHP, sugiro por meios didáticos que o nome seja UserTest.php. Nele, logo no início informamos que precisamos do PHPUnit, com isso basta dar um require em PHPUnit/Autoload.php. Após isto crie uma classe chamada User, apenas a crie e deixe-a vazia. Feito isto é hora de criar a classe de testes, nomeie-a como UserTest e extenda-a da classe PHPUnit_Framework_TestCase conforme a imagem abaixo.

1-classes

  Agora vamos instanciar a classe User em nossa classe de teste a partir do método setUp que é executado automaticamente quando executado o PHPUnit. 2-setUp   Aí já temos um começo... faltam alguns passos, mas são muito simples, fica calmo. Abra o terminal do seu Sistema Operacional, no meu caso Konsole por utilizar Debian com KDE, entre na pasta onde encontra-se seu projeto de teste e, com o PHPUnit instalado corretamente você pode o executar simplesmente digitando $phpunit NomeDaClasseDeTestes isto fará todos os testes existentes nela seja executados. Em nosso caso ainda não existem testes o que nos retornará uma falha indicando da falta de testes na classe. Dica: para que a visualização dos resultados dos testes se torne mais intuitiva podemos habilitar cores adicionado o parâmetro --colors antes do nome da classe de teste. Em nosso caso a execução correta do teste seria $ phpunit --colors UserTest   3-rodando-phpUnit   Agora que já sabemos que teremos de criar um teste ao menos, vamos o fazer. Não sei se é algo realmente necessário mas eu sempre gosto de testar se a classe instanciada é a esperada, com isso crio um método nomeando-o como testInstanceOf, isto é, sempre que se tratar de um teste o nome do método deve iniciar com a palavra test em minúsculo seguido da descrição desejada em camelCased. Agora ao digitar no terminal $ phpunit --colors UserTest haverá um teste que passará, olha só... 4-instanceOf   Note que acima foi apenas um simples teste e este normalmente passará, a não ser que você faça-o quebrar propositalmente. Então para de fato levarmos o TDD em sua correta implementação (vermelho, verde, refatora) devemos criar um teste que quebre, faremos o mesmo abaixo . 5-firstTest-1 Perceba que setamos um nome e depois demos um assertEquals do nome esperado (à esquerda) com o nome retornado (à direita). Dica: Leia os assertions do PHPUnit para conhecer as possibilidades, visto que não é o intuito deste post abranger nada além da asserção de equivalência. https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.assertions. Agora lembre-se de que chamamos o método setName e em seguida o getName, porém ambos não existem ainda. Isto fará o teste quebrar, mas esta não é a única forma de quebra de teste, outra forma é, o método existindo porém não comportando-se conforme o esperado. Ao executar $ phpunit --colors UserTest há inúmeras linhas de erro, erros estes que corrigiremos a seguir. 5-firstTest-2   Na classe User (não na UserTest) criaremos uma variável privada $name e seu getter e setter. Agora ao executarmos $ phpunit --colors UserTest o teste simplesmete ficará verde, olha só que legal!!! 5-firstTest-3 Isto porque tanto o método setName quanto o getName da classe testada comportaram-se conforme o esperado.   Vamos fazer mais um teste quebrar? Que tal gerar uma senha aleatória para o usuário, seguindo um exemplo de um formulário de recuperação de senha onde uma senha provisória é enviada ao email do solicitante. Criamos o teste primeiro (conforme as boas práticas do TDD sugerem: primeiro o teste e em seguida o código "definitivo"). Desta vez assertaremos a NÃO equivalênia, ou seja, testaremos se a senha retornada não é nula. Neste exemplo utilizaremos um recurso bastante útil do PHPUnit que é uma mensagem de informação a respeito do erro, definimos como "Empty Password" com isso ao teste quebrar a gente poderá ver além de qual teste é, uma mensagem mais amigável a respeito do erro. Execute o comando $ phpunit --colors UserTest e veja mais um teste quebrar. 7-secondTest-Password-1   Agora vamos à programação que não só fará o teste passar mas sim como sua aplicação se comportará. Desta vez o teste passa e você tem a certeza de que qualquer alteração futura no método newPassword da classe User ao alterar sua lógica será rapidamente visualizado se houveram erros e onde foram para imediata correção. 7-secondTest-Password-2   [/vc_column_text][us_cta title="Interesse em TDD?" title_size="h3" color="custom" bg_color="#422b72" text_color="#ffffff" btn_link="url:https%3A%2F%2Ftddcomphp.com.br||target:%20_blank|" btn_label="Conheça meu livro" btn_size="20px" btn_style="4"]
Então meu livro é perfeito pra você!
Pra ficar melhor ainda, tenho um cupom de 15% de desconto. Clique em "Conheça meu livro" e pegue o seu![/us_cta][vc_column_text]

Coverage

Com o xdebug instalado temos um ótimo debugger e unindo-o ao PHPUnit podemos visualizar quanto de nosso código está coberto por testes, isto veremos agora. Primeiramente esclareço que somente podemos gerar o code coverage se a classe de testes estiver separada da classe que está sendo testada então crie um novo arquivo chamado User.php, copie toda a classe User que atualmente encontra-se no arquivo  UserTest.php e cole-o no arquivo recém criado.   8-newUserClass-1 Agora inclua o arquivo User.php no UserTest.php. Como neste exemplo não estamos seguindo o padrão PSR-0, não há auto loader com isso vamos no require_one() mesmo. 8-newUserClass-2 Ok, aparentemente está tudo ok, se rodarmos o phpunit com as classes em arquivos separados todos os testes devem passar assim como já passaram anteriormente. Novamente o comando $ phpunit --colors UserTest. 8-newUserClass-2 Legal, agora que em arquivos separados todos os testes permaneceram funcionando basta que geramos o code coverage dos mesmos, para isto o phpunit nos oferece diversas formas de saída para que possamos analisar, pode ser um xml, html, php ou um txt. Utilizaremos o formato html. Digitando o comando $ phpunit --colors --coverage-html coverage UserTest temos
  • phpunit - o próprio framework de testes
  • --colors - saída com coloração para melhor
  • --coverage-html - o formato que será a saída gerada
  • coverage - pasta de destino para os arquivos hml
  • UserTest - a classe de testes.
  Note na imagem abaixo que ao rodar o comando especificando o coverage cria-se um diretório chamado coverage conforme definimos e dentro dele diversos arquivos, era exatamente isto que desejávamos. 9-coverage-1   Agora entrando no browser na pasta do projeto em que estamos realizando nossos testes é necessário entrar na pasta /coveage. Ao entrar o resultado será como abaixo. 9-coverage-2   Neste exemplo temos apenas 1 classe testada, caso tivéssemos mais, as mesmas também seriam listadas como na imagem acima. Para visualizar detalhes da cobertura por testes basta que se clique no arquivo desejado. 9-coverage-3 O mais legal de tudo é que no próprio coverage você encontra informações para suas dúvidas como a coloração das linhas e abrangência do teste.   Este foi um post muito breve do que vem a ser trabalhar com desenvolvimento orientado a testes mas como o intuito é: ser uma porta de entrada para o TDD em PHP acredito ser válido até mesmo porque muita gente acha que é um bicho de 7 cabeças criar testes. Não, criar testes como pode ser visto ao longo do post é uma tarefa muito simples, o grande problema é: O QUE TESTAR?   Espero ter contribuído de alguma forma, até a próxima ;) Código-fonte (PHP) Código-fonte (Ruby)   [/vc_column_text][us_cta title="Interesse em TDD?" title_size="h3" color="custom" bg_color="#422b72" text_color="#ffffff" btn_link="url:https%3A%2F%2Ftddcomphp.com.br||target:%20_blank|" btn_label="Conheça meu livro" btn_size="20px" btn_style="4"]
Então meu livro é perfeito pra você!
Pra ficar melhor ainda, tenho um cupom de 15% de desconto. Clique em "Conheça meu livro" e pegue o seu![/us_cta][/vc_column][/vc_row]


Scroll down