Back-End

20 dez, 2011

Rodando testes no CakePHP 2.0 – Parte 01

Publicidade

Nesse artigo vamos iniciar a utilização de testes para verificação das funcionalidades de nossas aplicações feitas com o CakePHP 2.0. Ele, em conjunto com o PHPUnit, oferece uma ferramenta para realizar testes programados em nossas aplicações afim de minimizar, ao máximo, os erros. Existem inúmeros tipos de testes específicos – por exemplo, para os controllers, models, views, components e helpers, onde cada um deles pode ser realizado tanto no core do Cake, quanto em nossa aplicação.

Os testes que realizamos no core do Cake já vem pronto para uso, porém nós mesmos teremos que programá-los, um por um. E é exatamente nesse momento que vem a pergunta: Vale a pena o trabalho? Sim, principalmente em sistemas de constante expansão, nos quais, quando alterado um controller ou model para que funcione de forma mais agil, podemos gerar um erro em outro controller/ model que tem algum tipo de relação com o que nós alteramos.

Vamos dar início instalando o PHPUnit no nosso servidor, seguindo os seguintes comandos no Linux:

pear upgrade PEAR
pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit

No Windows, devemos instalar o PEAR executando o script go-pear.bat que se encontra no diretório de instalação do PHP.

go-pear

Depois adicione os repositórios do PHPUnit e atualize-os:

pear channel-discover pear.phpunit.de
pear channel-discover pear.symfony-project.com
pear update-channels
pear upgrade-all

Instalando PHPUnit 3.4.14

pear install phpunit/PHPUnit

Após instalado, certifique-se de que o level de debug está, no minimo, em 1 nas configurações em app/Config/core.php. Caso o debug esteja em 0, não será possível rodar os testes via web. Agora vamos configurar nossa base de dados de teste em app/Config/database.php.

<?php
public $test = array(
    'datasource' => 'Database/Mysql',
    'persistent' => false,
    'host'       => 'dbhost',
    'login'      => 'dblogin',
    'password'   => 'dbpassword',
    'database'   => 'test_database'
);

Para fazer nossos testes, vamos criar uma base de dados chamada test_database. Lembre-se sempre que a base de teste não pode ser a mesma de produção. Recomendo que façam uma copia da base de dados da produção e adicione o prefixo test_ quando forem aplicar testes em seus projetos.

Para ter certeza que o CakePHP Test Suite 2.0 está funcionando acesse-o por estar URL.

Agora que tudo está funcionando perfeitamente, vamos criando uma tabela chamada “posts” com os campos “id”, “título”, “texto”, “created” e “modified”:

CREATE TABLE `posts` ( 
`id` int(11) NOT NULL AUTO_INCREMENT,
`titulo` varchar(50) NOT NULL DEFAULT '',
`texto` text NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=41 DEFAULT CHARSET=latin1 COMMENT='latin1_swedish_ci'

Vamos criar o model e o controller para essa tabela:

  • Model:
<?
class Post extends AppModel{

public $name = 'Post';

}
?>
  • Controller:
<?
class PostsController extends AppController{

public $name = 'Posts';

}
?>

Para facilitar o entendimento, vamos adicionar os métodos da nossa classe PostsController em paralelo com os métodos de testes.

Para implementar uma classe de teste no CakePHP nós devemos utilizar o mesmo nome da classe que vamos testar mais a palavra Test ao final. Dessa forma, a nossa classe de teste para PostsController será PostsControllerTest e ela deverá estender de ControllerTestCase.

Vamos criar, então, um arquivo chamado PostsControllerTest.php dentro de app/Test/Case/Controller/, que é onde todas nossas classes para testar os controllers deverão ficar.

TestController:

<?
class PostsControllerTest extends ControllerTestCase{

}
?>

Agora vamos adicionar o método index na classe PostsController:

public function index(){
$posts = $this->Post->find('all');
$this->set(compact('posts'));
}

Para realizar o teste nesse método, nós devemos criar um método na classe PostsControllerTest chamado testIndex:

public function testIndex(){
$results = $this->testAction('posts/index/');
debug($results);
}

O comando $this->testAction(‘posts/) vai testar essa ação e guardar o resultado na váriavel $results, que  será debugada em seguida.

Como podemos ver no exemplo acima, para testar um método do Controller basta criar um método com o mesmo nome, mudando a primeira letra para maiúscula e adicionando a palavra test antes do nome do método.

Vamos criar agora um método chamado add para adicionar posts no banco.

public function add(){
if($this->data){
if($this->Post->save($this->data))
$this->Session->setFlash('Cadastrado com sucesso!');
$this->data = array();
}
}

Criamos um método para teste agora.

public function testAdd(){
$data = array(
'Post' => array(
'titulo' => 'titulo',
'texto' => 'Lorem ipsum dolor sit amet, consectetur dipisicin'
)
);
$results = $this->testAction('posts/add',array('data' => $data,'method' => 'post'));
debug($results);
}

Como podemos ver, para fazer um teste utilizando uma requisição do tipo post é bem fácil. Tudo que temos que fazer é adicionar um array com os dados que queremos enviar e dentro do método testAction adicionar um array com os dados e o método que desejamos.

Depois de adicionar e listar os posts do banco, vamos criar um método para editar os posts adicionados e seu respectivo teste.

public function edit($id = null){
if($this->data){
if($this->Post->save($this->data))
$this->Session->setFlash('Editado com sucesso!');
$this->redirect(array('controller' => 'posts','action' => 'index'));
}else{
$this->data = $this->Post->read(null,$id);
}
}

No método para teste de edição nós vamos fazer dois testes: um para a leitura do registro, que será editado e depois um da edição em si.

public function testEdit(){
$results1 = $this->testAction('posts/edit/1');
debug($results1);

$data = array(
'Post' => array(
'id' => 1,
'titulo' => 'teste update',
'texto' => 'teste de update do texto'
)
);
$results2 = $this->testAction('posts/edit',array('data' => $data,'method' => 'post'));
debug($results2);
}

Como podemos ver, a única diferença nesse teste é que temos duas variáveis para debugar os erros – caso ocorra algum.

Para finalizar nosso CRUD, vamos criar o método delete e depois seu respectivo método de teste.

public function delete($id = null){
if($id){
if($this->Post->delete($id))
$this->Session->setFlash('Deletado com sucesso!');
$this->redirect(array('controller' => 'posts','action' => 'index'));
}
}

Para testar nosso delete:

public function testDelete(){
$results = $this->testAction('posts/delete/1');
debug($results);
}

Agora que temos todos os métodos implementados em ambos os Controllers, vamos acessar esse link e em baixo da palavra App vamos clicar em Tests e depois em Controller / PostsController. Caso não haja nenhum erro em nosso PostsController ele exibirá a seguinte tela:

Caso encontre algum erro, ele retornará algo parecido com isso:

Agora é só ler o erro retornado e corrigir. Edite a classe PostsController e force alguns erros para ver como ele retorna cada tipo de erro, onde ele exibe a mensagem, ou linha que encontrou o erro. Faça isso para se adaptar a esse ambiente de teste que o Cake nos fornece.

Na segunda parte deste artigo vou explicar como fazer os testes no Model da aplicação.

Espero ter sido útil e até a próxima!