Suites de testes no CakePHP

Post publicado em 09/03/2014 13:44 Última atualização em 04/04/2015 02:49

Venho trabalhando muito com TDD ultimamente (acredito que agora seja pra valer) e percebo certas diferenças ao rodar os testes em ambientes em que você utiliza X framework comparados ao  CakePHP.

Diferenças

Primeiramente se você está criando testes no Zend Framework por exemplo a configuração inicial (boostrap) de testes se dá de uma forma. Você cria um arquivo bootstrap contendo informações de que módulos serão utilizados assim como o código de produção. Fazendo esta configuração fora do Zend ou seja, sem um framework full-stack normalmente há a necessidade de criação de um bootstrap com parâmetros de configuração do banco de dados, como as entidades serão carregadas (caso esteja usando o ORM Doctrine) e mais algumas configurações. Em resumo, tanto no Zend quanto feito na "unha" você tem pleno conhecimento de como os testes estão sendo realizados, o que e como está sendo utilizado. No Cake PHP isto é um tanto diferente.

Como é no CakePHP?

O Cake pensou em ser um framework de desenvolvimento ágil, rápido, e de fato é. O mesmo possui uma suíte de testes já configurada, com seu próprio bootstrap, Fixtures , coverage, debug, passes... enfim, basta você criar os testes, não é necessário ter conhecimento de como os mesmo foram configurados, basta pegar e usar. Isto por um lado é ótimo, principalmente para quem está começando o desenvolvimento orientado a testes. Mas tem seu preço veja a imagem abaixo e perceba que os testes de App, que é nossa aplicação apenas são rodados um a um. Se você está testando apenas uma parte de cada vez tudo bem, é até mais rápido. No entanto se você precisar rodar um grupo de testes? No Zend ou na "unha" basta adicionar a anotação @group NomeDoGrupo na classe de teste e no momento de rodar o teste apenas adicionar o parâmetro --group NomeDoGrupo e pronto. 1-estrutura-padrao-testes-cake O CakePHP possui o console que pode ser utilizado para executar testes. O test console do cake é apenas uma interface para o executável phpunit no entanto justamente a divisão por grupo simplesmente é ignorada, você até passa o parâmetro --group NomeDoGrupo mas ao completar os demais parâmetros necessários que são [app|core] NomeDoTeste simplesmente o --group não faz mais sentido, perceba nas imagens abaixo. Definimos um grupo de testes na classe desejada. 2-definindo-um-grupo   Rodamos o testes informando que queremos somente o grupo User3-tentando-executar-um-grupo É triste, mas falhamos miseravelmente.   Mas calma há uma solução, não idêntica ao Group do PHPUnit mas ainda sim é uma forma de agrupar. Basta criarmos suítes de testes. Como assim o Cake já não tem sua suíte de testes? Tem. Mas nós podemos criar as nossas também. Supomos que quero testar todos os Models, basta na pasta Test/Case criarmos uma suíte que abranja a pasta model. Crie um arquivo chamado AllModelTest.php e adicione o seguinte conteúdo: (nos comentários a explicação)
<?php 
App::uses('CakeTestSuite', 'TestSuite');

class AllModelTest extends CakeTestSuite {

    public static function suite() {

        //Criando a nova suite de testes (ou grupo de testes)
        $suite = new CakeTestSuite('All Model Tests');

        // Adicionando diretório onde os testes se encontram
        $suite->addTestDirectory(TESTS . 'Case' . DS . 'Model');

        return $suite;
    }
}
Com isso se rodarmos novamente o test console, desta vez nem precisamos passar o parâmetro --group.4-executando-um-grupo Perceba que existe um caso de teste chamado AllModel. Ele pode ser executado com os seguintes comandos ./app/Console/cake test app e selecionando a opção 1 ou simplesmente ./app/Console/cake test app AllModel. Perceba que existem 26 testes pois o mesmo executou apenas os testes que encontram-se estritamente dentro de Test/Case/Model... mas se tivermos Behaviors? O caminho dos behaviors, helpers e components sempre estão dentro das pastas Model/Behavior, View/Helper e Controller/Component respectivamente. Há duas soluções, adicionar em nossa suíte de testes além da pasta Model, também a pasta Model/Behavior ou simplesmente adicionar as pastas recursivamente. como mostrado no novo AllModelTest.php
<?php 
App::uses('CakeTestSuite', 'TestSuite');

class AllModelTest extends CakeTestSuite {

   public static function suite() {

       //Criando a nova suite de testes (ou grupo de testes)
       $suite = new CakeTestSuite('All Model Tests');

       /*
       // Adicionando diretório onde os testes se encontram
       $suite->addTestDirectory(TESTS . 'Case' . DS . 'Model');
       $suite->addTestDirectory(TESTS . 'Case' . DS . 'Model/Behavior');
      */

       // Ou o mais indicado
       $suite->addTestDirectoryRecursive(TESTS . 'Case' . DS . 'Model');

       return $suite;
   }
}
  Com isso rodamos nossos testes novamente e perceba que existem mais de 26 testes como anteriormente 5-executando-um-grupo-recursiv Com este conceito em mãos basta aplicar testes para todos os controllers e views também e por último sugiro a criação de uma suíte chamada All, sendo seu arquivo AllTest.php e seu conteúdo a seguir
<?php
App::uses('CakeTestSuite', 'TestSuite');

class AllTest extends CakeTestSuite {

    public static function suite() {
        $suite = new CakeTestSuite('All tests');
        $suite->addTestDirectoryRecursive(TESTS . 'Case' . DS . 'Controller');
        $suite->addTestDirectoryRecursive(TESTS . 'Case' . DS . 'Model');
        $suite->addTestDirectoryRecursive(TESTS . 'Case' . DS . 'View');

        return $suite;
    }
}
Rodando os testes com o comando ./app/Console/cake test app All todos os testes são executados de uma vez. 6-executando-todos-console E isto é refletido na suíte de testes via browser que o CakePHP fornece. 7-todos-testes-browser E rodando todos via browser temos este resultado 8-rodando-todos-testes-browser   Por hoje é isso, é uma configuração bem simples mas que no CakePHP pode deixar muitos desenvolvedores frustrados por não conseguirem rodar todos os testes simultaneamente. Sugiro a leitura de CakePHP e Composer


Scroll down