Erro no teste de validação "not null" em campo string no CakePHP
Autor: Adriano "duke" Bacha | Publicado: 2010-03-19T08:22:00-04:00

No início das minhas experiências utilizando BDD com o cakephp e a sua biblioteca de testes (CakeTest estendendo SimpleTest), tive um problema que considero no mínimo bizarro.Vou tentar demonstrar o problema que eu tive e como eu resolvi:Pra começar irei criar uma tabela simples com apenas um campo id (int) e um campo nome (string):CREATE TABLE  `teste`.`usuarios` (`id` INT NOT NULL AUTO_INCREMENT ,`nome` VARCHAR( 255 ) NOT NULL ,PRIMARY KEY (  `id` ))Agora irei gerar pelo bake o modelo dessa tabela com a validação "notEmpty" (recomendada pelo bake para um campo de string) e também os arquivos de teste:Possible Models based on your current database:1. UsuarioEnter a number from the list above, type in the name of another model, or 'q' to exit  [q] > 1Would you like to supply validation criteria for the fields in your model? (y/n) [y] > y[...]Field: nomeType: string---------------------------------------------------------------Please select one of the following validation options:---------------------------------------------------------------[...]20 - notEmpty29 - Do not do any validation on this field.... or enter in a valid regex validation string.  [20] > Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)? (y/n) [y] > n---------------------------------------------------------------The following Model will be created:---------------------------------------------------------------Name:       UsuarioValidation: Array(    [nome] => notempty)Baking model class for Usuario...Creating file /home/duke/www/cakephp/app/models/usuario.phpWrote /home/duke/www/cakephp/app/models/usuario.php[...]Baking test fixture for Usuario...Creating file /home/duke/www/cakephp/app/tests/fixtures/usuario_fixture.phpWrote /home/duke/www/cakephp/app/tests/fixtures/usuario_fixture.phpBaking unit test for Usuario...Creating file /home/duke/www/cakephp/app/tests/cases/models/usuario.test.phpWrote /home/duke/www/cakephp/app/tests/cases/models/usuario.test.phpAgora abrirei o arquivo de testes do modelo (usuario.test.php) e criarei o seguinte método de teste: function testAttributes() {  $this->assertFalse($this->Usuario->validates(), 'should be invalid');  $this->Usuario->set("nome", "adriano");  $this->assertTrue($this->Usuario->save(), 'should be valid'); }Estou fazendo 2 asserts, ou seja, estou garantindo duas coisas:1. que ao tentar validar um objeto "Usuario" sem ter atribuído nenhum parâmetro, ele será inválido pois o campo "nome" é obrigatório;2. e que após definir o campo "nome" para "adriano" e tentar salvar, deve ser válido.Porém ao rodar os testes terei o seguinte resultado:FAILEDshould be invalid at [.../app/tests/cases/models/usuario.test.php line 14]PASSED [...]should be valid at [.../app/tests/cases/models/usuario.test.php line 16]Ou seja, ele falhou no primeiro teste, logo, ele trata o objeto usuário "cru" como um objeto válido.O meu teste está correto, eu quero que aconteça exatamente como designei nas minhas assertions, porém parece que o cake não entende "notEmpty" da mesma forma que eu.Para esse teste passar, teria que setar o nome do usuário vazio antes da assertion:$this->Usuario->set("nome", "");Ai sim ele falharia o validate e o teste passaria, porém eu quero considerar que se a posição do array de dados do objeto ($this->Usuario->data["nome"]) não existir, é porque ela está vazia.Para obter esse resultado, eu altero a regra de validação no modelo:O bake deve gera a validação apenas criando a regra de notempty para o campo: var $validate = array(  'nome' => array('notempty') );e eu alterarei para o campo aceitar todos os caracteres visíveis e ser obrigatório: var $validate = array(  'rule' => array('custom', '/^[\x20-\x7E]+$/i'),  'required' => true );agora se rodar os testes novamente, eles irão passar, mesmo sem declarar como vazio o nome do usuário