<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Léo Hackin 0.2c &#187; PHP</title>
	<atom:link href="http://www.leohackin.com.br/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.leohackin.com.br</link>
	<description>Eternamente beta, geralmente funcional</description>
	<lastBuildDate>Wed, 21 Jul 2010 00:34:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>II Workshop PHP-ES</title>
		<link>http://www.leohackin.com.br/2010/07/ii-workshop-php-es/</link>
		<comments>http://www.leohackin.com.br/2010/07/ii-workshop-php-es/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 00:26:10 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tecnologia]]></category>
		<category><![CDATA[eventos]]></category>

		<guid isPermaLink="false">http://www.leohackin.com.br/?p=424</guid>
		<description><![CDATA[Aloha, E lá vamos nós de novo:  depois de muitas barreiras, desanimo de fórum e até mesmo o pensamento de desistência, é com prazer que a venho confirmar a realização do II Workshop PHP-ES. O evento acontecerá no dia 28 de agosto (último sábado) na UVV, das 8:30 às 18:00 e  será gratuito: estamos tentando alguns [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2010/07/ii-workshop-php-es/&amp;shorturl=http://bit.ly/cyuWco&amp;title=II+Workshop+PHP-ES&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Aloha,</p>
<p>E lá vamos nós de novo:  depois de muitas barreiras, desanimo de fórum e até mesmo o pensamento de desistência, é com prazer que a venho confirmar a realização do<strong> II Workshop PHP-ES</strong>.</p>
<p>O evento acontecerá no dia 28 de agosto (último sábado) na UVV, das 8:30 às 18:00 e  será gratuito: estamos tentando alguns patrocínios para bancar um Coffee break básico mas até segunda ordem vai ser tudo o mais básico possível.</p>
<p>A grade confirma é:</p>
<p>PHPZeiro: Adote um Framework (Léo Hackin)</p>
<p>CodeIgniter: turbinando a produtividade com MVC (Francisco Souza e André Tagliati)</p>
<p>MySQL: Técnicas simples e eficazes para tirar o máximo do seu servidor Mysql (Marcelo Raposo)</p>
<p>PHP Data Object &#8211; Interface única de comunicação com SGDBs (Almir &#8220;M3nd3s&#8221;)</p>
<p>Moodle: fazendo EAD de qualidade com PHP (Lucas Coradini)</p>
<p>Aprendendo a começar um projeto com SCRUM (Time da Giran)</p>
<p>Como sempre, a idéia dos eventos de PHP-ES é agregar conhecimento aos desenvolvedores PHP não só da linguagem mas também em todo o seu entorno. Nesta edição vamos mostrar como as frameworks, como o CodeIgniter e o PDO, podem ajudar na produção de aplicativos de modo mais sustentável. Falando em base de dados, teremos uma palestra de &#8220;tunning&#8221; e macetes para fazer um ajuste fino do MySQL que foram feitas em cima de uma base de verdade com o DBA dela.</p>
<p>Vamos exibir também um case real e de sucesso feito com o Moodle, uma ferramenta PHP de Ensino a Distancia (EAD). No final do dia teremos um workshop de como iniciar um projeto com Scrum, metodologia ágil que está sendo bastante utilizada em várias empresas de desenvolvimento pela sua flexibilidade.</p>
<p>As inscrições pode ser feitas pelo link no página press-release do evento:</p>
<p><a href="http://www.phpes.org/ii-workshop-php-es/" target="_blank">http://www.phpes.org/ii-workshop-php-es/</a></p>
<p>Estamos ainda à procura de patrocionadores e apoiadores: se estiver interessado ou conheça alguém afim de bancar o coffee break, peça para mandar um e-mail para leohackin@gmail.com ou m3nd3s@gmail.com.</p>
<p>Para mais informações acesse: <a href="http://www.phpes.org/ii-workshop-php-es/" target="_blank">http://www.phpes.org/ii-workshop-php-es/</a></p>
<p>Um abraço forte e até lá. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2010/07/ii-workshop-php-es/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHPzeiro? Adote um Framework! :)</title>
		<link>http://www.leohackin.com.br/2009/12/phpzeiro-adote-um-framework/</link>
		<comments>http://www.leohackin.com.br/2009/12/phpzeiro-adote-um-framework/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 21:29:53 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.leohackin.com.br/?p=342</guid>
		<description><![CDATA[É notável a quantidade de aplicações em PHP que ainda utilizam nosso velho e conhecido modo Macarrônico de programar: dezenas de snippets e blocos de código que trabalham com regras de negócio, apresentação e tudo mais espalhados por N lugares na aplicação. Esse método é justificável dentro da PHP até certo ponto: a própria linguagem [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/12/phpzeiro-adote-um-framework/&amp;shorturl=http://bit.ly/7yrH5d&amp;title=PHPzeiro%3F+Adote+um+Framework%21+%3A%29&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>É notável a quantidade de aplicações em PHP que ainda utilizam nosso velho e conhecido modo <strong>Macarrônico</strong> de programar: dezenas de snippets e blocos de código que trabalham com regras de negócio, apresentação e tudo mais espalhados por N lugares na aplicação.</p>
<div id="attachment_344" class="wp-caption aligncenter" style="width: 318px"><a href="http://www.leohackin.com.br/wp-content/uploads/2009/12/Captura-de-tela-2009-12-22-às-11.07.04.png"><img class="size-full wp-image-344 " title="Captura de tela 2009-12-22 às 11.07.04" src="http://www.leohackin.com.br/wp-content/uploads/2009/12/Captura-de-tela-2009-12-22-às-11.07.04.png" alt="O PHP Macarrônico é assim" width="308" height="159" /></a><p class="wp-caption-text">O PHP Macarrônico é assim</p></div>
<p>Esse método é justificável dentro da PHP até certo ponto: <strong>a própria linguagem tem por princípio a simplicidade e velocidade</strong> na codificação e resolução de problemas. O próprio <a href="http://en.wikipedia.org/wiki/Rasmus_Lerdorf" target="_blank">Rasmus Lerdorf</a>, criador do PHP, já se mostrou bem contrário aos frameworks atuais pois eles são lentos e não escaláveis, culpa do feeling de  &#8221;<em>faz-tudo</em>&#8221; que a maioria delas leva no sentido de continuar ostentando a bandeira de &#8220;desenvolvimento rápido&#8221; da PHP, que muita gente confunde com gambiarras e que transformou a PHP em sinônimo de <strong>POG</strong> (Programação Orientada à Gambiarras).</p>
<p><span id="more-342"></span></p>
<p>Por muito tempo eu, como muitos desenvolvedores/empresas que conheço e já conversei, pensava assim:</p>
<blockquote><p>&#8220;<em>Porque vou abandonar toda aquela minha infra-estrutura pronta de gerenciamento de conteúdo e minhas bibliotecas caseiras que funcionam muito bem para adotar uma framework MVC e perder $$tempo$$ precioso ou impactar no $$prazo$$ que dei para o meu cliente. Não tem porque eu correr esse ri$co</em>&#8220;.</p></blockquote>
<p>Existem <strong>duas situações muito especiais </strong>que consigo identificar na hora de desenvolver uma aplicação e que impactam de forma crítica na <strong>decisão</strong> correta da arquitetura a ser seguida:<strong> necessidade de escalar a aplicação e potencial expansão de funcionalidades durante e depois do projeto</strong>.</p>
<p><em>Quantas aplicações de alta consumo de banda você já desenvolveu em sua empresa com PHP ? E dessas, quantas você realmente tem que dar uma atenção e implementação contínua de funcionalidades novas ?</em> <strong>Se você não contou nenhuma</strong>, o seu caso é bem comparável ao de muitos desenvolvedores PHP por aí. <strong>Se você contou alguma</strong> e<strong> não teve dores de cabeça</strong> com a manutenção ou testes em sua aplicação, <strong>você é um cara de sorte</strong>.</p>
<p>O <em>feijão com arroz </em>do desenvolvimento PHP no Brasil é muito atrelado à gerenciadores de conteúdo, front-end de websites e muitos projetos que geralmente são desenvolvidos por times por vezes multi-disciplinares. Um <strong>ecossistema comum</strong> são<em> agências digitais, bureau de mídias digitais</em> e várias outras<strong> que precisam desenvolver da forma mais simples e eficaz possível</strong>, muitas vezes devido até ao <strong>orçamento apertado</strong> e a menor margem de chance de que as coisas deêm errado para não ferrar um cronograma geralmente apertado e sem vez para os mais lentos. Juntamos isso à realidade dessas empresas que nem sempre tem um <strong>desenvolvedor</strong> com uma boa experiência, <strong>sem background de programação ou &#8220;migrados&#8221;</strong> de outras áreas e a lenha está feita.</p>
<p>Mesmo em ambientes mais profissionais, ainda existem aqueles que ainda resistem à idéia e são os &#8220;super-homens&#8221; que desenvolvem coisas que só eles conhecem e são difíceis de disseminar conhecimento válido na equipe.</p>
<p>Dentro desse contexto, <strong>algumas situações abaixo concerteza já rolaram com você </strong>ou na empresa em que você trabalha:</p>
<ul>
<li>Designers sobrescrevendo páginas com lógica de negócio embutida</li>
<li>Programadores detonando CSS dos outros</li>
<li>Classes das regras de negócio sendo alteradas a torto e direito ferrando algo que ja estava funcionando</li>
<li>Métodos espalhados pela aplicação com nomes bizarros e/ou funcionalidades redundantes ou no mínimo estranhas</li>
<li>Lógica de negócio repetidas, implementadas de formas diferentes e sem um lugar comum</li>
<li>Registros no banco de dados com dados incompletos e inconsistentes</li>
<li>Formulários que não validam tudo o que deveriam validar e que deixam cadastrar assim mesmo</li>
<li>e por ai vai &#8230;. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </li>
</ul>
<p><strong>Puxadin ali, patchzin aqui</strong> e geralmente temos <strong>monstros</strong> burocráticos ou <strong>incontroláveis</strong> que temos que lidar com o passar do tempo: fruto de uma arquitetura por vezes equivocada mas que por N motivos não pode ser substituída. <em>E aí José ?</em></p>
<h2><span style="font-weight: normal;">Adote um framework!</span></h2>
<p>A <strong>solução mais sustentável</strong> para esse tipo de situação seja provavelmente a adoção de um framework, mas <strong>existe uma resistência</strong> muito grande que é completamente justificável: voltamos àquelas perguntas relativas à &#8220;<em>para que mexer num time que está ganhando?</em>&#8220;.</p>
<p>A resposta é:  &#8221;<em>Você pode ganhar muito mais a curto prazo e com mais qualidade de vida&#8221;</em>.</p>
<p><strong>Algumas perguntas e afirmações que já ouvi</strong> (e eu mesmo me fiz) antes de tudo:</p>
<ul>
<li>Meus programadores (ou eu) tem nível técnico para trabalhar com isso?</li>
<li>E tudo o que eu tenho? O que eu faço que isso ?</li>
<li>Isso vai atrasar o projeto cara!</li>
<li>MVC ? ORM? Que p*rra é essa ?</li>
<li>As funções dos meus includes já fazem tudo isso e muito melhor!</li>
<li>Bah! Já temos nosso ADM pronto: é só copiar, colar e alterar os campos. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </li>
<li>O cliente disse que quer apenas produtos e não vai precisar de nada mais.</li>
</ul>
<p>Todo esse tipo de pensamento/sentimento as vezes não vem de comodismo ou preguiça, mas da falta de conhecimento ou estudo de como uma framework pode ajudar no trabalho, até onde ela pode ir e principalmente em equipe multi-disciplinares com prazos ultra-curtos.</p>
<p>Então, vão <strong>algumas observações/pontos de vista</strong> em relação às principais frameworks PHP do mercado que podem resumir de certa forma alguns pontos positivos e relevantes para a adoção de uma framework:</p>
<ul>
<li><strong>Elas já estão bem difundidas, com boa documentação e geralmente tem uma curva de aprendizado mínima</strong>: com um mês um programador iniciante estará fazendo cadastros simples e bacanas;</li>
<li>Por serem frameworks de <strong>conhecimento público</strong>, a disseminação do conhecimento e uso é muito maior e não fica atrelado à uma ou duas pessoas;</li>
<li>Você não tem apenas uma ou duas pessoas pra fazer &#8220;aquela melhoria no envio de e-mail&#8221;: você terá uma comunidade para te ajudar com isso;</li>
<li><strong>Se o &#8220;dono da framework&#8221; morrer, você não perder todo o investimento</strong> na ferramenta porque não existe &#8220;dono&#8221;. Acaba aquela falácia do &#8220;super-homem&#8221; ou do &#8220;cara que fez a framework e só ele sabe mexer nisso&#8221;.</li>
<li>Estatisticamente comprovado, <strong>desenvolver e manter uma framework caseira é muito mais custoso</strong> que usar e customizar uma framework já extensamente utilizada no mercado, tanto à nivel de suporte quanto à melhoria da ferramenta e correção de bugs;</li>
<li><strong>O que traz diferencial para o negócio de seu cliente (e o seu) é o conhecimento de negócio</strong>: a ferramenta será apenas um meio e é mais que bacana que ela esteja pronta e você se preocupe apenas com o negócio e não como <em>&#8220;fazer aquele usuário logar e se manter autenticado em página X e Y&#8221;</em>.</li>
<li><strong>Frameworks trabalham com padrões de design testados e refatorados continuamente</strong> por pessoas com anos de experiência em software: é jogar dinheiro no lixo tentar re-inventar a roda ou re-implementar tudo se não for completamente necessário.</li>
<li>Programadores experientes terão uma ferramenta amplamente testada e na maioria das vezes bem flexíveis quando precisar adaptar &#8220;<em>aquela regra de negócio extraterrestre do cliente XPTO</em>&#8220;;</li>
<li>Frameworks tem um <strong>conjunto grande de plugins/componentes que cobre a maior parte das tarefas comuns</strong> como controle de sessão/cookies, envio de e-mails, upload de imagens, internacionalização, autenticação e por ai vai. Se não existir, geralmente é fácil (e muito didático) desenvolver algo novo e que a comunidade vai concerteza agradecer;</li>
<li>A parte de visualização dos dados (view) fica separada do controle das ações possíveis no sistema (controller), que por sua vez tem que respeitar as regras de negócio implementadas no acesso ao banco (model) que ficam centralizadas num lugar apenas: ou seja, o <strong>MVC (Model-View-Controller) vai diminuir bastante o quebra pau entre designers e programadores</strong> e evitar bastante re-trabalho. No caso de sistemas, vai melhorar e muito a manutenção deste;</li>
<li><strong>O trabalho com testes é praticamente embutido nessas frameworks</strong> e é uma forma ótima para iniciar os trabalhos com TDD nos projetos. Testes não são moda e sim uma tendência natural do mercado onde as aplicações precisam ser cada vez mais confiáveis para não trazer prejuízo para seu cliente;</li>
</ul>
<p><strong>Boa parte das dúvidas</strong> que geralmente se tem recaem principalmente na preocupação de comprometer um projeto com <strong>questões técnicas e impedimentos</strong> ou na parte do aprendizado em si da ferramenta. Felizmente, com o tempo se percebe que com empenho em <strong>cerca de um ou dois meses</strong> uma boa framework é <strong>absorvida naturalmente</strong>.</p>
<p>De certa forma, ela até mesmo <strong>promove uma auto-reciclagem</strong> de todos os profissionais pois começam a envolver questões como <strong>padrões de projeto, orientação à objetos, testes, controles de versão</strong> e tudo o que há mais de novo no mundo de desenvolvimento e que volta e meia não chega ao mundo das agências ou software houses mais caseiras.</p>
<h2><span style="font-weight: normal;">Em resumo</span></h2>
<p>A adoção de uma framework MVC não é um bixo de 15 cabeças cuspindo fogo e destruindo, mas assim como qualquer novidade apresenta riscos e custo, que CONCERTEZA são altamente recompensadores mesmo que no final ela não seja aproveitada: idéias são concebidas e o nível de conhecimento pós-experimentação é notadamente maior.</p>
<p>Para quem quiser tentar, <strong>algumas dicas podem ajudar</strong> (ao menos me ajudaram):</p>
<ul>
<li><strong>Inicie com projetos pequenos</strong> ou internos para sentir como a framework funciona e até mesmo descobrir características a favor ou contra sua adoção na empresa. <strong>Após conhecer pontos fortes e fracos, decida se ela é realmente viável em seu projeto</strong>;</li>
<li>Se você tem um time, <strong>escolha uma pessoa</strong> para estudar a ferramenta escolhida e <strong>depois faça um hands-on com a equipe </strong>pois assim as dúvidas/conclusões fluem de uma maneira surpreendente;</li>
<li><strong>Procure conhecer</strong> sobre OO (Orientação à Objetos), ORM (Object-Relational Mapping), MVC (paradigma Model-View-Controller), TDD (uso bastante o SimpleTest), controle de versão (estamos usando bastante o GIT) e metodologias ágeis (uso bastante o Scrum): essas coisas &#8220;puxam&#8221; junto um monte de outras coisas que vão fazer o aproveitamento de qualquer framework MUITO maior;</li>
<li><strong>Participe ativamente de listas</strong> para tirar dúvidas suas e dos outros: em pouco tempo se tornar um commiter em um projeto pode ser uma experiência e tanto de aprendizado;</li>
<li>Mantenha-se antenado nas novidades da framework: a maioria delas tem atualizações constantes e as vezes até chave para alguma coisas que sua empresa pretende fazer;</li>
</ul>
<p>Existem, claro, frameworks com diferentes abordagens e  vantagens. Então, para tentar encurtar o caminho mas sem traçar um comparativo muito técnico, vão algumas bacanas para se começar:</p>
<ul>
<li><a href="http://cakephp.org/" target="_blank"><strong>CakePHP</strong></a>, hoje uma das frameworks mais conhecidas e utilizadas no PHP, é uma ferramenta bem influenciada pelo Ruby On Rails, com documentação bacana e uma comunidade grande pacas. Sua curva de aprendizado é bem fácil e os resultados saem bem rápido também, devido ao enorme número de coisas prontas para serem utilizadas. Um ponto fraco é sua performance que não é tão rapida quanto às concorrentes;</li>
<li><strong><a href="http://codeigniter.com/" target="_blank">CodeIgniter</a></strong>, é uma framework que vai no caminho contrário da CakePHP: ela é mais enxuta e sem muitos componentes para rodar bem rápido. Sua curva é tranquila e a documentação bem bacana. Um ponto fraco é a ausência nativa de ORM para mapeamento do banco de dados.</li>
</ul>
<p><a href="http://www.phpframeworks.com/top-10-php-frameworks/" target="_blank">Existem várias frameworks</a>, com vários &#8220;sabores&#8221; a serem degustados:<strong> é ver, testar e ver qual mais agrada e ser feliz!</strong></p>
<p>Simbora.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/12/phpzeiro-adote-um-framework/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Mock Objects no SimpleTest</title>
		<link>http://www.leohackin.com.br/2009/12/mock-objects-no-simpletest/</link>
		<comments>http://www.leohackin.com.br/2009/12/mock-objects-no-simpletest/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 15:51:34 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[mockobjects]]></category>
		<category><![CDATA[simpletest]]></category>

		<guid isPermaLink="false">http://www.leohackin.com.br/?p=253</guid>
		<description><![CDATA[Olá pessoal, Continuando nossa sequência de artigos sobre o SimpleTest, já aprendemos como fazer testes unitários e agrupa-los para facilitar a execução em lote: agora vamos falar um pouco sobre mock objects. Até agora, nossos testes unitários se resumiram a testar métodos e funcionalidades que envolviam apenas uma classe como nossa calculadora: tínhamos um método chamado [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/12/mock-objects-no-simpletest/&amp;title=Mock+Objects+no+SimpleTest&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Olá pessoal,</p>
<p>Continuando nossa sequência de artigos sobre o <a href="http://www.simpletest.org" target="_blank">SimpleTest</a>, já aprendemos <a href="http://www.leohackin.com.br/2009/07/iniciando-com-o-simpletest/" target="_blank">como fazer testes unitários</a> e <a href="http://www.leohackin.com.br/2009/07/agrupando-casos-de-teste-no-simpletest/" target="_blank">agrupa-los</a> para facilitar a execução em lote: agora vamos falar um pouco sobre <strong>mock objects</strong>.</p>
<p>Até agora, nossos testes unitários se resumiram a <strong>testar métodos e funcionalidades que envolviam apenas uma classe</strong> como nossa calculadora: tínhamos um método chamado &#8220;somar&#8221; que fazia parte da própria classe e recebia como parametro de entrada apenas dois inteiros.</p>
<p>A idéia do <strong>teste unitário</strong> (ou de unidade), como o próprio nome diz, é <strong>isolar e testar apenas aquele ponto e funcionalidade</strong> do software: então é imprescindível que possamos isolar da melhor maneira apenas a classe/métodos que desejamos testar para que, caso apresente falha, possamos <strong>identificar exatamente onde a falha ocorreu</strong>.</p>
<p>Mas e quando nossa classe depende de outra(s) classe(s) para fazer um método funcionar ?</p>
<p><span id="more-253"></span></p>
<h2><span style="font-weight: normal;">Conceituando o problema</span></h2>
<p>Então, vamos imaginar a seguinte situação: estamos desenvolvendo um software de e-commerce e em dado momento precisamos validar se um usuário existe em nosso banco de dados. Apesar das possibilidades abrangentes de um sistema de validação/autenticação, vamos nos preocupar com o básico e implementá-lo de uma forma simples como abaixo:</p>
<div id="attachment_264" class="wp-caption aligncenter" style="width: 568px"><img class="size-full wp-image-264" title="As classes usadas no validador" src="http://www.leohackin.com.br/wp-content/uploads/2009/12/diagrama_validator.gif" alt="As classes usadas no validador" width="558" height="181" /><p class="wp-caption-text">As classes usadas no validador</p></div>
<p>Vamos criar uma classe chamada <em><span style="text-decoration: underline;">Validator</span></em>, que receberá o login do usuário, verificará no banco de dados se ele existe ou não e validará seu acesso. Para tanto, nossa classe de validação terá um método chamado <em>validate</em>, que receberá um parâmetro <em>string</em> representando o nome do usuário a ser validado.</p>
<p>Para conectar-se ao banco de dados, nossa classe receberá em sua criação um objeto referente à classe <em><span style="text-decoration: underline;">Conexao</span></em>, que disponibilizará um método chamado <em><span style="text-decoration: underline;">query</span></em>, que consulta o banco e retorna uma array de resultados.</p>
<p><strong><span style="color: #000080;">classe validator.php</span></strong></p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> Validator <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$conexao</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conexao</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conexao</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> validate<span style="color: #009900;">&#40;</span><span style="color: #000088;">$nome</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">// aqui vai a lógica para verificar se o usuário existe ou não e que vamos testar</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p><span style="color: #000080;"><strong><span style="color: #333399;">classe conexao.php</span></strong></span></p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> Conexao <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">// configura o acesso ao banco de dados</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> query<span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">// retorna um array com os resultados da consulta</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Para que tudo fique mais claro, podemos dar uma olhada em como ficaria nosso código final da aplicação:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Config<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000088;">$Conexao</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Validator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$usuario</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Léo'</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$validator</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$usuario</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">// redireciona para a página restrita</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">// retorna uma alerta falando que o usuário não existe</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Como aprendemos em nosso primeiro artigo sobre TDD, <strong>primeiro fazemos os testes e depois fazemos nossa aplicação passar nos neles</strong>, implementando a lógica de negócio válida. Nosso objetivo nesse momento é <strong>testar o método validate</strong>: fazendo um pouco de nossa flexão mental chegamos a dois comportamentos válidos para o método:</p>
<ul>
<li>Se o usuário existir, ele retornará true;</li>
<li>Se o usuário não existir, ele retornará false;</li>
</ul>
<h2><span style="font-weight: normal;">O problema </span></h2>
<p>Então, pensamos &#8220;<em>Bacana! Então vou fazer um caso de teste chamado ValidatorTestCase e um teste chamado testValidarSeUsuarioExistir que irá validar se um usuário foi validado se ele existir!</em>&#8220;.</p>
<p>Partimos para o código então:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> ValidatorTestCase <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> testValidarSeUsuarioExistir<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Config<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Conexao<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Validator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$validator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p><strong>Tudo ok ?</strong> <span style="color: #800000;"><strong><span style="color: #ff0000;">NADA OK!</span></strong></span> O código acima pode funcionar mas temos alguns problemas:</p>
<ul>
<li>Como garantir que nosso banco de dados vai estar disponível na hora do teste ?</li>
<li>Como vamos saber se existe o usuário que queremos testar está no banco, para testarmos se a validação realmente vai passar no teste e se comportar como queremos ?</li>
<li>E se ocorrer um erro de conexão ao banco no meio do teste ?</li>
<li>E se a conexão banco for demorada e nosso caso de teste ter 50 testes acessando o banco? oO</li>
<li>Como saber se as configurações estão exatas para a conexão no banco? Aliás, eu nem sei nada sobre config até agora!</li>
<li>E principalmente: e se ocorrer um problema na pesquisa da query que não tenha nada haver exatamente com nosso validador, já que nosso objetivo é testar unicamente se &#8220;ao receber um usuário, verificar se ele existe no banco e validar em caso afirmativo&#8221;.</li>
</ul>
<p><strong>Haja coisa né ?</strong></p>
<h2><span style="font-weight: normal;">Mock Objects (nosso boneco de testes)</span></h2>
<p>Pensando nesse problema, foram criados os <strong>Mock objects</strong>. Um mock object (vou usar o termo em inglês pois a esmagadora maioria das referências TDD estão assim) nada mais é que <strong>um objeto que simula e imita o comportamento de um objeto real</strong>.</p>
<p>Imagine os <strong>bonecos de teste de batidas de carro</strong>: os engenheiros os constroem com peso, altura, juntas e vários aspectos que <strong>imitam o corpo de um ser humano para poderem fazer seus testes</strong>. Eles colocam esses bonecos nas mais variadas situações e posições possíveis para testarem a segurança de um carro entre outras coisas, sem precisar matar ninguém para isso. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>No nosso caso, nossos <strong>mock objects são representações de classes reais onde podemos simular e forçar qualquer comportamento que desejamos para testarmos certas situações</strong> que talvez não seriam possíveis de serem alcançadas &#8220;explicitamente&#8221; sem gambiarra-las ou mesmo que sejam de dificil configuração.</p>
<p>Em resumo, usamos um mock quando nossa classe real (<span style="color: #c0c0c0;">colado do wikipedia &#8211; thank&#8217;s god</span>):</p>
<ul>
<li>gera resultados não deterministicos (e.g. a hora ou temperatura atual);</li>
<li>tem estados que são difíceis de criar ou reproduzir (e.g. erro de comunicação da rede);</li>
<li>é lento (e.g. um banco de dados completo que precisa ser inicializado antes do teste);</li>
<li>ainda não existe ou pode ter comportamento alterado;</li>
<li>teriam que adicionar informações e métodos exclusivamente para os testes (e não para sua função real).</li>
</ul>
<p>Analisando nosso problema anterior, podemos constatar que nossa classe <em><span style="text-decoration: underline;">Conexao</span></em> é forte candidata à ser &#8220;mockeada&#8221;: assim nos livramos de todos aqueles problemas de conexão, de existência de registros e tudo mais que não tem nada haver com nosso teste unitário em si, que diz respeito pura e diretamente à nossa classe <em><span style="text-decoration: underline;">Validator</span></em>.</p>
<p>Ou seja, <strong>ao invés de usar a classe Conexao real, vamos usar uma &#8220;imitação&#8221; dela, muito mais simples e fácil de manipular</strong> para chegarmos de forma mais simples ao nosso resultado esperado no teste unitário. Vamos utilizar esse mock pois não faz sentido testar a conexão nem nenhum método dessa classe e sim utilizar o comportamento referente ao código que vamos utilizar no nosso teste.</p>
<h2><span style="font-weight: normal;">Codando!</span></h2>
<p>Como vimos, nossa classe <em><span style="text-decoration: underline;">Conexao</span></em> não tem nada implementado ainda. Mas isso não nos interessa pois vamos fazer um mock da classe, para podermos simular o que precisamos: o retorno dos resultados que desejamos para testar o método <em><span style="text-decoration: underline;">validate</span></em> do <em><span style="text-decoration: underline;">Validator</span></em>.</p>
<p><strong>Para criar um mock de nossa classe</strong>, simplesmente fazemos o include dessa classe em nosso teste e &#8220;geramos&#8221; esse mock com o método <em><span style="text-decoration: underline;">generate</span></em> da classe <em><span style="text-decoration: underline;">Mock</span></em> (que é importada automaticamente no nosso include do autorun.php do Simpletest).</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'conexao.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'validator.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
Mock<span style="color: #339933;">::</span><span style="color: #004000;">generate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Conexao'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Com isso, vamos gerar um clone mockeado da classe <span style="text-decoration: underline;"><em>Conexao</em></span> para podermos usa-la em nossos testes.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'conexao.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'validator.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
Mock<span style="color: #339933;">::</span><span style="color: #004000;">generate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Conexao'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> ValidatorTestCase <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> testValidarSeUsuarioExistir<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockConexao<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #339933;">...</span><br />
<span style="color: #339933;">...</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Fácil né ?</p>
<h2><span style="font-weight: normal;">Mocks como atores</span></h2>
<p>Agora que sabemos como criar um mock, <strong>vamos aprender a &#8220;imitar&#8221; o que a classe original faz afim de &#8220;simular&#8221; os resultados</strong> que queremos ter para fazer nossos testes passarem.</p>
<p>Os Mocks podem se comportar de duas maneiras:</p>
<ul>
<li>como <strong>Atores (Actors)</strong>, onde o Mock é usado para simular o retorno de propriedades e métodos (e o que vamos usar aqui).</li>
<li>como <strong>Críticos (Critics)</strong>, onde o Mock é usado para guardar e verificar as interações entre os objetos num teste.</li>
</ul>
<blockquote><p>Quando trabalhamos com o Mock apenas como Ator, apenas simulando o retorno de propriedades e métodos, ele é considerado um &#8220;server stub&#8221;, que nada mais é que um objeto que simula um comportamento. Existe uma grande discussão existe em torno disso, mas por enquanto vamos deixar pra lá pois vamos falar sobre os Mocks como uma ferramenta para testes baseados em interação no próximo post e isso vai ficar mais claro.</p></blockquote>
<p>Se analisarmos a classe <em><span style="text-decoration: underline;">Conexao</span></em> novamente, vamos chegar à conclusão que o método que vai ser utilizado em nosso teste será apenas o <em><span style="text-decoration: underline;">query</span></em>: vamos fazer uma consulta à base dados buscando todos os usuários cujo nome seja igual ao parametro que enviarmos ao método <em><span style="text-decoration: underline;">validate</span></em>.</p>
<p><strong>Nosso mock da </strong><em><span style="text-decoration: underline;"><strong>Conexao</strong></span></em><strong> ainda não sabe fazer nada, mas podemos instrui-lo a retornar o que a quisermos</strong>. Por exemplo, em nosso teste chamado <strong>testValidarSeUsuarioExistir</strong> vamos ter que dizer ao mock para retornar sempre um resultado que satisfaça nosso teste. Ou seja, como no exemplo da implementação, se eu envio &#8220;Léo&#8221; ele tem que me devolver um resultado onde &#8220;Léo&#8221; esteja presente, pois queremos testar o comportamento do <em><span style="text-decoration: underline;">validate</span></em> e não o retorno de valor da conexão.</p>
<p>Então, <strong>vamos fazer nosso mock devolver sempre um resultado onde exista o usuário &#8220;Léo&#8221; no resultado</strong>.</p>
<p>Como vimos, nosso método <em><span style="text-decoration: underline;">query</span></em> retorna uma array com os resultados da consulta. Vamos então instruir o mock a retornar sempre um array quando o método query for chamado. Quando o objeto é mockeado, ele ganha vários métodos, entre eles o <strong>s</strong><strong>etReturnValue: esse método diz ao mock &#8220;retorne sempre X resultado quando tal método for chamado&#8221;</strong>.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockConexao<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$conexao</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setReturnValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query'</span><span style="color: #339933;">,</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Pronto! Agora podemos testar nosso validate:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'conexao.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'validator.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
Mock<span style="color: #339933;">::</span><span style="color: #004000;">generate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Conexao'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> ValidatorTestCase <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> testValidarSeUsuarioExistir<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockConexao<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$conexao</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setReturnValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query'</span><span style="color: #339933;">,</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Validator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$validator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>O que aconteceu em nosso teste:</p>
<ul>
<li>Criamos um mock do nossa classe Conexao</li>
<li>Instanciamos esse mock em nosso teste</li>
<li>Instruimos ao mock para que ele devolvesse sempre um array com o usuário Léo quando o método query fosse chamado</li>
<li>Instanciamos nosso validator, passando como parâmetro nossa conexao mockeada</li>
<li>fizemos o teste para verificar se a validação deu certo</li>
</ul>
<p>Fui roda-lo e &#8230;.</p>
<div id="attachment_310" class="wp-caption aligncenter" style="width: 624px"><img class="size-full wp-image-310" title="Opsss! Falhou! :D" src="http://www.leohackin.com.br/wp-content/uploads/2009/12/Captura-de-tela-2009-12-04-às-19.31.10.png" alt="Opsss! Falhou! :D" width="614" height="298" /><p class="wp-caption-text">Opsss! Falhou! <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p></div>
<p>Temos nosso resultado esperado, afinal <strong>não implementamos ainda nosso método <em><span style="text-decoration: underline;">validate</span></em></strong>. Então, vamos resolver isso:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> Validator <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$conexao</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conexao</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conexao</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> validate<span style="color: #009900;">&#40;</span><span style="color: #000088;">$nome</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #000088;">$resultados</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conexao</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;select id, nome from users where nome = '<span style="color: #006699; font-weight: bold;">{$nome}</span>'&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/array_search"><span style="color: #990000;">array_search</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$nome</span><span style="color: #339933;">,</span><span style="color: #000088;">$resultados</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Implementamos uma lógica onde fazemos uma pesquisa ao banco pedindo para selecionar o id e o nome da tabela users onde o nome seja igual ao parâmetro enviado. <strong>A mágica acontece finalmente</strong>: nossa &#8221; falsa conexao&#8221; foi instruída a retornar sempre um array com uma posição apenas, onde o resultado sempre é Léo. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Agora quando rodamos o teste:</p>
<div id="attachment_315" class="wp-caption aligncenter" style="width: 521px"><img class="size-full wp-image-315" title="Teste do validator agora com a implementação" src="http://www.leohackin.com.br/wp-content/uploads/2009/12/Captura-de-tela-2009-12-05-às-10.25.05.png" alt="Teste do validator agora com a implementação" width="511" height="281" /><p class="wp-caption-text">Teste do validator agora com a implementação</p></div>
<p><strong>Bingo! Nosso teste passou!</strong></p>
<p>Para comprovarmos que o funcionamento do <em><span style="text-decoration: underline;">validate</span></em> está correto, vamos complementar nosso caso de teste adicionando um teste pra verificar se informarmos um usuário que não existe, ele retornar false.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;height:350px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'conexao.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'validator.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
Mock<span style="color: #339933;">::</span><span style="color: #004000;">generate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Conexao'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> ValidatorTestCase <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> testValidarSeUsuarioExistir<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockConexao<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$conexao</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setReturnValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query'</span><span style="color: #339933;">,</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Validator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$validator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> testNaoValidarSeUsuarioNaoExistir<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000088;">$conexao</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockConexao<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$conexao</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setReturnValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query'</span><span style="color: #339933;">,</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Léo'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Validator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conexao</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$validator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Jeveaux'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Vamos testar denovo e &#8230;</p>
<div id="attachment_322" class="wp-caption aligncenter" style="width: 523px"><img class="size-full wp-image-322" title="Fazendo dois testes" src="http://www.leohackin.com.br/wp-content/uploads/2009/12/Captura-de-tela-2009-12-05-às-12.42.23.png" alt="Fazendo dois testes" width="513" height="281" /><p class="wp-caption-text">Fazendo dois testes</p></div>
<p>Mantemos o nosso mock retornando apenas &#8220;Léo&#8221; nos resultados, mas dessa vez passamos o nome &#8220;Jeveaux&#8221; para procurar e como esperado, ele retornou false, dado que o usuário &#8220;Jeveaux&#8221; não existe. <strong>Show!</strong></p>
<h2><span style="font-weight: normal;">Ufa! Vamos resumir o testamento</span></h2>
<p>O aprendizado de mock objects é um pouco abstrato inicialmente mas com alguma prática se revela uma técnica perfeita e viável para fazemos nossos testes unitários funcionarem de forma correta e independente. A utilização do Mock Object apenas como ator (ou server stub como você lerá muito por ai) é apenas uma parte do poder real de um mock.</p>
<p>Dentro de nosso entendimento, podemos resumir que um<strong><em> mock object é uma imitação de nosso objeto real que podemos manipular de forma fácil e simples para que ele faça exatamente o que quisermos, facilitando assim a implementação de nossos testes unitários e isolando nossas classes</em></strong>.</p>
<p>Algumas leituras legais melhorar o entendimento dos Mock Objects:</p>
<ul>
<li><a href="http://www.simpletest.org/en/mock_objects_documentation.html" target="_blank">Mock Objects no SimpleTest [ doc oficial do SimpleTest ]</a></li>
<li><a href="http://www.improveit.com.br/xp/praticas/tdd/mock_objects" target="_blank">Testes de unidade com mock objects [ ImproveIt ]</a></li>
<li><a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/12/19/135757.aspx" target="_blank">Mock Objects and Stubs: The Bottle Brush of TD</a>D</li>
<li><a href="http://pt.wikipedia.org/wiki/Mock_Object" target="_blank">Mock Objects [ Wikipedia]</a></li>
</ul>
<p>Outra referência bem bacana é o <a href="http://www.jeveaux.com" target="_blank">blog do Jeveaux</a>, meu revisor TDD oficial e grande conhecer de causa. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>No próximo post vamos ver como trabalhar com nosso Mock Object em sua forma mais plena e com um exemplo um pouco mais complexo para partir também para o modo Critic. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Simbora.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/12/mock-objects-no-simpletest/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Problema com IDs alfanuméricos no form-&gt;input (select) do CakePHP</title>
		<link>http://www.leohackin.com.br/2009/11/problema-com-ids-alfanumericos-no-form-input-select-do-cakephp/</link>
		<comments>http://www.leohackin.com.br/2009/11/problema-com-ids-alfanumericos-no-form-input-select-do-cakephp/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 05:42:58 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[dica]]></category>

		<guid isPermaLink="false">http://www.leohackin.com.br/?p=211</guid>
		<description><![CDATA[Para quem já está mexendo com CakePHP a algum tempo, algumas limitações de funcionalidades podem tirar um pouco o sono de quem está muito mal acostumado com a produtividade da framework. Em geral, toda framework tem seus pontos fracos. A algum tempo, tive um problema curioso: a chave primária de uma tabela teria valores alfanuméricos. [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/11/problema-com-ids-alfanumericos-no-form-input-select-do-cakephp/&amp;title=Problema+com+IDs+alfanum%C3%A9ricos+no+form-%3Einput+%28select%29+do+CakePHP&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Para quem já está mexendo com CakePHP a algum tempo, algumas limitações de funcionalidades podem tirar um pouco o sono de quem está muito mal acostumado com a produtividade da framework. Em geral, toda framework tem seus pontos fracos.</p>
<p>A algum tempo, tive um problema curioso: a chave primária de uma tabela teria valores alfanuméricos. Ou seja: valores como &#8220;205-A&#8221;, &#8220;JB02&#8243; e outros bizarros seriam possíveis. Regra de negócio definida, modificação do modelo para o nome de chave fora da convenção e tudo corria bem até que populei um select.<br />
 <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  Qual não foi minha surpresa em ver que o CakePHP, além de não marcar o valor correto, em certos casos ainda selecionava mais de um valor no select. #fail total.</p>
<p><span id="more-211"></span></p>
<p>Pesquisa na internet, perguntas na lista de discussão oficial do CakePHP e as respostas eram:</p>
<ul>
<li>Coisas que não tinha nada haver com o problema</li>
<li>Sugestões pra mudar a estratégia para resolver o problema</li>
<li>Gente falando que o CakePHP só trampa com valores numérico (o que de fato acontece <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> )</li>
</ul>
<h2>O problema</h2>
<p>Então, mexendo no código pra cima e pra baixo (sem conotações sexuais por favor) consegui achar o problema.</p>
<p>No arquivo &nbsp;cake/libs/views/helpers/form.php (cakephp 1.2.5), na linha 1710:</p>
<pre class="brush: php;">if ((!$selectedIsEmpty &amp;&amp; $selected == $name) || ($selectedIsArray &amp;&amp; in_array($name, $selected))) {</pre>
<p>Depois de fuçar e testar um pouco, vi que o problema principal na verdade é um problema com o próprio operador == do PHP: ele trata as operações entre strings e numéricos (<a href="http://php.net/manual/en/language.operators.comparison.php" target="_blank">http://php.net/manual/en/language.operators.comparison.php</a>)&nbsp;de uma forma que gera os seguintes resultados:</p>
<ul>
<li>um valor como 206-1 por exemplo, o helper casava tanto o valor 206-1 (o correto) quanto 206 (string == integer).</li>
<li>um valor como JB01 por exemplo, o helper casava tanto o valor JB01 (o correto) quanto 0 (string == integer).</li>
</ul>
<p>Devido à característica do PHP de resolver qual o tipo da variável em tempo real, ele tenta fazer o casting da variável sempre e acaba gerando resultados não esperados pra gente.</p>
<h2>Solução</h2>
<p>A solução então foi forçar (type casting) as variáveis para serem tratadas como strings. Assim, evitamos que o PHP transforme nossas variáveis em tipos distintos (no nosso caso string e integer) e consequentemente faça a comparação de valores do jeito que precisamos.</p>
<p>A linha 1710 (no <em>cakephp 1.2.5</em> ou 1748 no <em>cakephp 1.3-dev</em>) ficou assim:</p>
<pre class="brush: php;">if ((!$selectedIsEmpty &amp;&amp; (string)$selected == (string)$name) || ($selectedIsArray &amp;&amp; in_array($name, $selected))) {</pre>
<p>Note o type casting sendo feito nas variáveis $selected e $name. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Se alguem conseguir uma solução mais bacana ou encontrou outro bug bizarro do CakePHP, compartilhe! <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Simbora!</strong></p>
<p><strong>Update: <span style="font-weight: normal;">Eu tinha reportado esse erro a algum tempo no track de bugs do CakePHP &nbsp;e hoje vi que já corrigiram isso.&nbsp;</span><span style="font-weight: normal;">Então, quando sair a versão stable do cake 1.3, não precisa mais se preocupar com isso. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </span></strong></p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/11/problema-com-ids-alfanumericos-no-form-input-select-do-cakephp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Agrupando casos de teste no SimpleTest</title>
		<link>http://www.leohackin.com.br/2009/07/agrupando-casos-de-teste-no-simpletest/</link>
		<comments>http://www.leohackin.com.br/2009/07/agrupando-casos-de-teste-no-simpletest/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 02:33:13 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[simpletest]]></category>

		<guid isPermaLink="false">http://leohackin.com.br/blog/?p=162</guid>
		<description><![CDATA[Aloha, Primeiramente, obrigado ao pessoal pelas belas palavras de incentivo e tudo mais: é esse tipo de coisa que nos empolga pra continuar trabalhando e estudando duro. Em nosso post de iniciação no SimpleTest, criamos um caso de teste completo de uma calculadora. Relembrando nossa telinha bonita do caso de teste&#8230; Agora vejamos &#8230; e [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/07/agrupando-casos-de-teste-no-simpletest/&amp;shorturl=http://bit.ly/aDSGQe&amp;title=Agrupando+casos+de+teste+no+SimpleTest&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Aloha,</p>
<p>Primeiramente, obrigado ao pessoal pelas belas palavras de incentivo e tudo mais: é esse tipo de coisa que nos empolga pra continuar trabalhando e estudando duro.</p>
<p>Em nosso post de iniciação no <a href="http://www.simpletest.org" target="_blank">SimpleTest</a>, criamos um caso de teste completo de uma calculadora. Relembrando nossa telinha bonita do caso de teste&#8230;</p>
<p><img class="alignnone size-medium wp-image-164" title="ishot-1" src="http://leohackin.com.br/wp-content/uploads/2009/07/ishot-1-300x155.jpg" alt="ishot-1" width="300" height="155" /></p>
<p>Agora vejamos &#8230; e se por exemplo, tivéssemos <strong>não apenas uma calculadora</strong> em nossa aplicação, mas também uma agenda de compromissos, uma agenda de contatos, um wiki, um mural de recados e &#8230; enfim, se nossa <strong>aplicação fosse composta por N classes</strong> como faríamos para rodar os casos de teste unitários de TODAS AS CLASSES ?</p>
<p>Na TDD, como vimos antes, escrevemos todos os testes antes de começarmos a implementar nossa aplicação em si: quando pensamos &#8220;rodar os testes&#8221; isso se aplica à todas as classes e funcionalidades que possam gerar erros em nossa aplicação.</p>
<p>Ai você: <em>&#8220;Rapaz, vou ter que acessar teste por teste  como fiz com a calculadora? Mamãe, eu tenho 253 casos de uso!!!!&#8221;</em></p>
<p>Imagina só se você executar, URL por URL ou comando por comando, 253 casos de uso. =/</p>
<p>Pensando nisso, a SimpleTest disponibiliza um <strong>recurso de agrupamento </strong>de casos de teste chamado de <strong>Test Suite</strong>. Esse recurso permite agrupar vários casos de testes numa só classe, facilitando e permitindo a execução desses testes com uma só chamada.</p>
<p>Seria como um script de checagem, onde cada item seria um caso de teste:</p>
<p>Checagem do carro</p>
<ol>
<li>Checar Óleo</li>
<li>Checar Rodas</li>
<li>Checar Água Carburador</li>
<li>Checar itens de segurança</li>
</ol>
<p>A test suite funciona exatamente assim, executando cada caso de teste na ordem que você desejar: o &#8220;check list&#8221; roda e no final você tem todos as falhas que ocorreram, separadas por caso de test e método. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Codando!</h2>
<p>Bom, vamos supor que vamos ter uma aplicação composta por 5 classes: ClasseA, ClasseB, ClasseC, ClasseD e ClasseE. Cada uma delas tem suas próprias implementações e vamos ter que fazer casos de testes que testem elas individualmente.</p>
<p>Para ilustrar o funcionamento, vamos escrever um método para todas as classes chamado <span style="text-decoration: underline;"><em>Dizer</em></span>: esse método deverá receber a uma string e retornar &#8220;Estou dizendo &#8221; concatenado com o que você passou como parâmetro. Exemplificando</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$obj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Dizer</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Muito Bacana'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Estou Dizendo Muito Bacana</span></div></td></tr></tbody></table></div>
<p>Vamos botar esse método em todas as classes apenas para simularmos as passagens e não passagens de teste delas. hehhehe</p>
<p>Bom, partindo do pressuposto que você esteja com o SimpleTest instalado e com nossa estrutura de arquivos do artigo de iniciação à ele, vamos escrever o caso de teste da ClasseA que será salvo dentro da nossa pasta <em>tests</em> e terá o nome de <strong>classe_a_test.php</strong>.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'../classes/classe_a.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;&lt;/</span>code<span style="color: #339933;">&gt;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> TestOfClasseA <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">function</span> testDizer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$classea</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClasseA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertIdentical</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$classea</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dizer</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Muito Bacana'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Estou dizendo Muito Bacana'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Relembrando um pouco:</p>
<ul>
<li>Fazemos o include do arquito <em>autorun.php</em> para automatizar nossos testes;</li>
<li>Fazemos o include da classe que vai ser testada</li>
<li>Implementamos a classe de teste iniciando por &#8220;Test&#8221; afim de que a SimpleTest execute-a automaticamente;</li>
<li>Criamos o método <em>testDizer</em> para testar o método dizer da nossa <em>ClasseA</em>;</li>
<li>Fazemos um <em>assertIdentical</em> que executará nosso método dizer passando &#8220;Muito Bacana&#8221; e esperará como resultado algo IDENTICO à &#8220;Estou dizendo Muito Bacana&#8221;;</li>
</ul>
<p>Beleza, agora vamos rodar nosso teste &#8230;</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-170" title="Imagem14" src="http://leohackin.com.br/wp-content/uploads/2009/07/Imagem14.png" alt="Imagem14" width="560" height="341" /></p>
<p>Como era esperado (espero) nosso teste deu pau porque não escrevemos nossa ClasseA ainda em arquivo algum. Então, vamos escrevê-la e salva-la dentro da pasta <em>classes</em> com o nome de <strong>classe_a.php</strong>:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> ClasseA <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">function</span> dizer<span style="color: #009900;">&#40;</span><span style="color: #000088;">$frase</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'Estou dizendo '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$frase</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Agora, vamos rodar novamente nosso teste:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-171" title="Imagem15" src="http://leohackin.com.br/wp-content/uploads/2009/07/Imagem15.png" alt="Imagem15" width="567" height="285" /></p>
<p><strong>Massa demais!</strong> Fizemos novamente um caso de teste. Até ai nenhuma novidade.</p>
<p>Agora o exercício braçal: crie os casos de teste para a ClasseB. ClasseC, ClasseD e ClasseE lembrando que:</p>
<ul>
<li>Classes da aplicação devem ser salvas dentro da pasta classes</li>
<li>Classes dos casos de teste dentro da pasta tests</li>
</ul>
<p>Após a criação delas, faça os testes (jura?) e veja se está tudo ok.</p>
<h2>Criando nossa suite de testes</h2>
<p>Agora que executamos todos os testes de forma separada, vamos junta-los em nossa suite para faze-los todos de uma vez só.</p>
<p>Vamos criar nossa suite de testes no arquivo <strong>all_tests.php</strong> e salva-lo na pasta <em>tests</em> junto com todos os nosses casos de uso.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'classe_a_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'classe_b_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'classe_c_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'classe_d_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'classe_e_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> AllTests <span style="color: #000000; font-weight: bold;">extends</span> TestSuite <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">function</span> AllTests<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">TestSuite</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'All tests'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addTestCase</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> TestOfClasseA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addTestCase</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> TestOfClasseB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addTestCase</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> TestOfClasseC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addTestCase</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> TestOfClasseD<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addTestCase</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> TestOfClasseE<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Explicando nosso script:</p>
<ul>
<li>fazemos o include de <em>simpletest/autorun.php</em> para fazer rodar nossos testes</li>
<li>fazemos os includes de todas os casos de testes que usaremos na suite</li>
<li>criamos uma classe <em>AllTests</em> que extende <em>TestSuite</em>, que por sua vez é a classe que será responsável pelo agrupamento e execução de todos os testes</li>
<li>criamos um método <em>AllTests</em> que fará a execução dos casos de teste</li>
<li>Nomeamos a suite de testes com o nome <em>All tests</em> com o método $this-&gt;TestSuite;</li>
<li>Adicionamos então todos os nossos casos de teste com o método $this-&gt;addTestCase, instanciando o objeto de cada classe de teste</li>
</ul>
<p>Agora, basta rodar:</p>
<p><img class="size-full wp-image-181  alignnone" title="Imagem2" src="http://leohackin.com.br/wp-content/uploads/2009/07/Imagem2.png" alt="Imagem2" width="560" height="274" /></p>
<p><strong>Pronto!</strong> Nossa suite agrupou nossos testes (que eram cinco ao todo, cada um com um método de teste) e executou todos de uma vez. A lógica da suíte é você inserir os testes conforme seu contexto e sua necessidade de agrupamento de testes. Para incluir, basta repetir o procedimento já feito no arquivo da suíte:</p>
<ul>
<li>faça o require_once do arquivo php do caso de teste</li>
<li>inclua o caso de teste com $this-&gt;addTestCase</li>
</ul>
<p><strong>E se algum teste falha-se ?</strong> Vamos fazer o teste da ClasseB falhar. Para isso altere a classe B para para retornar algo que não seja &#8220;Estou dizendo &#8221; mas sim &#8220;Eu vou dizer &#8220;: com isso, nosso teste vai falhar. Após alterar a classeB, rode a suite de testes novamente:</p>
<p><img class="size-full wp-image-183 alignnone" title="Imagem3" src="http://leohackin.com.br/wp-content/uploads/2009/07/Imagem31.png" alt="Imagem3" width="565" height="277" /></p>
<p>Como pode ser visto, nossa suite de testes dá o erro exetamente onde ele aconteceu: no nosso caso, a suite de testes que chamamos de All tests reportou o erro do caso de teste TestOfClasseB no método testDizer. Maneirasso não ?</p>
<p>Nossa suite mostra todas as falhas por caso de teste. Simples e rápido.</p>
<h2>E vamos às considerações</h2>
<p>A forma que fizemos a construção da nossa suite de testes está diferente da forma em que o próprio site da SimpleTest (<a href="http://www.simpletest.org/en/start-testing.html" target="_blank">http://www.simpletest.org/en/start-testing.html</a>) mostra em sua página inicial no Quick Start dele, que está diferente do <a href="http://www.simpletest.org/en/group_test_tutorial.html" target="_blank">link que deveria ser a mesma explicação mais detalhada</a>, mas não é. Se olharmos o script de test suite do quick start teremos, aplicando ao nosso exemplo, teríamos:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> AllTests <span style="color: #000000; font-weight: bold;">extends</span> TestSuite <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">function</span> AllTests<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">TestSuite</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'All tests'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addFile</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'classe_a_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//... outros casos de teste ...</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Concerteza é um jeito mais prático: ao invés de fazer-mos os includes dos casos de testes e fazermos os instanciamentos dos mesmos no addTestCase, requerendo mais programação, simplesmente podemos incluir o teste com um addFile. E isso realmente funciona. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Mas infelizmente não sem algumas adaptações no código.</p>
<p>Se quiser re-escrever sua suite de testes nesse formato, se atente ao fato que o SimpleTest aparentemente trabalha com a suite de testes acessando os caminhos absolutos dos arquivos e se perde quando referenciamos nossos arquivos, mesmo que eles estejam na mesma pasta tests. Para contornar isso, coloque a inclusão do arquivo de classe no caso de testes e a referência ao arquivo do caso de teste na suite com seus caminhos absolutos. Vamos isso na classeA por exemplo:</p>
<p>Na classe_a_test.php teríamos:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'DOCUMENT_ROOT'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/app_tdd/classes/classe_a.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>E na nossa suite all_tests.php seria re-escrita como:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> AllTests <span style="color: #000000; font-weight: bold;">extends</span> TestSuite <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">function</span> AllTests<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">TestSuite</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'All tests'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addFile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'DOCUMENT_ROOT'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/app_tdd/tests/classe_a_test.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Espero que tenham gostado e no próximo post falaremos um pouco sobre MockObjetcs. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Até lá.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/07/agrupando-casos-de-teste-no-simpletest/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Léo Hackin agora no iMasters</title>
		<link>http://www.leohackin.com.br/2009/07/leo-hackin-agora-no-imasters/</link>
		<comments>http://www.leohackin.com.br/2009/07/leo-hackin-agora-no-imasters/#comments</comments>
		<pubDate>Fri, 17 Jul 2009 20:32:58 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Pessoal]]></category>
		<category><![CDATA[artigos]]></category>
		<category><![CDATA[imasters]]></category>
		<category><![CDATA[leohackin]]></category>

		<guid isPermaLink="false">http://leohackin.com.br/blog/?p=167</guid>
		<description><![CDATA[Olá a todos, Post rápido sobre uma novidade bacana e que me deixou bem feliz essa semana: fui convidado a ser um articulista no portal iMasters. O primeiro artigo a ser publicado lá foi o Iniciando com o SimpleTest e a idéia é ter alguns dos posts que coloco aqui sendo publicados lá. Agradeço à [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/07/leo-hackin-agora-no-imasters/&amp;title=L%C3%A9o+Hackin+agora+no+iMasters&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Olá a todos,</p>
<p>Post rápido sobre uma novidade bacana e que me deixou bem feliz essa semana: fui convidado a ser um articulista no <a href="http://imasters.uol.com.br/" target="_blank">portal iMasters</a>. O primeiro artigo a ser publicado lá foi o <a href="http://imasters.uol.com.br/artigo/13569/php/iniciando_com_o_simpletest/" target="_blank">Iniciando com o SimpleTest</a> e a idéia é ter alguns dos posts que coloco aqui sendo publicados lá.</p>
<p>Agradeço à equipe da iMasters pela honra e espero que possamos distribuir conteúdo legal e relevante pelos próximos tempos por ai.</p>
<p>Simbora! <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/07/leo-hackin-agora-no-imasters/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Iniciando com o SimpleTest</title>
		<link>http://www.leohackin.com.br/2009/07/iniciando-com-o-simpletest/</link>
		<comments>http://www.leohackin.com.br/2009/07/iniciando-com-o-simpletest/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 20:11:24 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[simpletest]]></category>

		<guid isPermaLink="false">http://leohackin.com.br/blog/?p=119</guid>
		<description><![CDATA[Salve people, Vamos iniciar hoje uma pequena jornada à terras que possivelmente muita gente só viu/leu em sites especializados e muito pouco comentadas em PHP: a terra do desenvolvimento orientado a testes, ou TDD. Se você não sabe ou nem faz idéia do que é TDD, dê uma procura no Google pois existem dezenas de [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/07/iniciando-com-o-simpletest/&amp;shorturl=http://bit.ly/5e07yU&amp;title=Iniciando+com+o+SimpleTest&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Salve people,</p>
<p>Vamos iniciar hoje uma pequena jornada à terras que possivelmente muita gente só viu/leu em sites especializados e muito pouco comentadas em PHP: a terra do desenvolvimento orientado a testes, ou <strong>TDD</strong>.</p>
<p>Se você não sabe ou nem faz idéia do que é TDD, dê uma procura no <strong>Google</strong> pois existem dezenas de sites muito bacanas destilando idéias e tudo mais sobre isso.</p>
<p><em>Em poucas palavras, </em><strong><em>TDD</em></strong><em> (Test Driven Development) é um técnica de desenvolvimento de software que nos diz que devemos escrever os testes antes de escrever o código da aplicação propriamente dito.</em></p>
<p>Inicialmente isso parece meio louco: afinal, você sempre testa DEPOIS de escrever seus programas ou durante, enquanto debuga tudo, correto ? Mas com o passar do tempo, a verdadeira natureza e vantagem do TDD, quando aplicada corretamente, se faz presente.</p>
<p>Você se torna capaz de antecipar a detecção e correção de várias falhas, reduzindo dramaticamente o tempo gasto com correções em cima de implementações muito complexas já praticamente no final do seu cronograma.</p>
<p>Hoje em dia, existem várias frameworks que auxiliam nessa tarefa de escrever testes. O foco aqui é algo que poucos sites (principalmente em português) abordam de forma prática que é o uso da <strong><a href="http://www.simpletest.org" target="_blank">SimpleTest</a></strong>, uma framework para testes unitários que vem ganhando o espaço antes ocupado pelo <a href="http://www.phpunit.de/" target="_blank">PHPUnit</a>.</p>
<p>No decorrer dos próximos posts sobre o SimpleTest, você poderá adquirir um pouco de conhecimento que poderá ser útil em seus futuros projetos. Então, vamos simbora.</p>
<h2>Instalando o SimpleTest</h2>
<p>A instalação do SimpleTest em si é muito fácil.</p>
<ol>
<li>Baixe a versão mais atual do SimpleTest no site <a href="http://www.simpletest.org" target="_blank">http://www.simpletest.org</a> (a versão que usaremos nessa sequência de tutoriais é a 1.0.1). A framework é composta por uma pasta simples;</li>
<li>Descompacte o arquivo dentro de sua aplicação. Para fins de organização, vamos criar uma pasta &#8220;tests&#8221; na raíz de nossa aplicação e descompactar o zip/tar do SimpleTest lá: ao descompactar você verá uma pasta chamada <em>simpletest</em> sendo criada.</li>
</ol>
<p>Em tese, nossa aplicação pode ter qualquer estrutura de diretórios. O SimpleTest funciona tanto com functions como com classes. Vamos abordar o uso de classes, dado que o TDD é amplamente usado em sua maioria em soluções OO (Orientadas a Objeto) e acho que já passou da hora da comunidade PHP pensar OO. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Partindo desse pressuposto, vamos criar a pasta &#8220;<em><strong>classes</strong></em>&#8221; na raíz de nossa aplicação: lá iremos botar todas as nossas classes que serão usadas nos testes.</p>
<p>Teremos então, uma estrutura de arquivos como abaixo:</p>
<p><img class="alignnone size-full wp-image-120" title="imagem5" src="http://leohackin.com.br/wp-content/uploads/2009/07/imagem5.png" alt="imagem5" width="231" height="101" /></p>
<p>A pasta <strong>app_tdd </strong>é a pasta onde está nossa aplicação: uma pasta criada dentro do meu htdocs (raíz do Apache).</p>
<p>Se o seu servidor web estiver instalado com configurações padrão, provavelmente você poderá acessar usando: <em><a href="http://localhost/app_tdd" target="_blank">http://localhost/app_tdd</a></em></p>
<h2><strong>Nosso problema: uma calculadora</strong></h2>
<p>Com o SimpleTest &#8220;instalado&#8221; em nossa aplicação e nossa estrutura de diretórios resolvida, vamos escrever nosso primeiro caso de teste.</p>
<p>O cenário de nossa aplicação é uma <strong>calculadora</strong>: nossa calculadora conseguirá efetuar apenas a operação de soma.</p>
<p>Com uma análise rápida do problema, já nos vem à cabeça que:</p>
<ul>
<li>Uma classe chamada &#8220;Calculadora&#8221; com um método chamado &#8220;soma&#8221;;</li>
<li>Nosso método soma recebendo dois números</li>
<li>Nosso método retornando o valor da soma entre os dois números</li>
</ul>
<p><strong>Nossa abordagem não TDD seria</strong>: vamos fazer a classe, implementar o método e depois testa-lo em uma página teste. Correto ? Num primeiro momento isso seria ótimo: afinal, o código e complexidade das classes inicialmente são lindos.</p>
<p>Mas <strong>imagine agora sua aplicação crescendo e crescendo</strong>: classes extendendo e usando outras classes. Você extende a Calculadora, outra classe utiliza o método soma e você vai testando apenas &#8220;o que vem depois&#8221;.</p>
<p>Num dado momento, <strong>você tem um resultado incorreto de soma</strong>: uma entrada incorreta de parâmetros, um deles ser uma letra e não um número, termos uma passagem de um objeto ao invés de um número propriamente dito &#8230; <strong>De quem é a culpa ?</strong> Da classe nova, que esqueceu de filtrar a entrada de parametros ? Do designer, que esqueceu de limitar a entrada dos valores no form para apenas números ? Do outro programador, que foi descuidado e não validou se os dados passados eram realmente números antes de chamar a soma ?</p>
<p><strong>Enfim, temos N cenários onde a detecção do erro pode ser muito custosa</strong>, seja pelo método para encontra-lo (que varia do debug minucioso ao &#8220;achismo&#8221;) e/ou pelo custo em termos de tempo para concerta-lo. Tudo isso pode gerar um custo/prejuízo que seria reduzido com a implementação do pensando TDD.</p>
<h2>Pensando primeiro em testes</h2>
<p><strong>Mentalize</strong>: <em>&#8220;Quais as situações que podem quebrar meu método soma? Se acontecer, como devo tratar esse erro ?&#8221;</em></p>
<p>Com base nesse pensamento, podemos deduzir:</p>
<ul>
<li>Para somar, nossa calculadora terá que receber sempre <strong>dois números</strong>;</li>
<li>A soma sempre ocorre entre dois números, nunca entre letras, objetos ou qualquer coisa que não seja exatamente um número;</li>
<li>Se algo der erro, devo retornar falso;</li>
</ul>
<p><strong>Interessante!</strong> Não implementamos nenhuma linha de nossa solução e já sabemos:</p>
<ul>
<li>Que vamos precisar de uma classe (Calculadora) com um método de soma;</li>
<li>Sabemos que o método deverá receber dois parâmetros que deverão ser sempre números;</li>
<li>Que se for passado qualquer coisa que não sejam dois números, eu devo retornar falso;</li>
</ul>
<p><strong>Bom, então vamos implementar a classe ?</strong> Não, pequeno gafanhoto: <strong>vamos implementar primeiro os testes</strong>, porque é com base neles que vamos ter certeza que nossa classe se comportará exatamente como pensamos que ela deve se comportar sob os mais diversos cenários.</p>
<h2>Escrevendo nosso primeiro teste</h2>
<p>Implementar um teste com SimpleTest é, como o nome já diz, &#8220;simples&#8221;.</p>
<p>Vamos criar todos os nossos testes dentro da pasta <em><span style="text-decoration: underline;">tests</span></em>. Para cada classe que tivermos que testar, vamos criar um caso de teste (unit test case) que será representado em um arquivo php.</p>
<p>Então, nosso primeiro caso de teste será o <strong>calculadora_test.php</strong>. O nome do arquivo não tem um padrão de nomenclatura, mas por convenção usa-se sempre<em> nomedaclasse</em><em>_test.php</em>.</p>
<p><strong>calculadora.php -&gt; calculadora_test.php</strong></p>
<p>A estrutura inicial do nosso arquivo calculadora_test.php será a seguinte:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'../classes/calculadora.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> TestOfCalculadora <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">// os testes vão aqui ;)</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p><strong>Pronto!</strong> Nosso caso de teste da classe Calculadora está feito. Para testa-lo, vamos apontar o browser para <a href="http://localhost/app_tdd/tests/calculadora_test.php" target="_blank">http://localhost/app_tdd/tests/calculadora_test.php</a>. O resultado será:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Warning<span style="color: #339933;">:</span> <span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">../</span>classes<span style="color: #339933;">/</span>calculadora<span style="color: #339933;">.</span>php<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #339933;">.</span>require<span style="color: #339933;">-</span>once<span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> failed to open stream<span style="color: #339933;">:</span> No such <a href="http://www.php.net/file"><span style="color: #990000;">file</span></a> or directory in <span style="color: #339933;">/</span>Applications<span style="color: #339933;">/</span>MAMP<span style="color: #339933;">/</span>htdocs<span style="color: #339933;">/</span>app_tdd<span style="color: #339933;">/</span>tests<span style="color: #339933;">/</span>calculadora_test<span style="color: #339933;">.</span>php on line 4<br />
<br />
Fatal error<span style="color: #339933;">:</span> <span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #339933;">.</span><span style="color: #b1b100;">require</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> Failed opening required <span style="color: #0000ff;">'../classes/calculadora.php'</span> <span style="color: #009900;">&#40;</span>include_path<span style="color: #339933;">=</span><span style="color: #0000ff;">'.:/Applications/MAMP/bin/php5/lib/php:/Users/leohackin/PEAR'</span><span style="color: #009900;">&#41;</span> in <span style="color: #339933;">/</span>Applications<span style="color: #339933;">/</span>MAMP<span style="color: #339933;">/</span>htdocs<span style="color: #339933;">/</span>app_tdd<span style="color: #339933;">/</span>tests<span style="color: #339933;">/</span>calculadora_test<span style="color: #339933;">.</span>php on line <span style="color: #cc66cc;">4</span></div></td></tr></tbody></table></div>
<p><strong>Ops! </strong>Não criamos nossa classe ainda, por isso obtemos esse erro. Quando disse que escrevemos testes antes de implementar nossa lógica, estava falando sério. =)</p>
<p>Vamos criar nossa classe Calculadora então.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> Calculadora <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">function</span> soma<span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #339933;">,</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Legal, agora vamos acessar nosso caso de teste denovo.</p>
<p><img class="alignnone size-full wp-image-146" title="imagem6" src="http://leohackin.com.br/wp-content/uploads/2009/07/imagem6.png" alt="imagem6" width="458" height="240" /></p>
<p><strong>Uhu! Funfou!!!</strong></p>
<p>Analisando o código:</p>
<ul>
<li>fazemos o include de dois arquivos:
<ul>
<li>o arquivo autorun.php é o arquivo que faz a &#8220;mágica&#8221; acontecer: é ele quem roda os testes e exibe os resultados, portanto deverá sempre estar no seu caso de teste;</li>
</ul>
<ul>
<li>o outro arquivo é a classe que desejamos usar no teste, no caso calculadora.php</li>
</ul>
</li>
<li>Criamos uma classe chamada <span style="text-decoration: underline;"><em>TestOfCalculadora</em></span> extendendo <em><span style="text-decoration: underline;">UnitTestCase</span></em>, que será a classe que o SimpleTest usará para fazer o teste. <strong>É obrigatório que a classe inicie com o nome &#8220;test&#8221; para que o SimpleTest execute automaticamente</strong> a mesma como um caso de teste. Existe uma forma de faze-lo sem iniciar o nome com &#8220;test&#8221;, mas isso não vem ao caso agora.</li>
</ul>
<p><strong>Maneiro né ?</strong> Mas como puderam notar, <strong>nosso caso de teste não testa nada ainda</strong>. Hahahah</p>
<p><strong>Vamos adicionar agora um teste</strong>: o teste vai verificar se a soma está realmente &#8220;somando&#8221; dois números. Para isso, devemos adicionar um método à nossa classe de testes. Vamos chamar esse teste de &#8220;<em><span style="text-decoration: underline;">testSomaDoisNumerosInteiros</span></em>&#8220;, onde vamos passar dois números inteiros esperando que a soma deles esteja correta.</p>
<p>Usar nomes grandes assim no nome do método são uma boa prática, já que deixam os testes mais legíveis na hora de rodar o caso de teste.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'simpletest/autorun.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'../classes/calculadora.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> TestOfCalculadora <span style="color: #000000; font-weight: bold;">extends</span> UnitTestCase <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> testSomaDoisNumerosInteiros<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #000088;">$calculadora</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Calculadora<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$calculadora</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soma</span><span style="color: #009900;">&#40;</span>1<span style="color: #339933;">,</span>1<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Como visto, temos nosso método <em><span style="text-decoration: underline;">testSomaDoisNumerosInteiros</span></em> que instancia nossa <span style="text-decoration: underline;">classe </span><em><span style="text-decoration: underline;">Calculadora</span></em> e depois executa um método chamado <em><span style="text-decoration: underline;">assertEqual</span></em>. Esse método é o responsável por testar nossa soma. Ele significa:</p>
<p><em>Verifique se a chamada </em><span style="text-decoration: underline;"><em>$calculadora-&gt;soma(1,1)</em></span><em> retornará um resultado </em><strong><em>igual à 2</em></strong></p>
<p>Se a chamada retornar qualquer coisa diferente de dois, nosso teste irá falhar, indentificando que algo de podre está acontecendo em nosso método soma.</p>
<p>Se rodarmos esse script teremos enfim:</p>
<p><img class="alignnone size-full wp-image-149" style="border: 1px solid black;" title="imagem1" src="http://leohackin.com.br/wp-content/uploads/2009/07/imagem1.png" alt="imagem1" width="829" height="273" /></p>
<p><strong>Tivemos uma falha</strong>. Traduzindo a mensagem de forma prática:</p>
<p><em>O seu teste testSomeDoisNumerosInteiros, do caso de teste TestOfCalculadora, falhou porque NULL (que foi retornado pela chamada ao nosso método soma) não é igual a 2 (que seria nossa resposta esperada).</em></p>
<p>A resposta para isso é que ainda nem implementamos nosso método soma. Mas vejamos que nesse ponto já sabemos exatamente como deve ser comportar nosso método para o funcionamento com dois números. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Vamos implementar nossa classe então:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> Calculadora <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">function</span> soma<span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #339933;">,</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #000088;">$a</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$b</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Com nosso método agora implementado, vamos executar nosso caso de teste denovo.</p>
<p><img class="alignnone size-full wp-image-150" title="imagem2" src="http://leohackin.com.br/wp-content/uploads/2009/07/imagem2.png" alt="imagem2" width="497" height="245" /></p>
<p><strong>Agora sim!</strong> Temos um caso de teste funcional que testa uma classe implementada. Parabéns por chegar até aqui.</p>
<p>Nesse ponto, já temos conhecimento suficiente para escrever vários casos de teste para nossas classes<strong>. Um caso de teste pode conter vários testes diferentes: cada teste é feito através de um método da classe do caso de teste.</strong></p>
<p>Revisando aquelas possibilidades de cenário que poderiam &#8220;quebrar&#8221; nossa calculadora, já testamos se a soma está correta. Agora, podemos testar as possibilidades que podem gerar um erro na calculadora.</p>
<p>Uma delas é se passarmos letras no lugar de números: haviamos combinado que nessa situação, devolveriamos falso para o resultado, correto ? Então, vamos escrever o teste: vamos chama-lo de &#8220;<em><span style="text-decoration: underline;">testSomaNaoNumeros</span></em>&#8220;:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> testSomaNaoNumeros<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #000088;">$calculadora</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Calculadora<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEqual</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$calculadora</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soma</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'A'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Adicionamos essa função à nossa classe. Rodamos nosso teste novamente e &#8230;</p>
<p><img class="alignnone size-full wp-image-151" title="imagem3" src="http://leohackin.com.br/wp-content/uploads/2009/07/imagem3.png" alt="imagem3" width="860" height="284" /></p>
<p><strong>Previsivelmente</strong>, temos um erro pois nosso método soma ainda não verifica se os parâmetros recebidos são números válidos. Ai você irá pensar:</p>
<p><em><span style="text-decoration: underline;">Mas eu vou escrevendo os testes e vou implementando toda a minha lógica de negócio ao mesmo tempo ?</span></em></p>
<p>A TDD tem uma característica bacana, que anda de mãos dados ao <strong><a href="http://www.agence.com.br/refactoring-engenharia-de-software.php" target="_blank">refactoring</a></strong>: a TDD nos diz que devemos SIM escrever os testes primeiro e fazer as classes &#8220;passarem no teste&#8221; usando o mínimo de código possível: se a lógica for complexa, retorne uma resposta &#8220;hardcode&#8221; para &#8220;enganar&#8221; o teste e depois faça o refactory do código.</p>
<p>O refactory deve ser feito apenas depois de todos os testes serem feitos, pois nesse ponto você terá certeza de como o funcionamnento de sua classe atenderá a todos as respostas que são requisitadas nos testes como &#8220;corretos&#8221;.</p>
<p>Pensando nisso, vamos fazer nosso método soma &#8220;passar&#8221; no teste:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> Calculadora <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">function</span> soma<span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #339933;">,</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_int"><span style="color: #990000;">is_int</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.php.net/is_int"><span style="color: #990000;">is_int</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #000088;">$a</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$b</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Agora, vamos rodar nosso teste.</p>
<p><img class="alignnone size-full wp-image-152" style="border: 1px solid black;" title="imagem4" src="http://leohackin.com.br/wp-content/uploads/2009/07/imagem4.png" alt="imagem4" width="497" height="253" /></p>
<p><strong>Blz!</strong> Nosso teste passou, mas testamos apenas se os valores são inteiros e se forem, efetuamos a soma. Se não forem, a gente retorna false, como nosso teste pediu. Podemos depois refatorar isso: verificar se o valor é uma string com um número dentro e por ai vai.</p>
<h2>Finalizando</h2>
<p>Você pode estar se perguntando: <em>&#8220;Uai, mas podemos ter muito mais ocasiões que podem quebrar a soma! Podemos também extender algumas funcionalidades e exibir mensagens de erro&#8221;.</em></p>
<p>Tivemos uma amostra do que é o SimpleTest em seu cenário mais simples: apesar do tamanho do post, o conceito e a aplicação são bem simples como puderam ver.</p>
<p>Além do assetEqual, a SimpleTest tem um <a href="http://www.simpletest.org/en/unit_test_documentation.html" target="_blank">set de ações enorme de validações</a>, além de recursos mais avançados, como suites, mocks e web tests que veremos em breve.</p>
<p>Crie outras classes, pense nos testes, escreva seus casos de teste e vá executando: com a prática isso vai ficar tão automático que o ganho com a diminuição dos testes e bugs no final da aplicação vão ser notórios.</p>
<p><strong>Testes nos tornam programadores melhores. <span style="text-decoration: underline;">Pense nisso.</span></strong></p>
<p>Algumas coisas para se pensar quando começar a abordar isso:</p>
<ul>
<li> Não precisamos escrever TODOS os testes: é completamente normal se esquecermos algo ou houver alguma necessidade de mudança de negócio do cliente que nos fará escrever novos testes ou re-escrever os existentes. Tenha em mente que o TDD é para ajudar e não para ser mais uma fase carrancuda e intransponível no desenvolvimento;</li>
<li>A análise para chegar aos casos de teste faz bem ao início do projeto: com essa abordagem, você pode fazer perguntas ao cliente (e ele a você) sobre algumas coisas que possívelmente só apareceriam no final do projeto gerando assim muito re-trabalho;</li>
</ul>
<p>Bom, por enquanto é isso pessoal. No próximo post falaremos um pouco sobre agrupamentos de teste e partir para um exemplo mais complexo. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Espero que tenham gostado do post.</p>
<p>Simbora! <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/07/iniciando-com-o-simpletest/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Dica de chave do model no CakePHP</title>
		<link>http://www.leohackin.com.br/2009/06/dicas-de-chave-do-model-no-cakephp/</link>
		<comments>http://www.leohackin.com.br/2009/06/dicas-de-chave-do-model-no-cakephp/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 00:14:21 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[dica]]></category>

		<guid isPermaLink="false">http://leohackin.com.br/blog/?p=108</guid>
		<description><![CDATA[Estava rascunhando algumas coisas e fazendo umas melhorias num sistema na Giran, quando lembrei de duas perguntas que haviam sido feitas no 1º Workshop PHP-ES sobre CakePHP. Aproveitando que lembrei delas mas não tinha a resposta na ponta da língua, ai vai uma dica sobre chaves primárias para ser feita no model de sua app. [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/06/dicas-de-chave-do-model-no-cakephp/&amp;title=Dica+de+chave+do+model+no+CakePHP&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>Estava rascunhando algumas coisas e fazendo umas melhorias num sistema na <a href="http://www.giran.com.br" target="_blank">Giran</a>, quando lembrei de duas perguntas que haviam sido feitas no 1º Workshop PHP-ES sobre <a href="http://cakephp.org" target="_blank">CakePHP</a>.</p>
<p>Aproveitando que lembrei delas mas não tinha a resposta na ponta da língua, ai vai uma dica sobre chaves primárias para ser feita no model de sua app. Isso está explicito no Cookbook, mas não muito à mão para quem está começando ou nos bilhares de screencasts existentes. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Modificando a chave primária ID</strong></p>
<p>Se você está portando uma base de dados que já exista e que não segue a nomenclatura padrão do CakePHP, onde a chave primária da tabela é sempre chamada por <strong>id</strong>, utilize o atributo <strong>primaryKey</strong> do seu model para usar outro campo.</p>
<pre lang="php">class Cliente extends AppModel {

var primaryKey = "CdCliente";

}</pre>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/06/dicas-de-chave-do-model-no-cakephp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convite 1º Workshop PHP-ES</title>
		<link>http://www.leohackin.com.br/2009/05/convite-1%c2%ba-workshop-php-es/</link>
		<comments>http://www.leohackin.com.br/2009/05/convite-1%c2%ba-workshop-php-es/#comments</comments>
		<pubDate>Thu, 14 May 2009 14:28:35 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tecnologia]]></category>
		<category><![CDATA[eventos]]></category>
		<category><![CDATA[espiritosanto]]></category>
		<category><![CDATA[phpes]]></category>

		<guid isPermaLink="false">http://leohackin.com.br/blog/?p=94</guid>
		<description><![CDATA[É com muita alegria que a comunidade PHP do Espírito Santo &#8211; PHP-ES &#8211; convida a toda a comunidade capixaba de desenvolvedores, gerentes de TI, estudantes, curiosos e a quem interessar para participar do 1º Workshop PHP-ES. O Workshop PHP-ES é um evento regional totalmente dedicado à divulgação e disseminação da linguagem de programação PHP [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/05/convite-1%c2%ba-workshop-php-es/&amp;title=Convite+1%C2%BA+Workshop+PHP-ES&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p>É com muita alegria que a comunidade <a href="http://www.php-espiritosanto.com.br/" target="_blank">PHP do Espírito Santo &#8211; PHP-ES</a> &#8211; convida a toda a comunidade capixaba de desenvolvedores, gerentes de TI, estudantes, curiosos e a quem interessar para participar do <a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/" target="_blank">1º Workshop PHP-ES</a>.</p>
<p>O Workshop PHP-ES é um evento regional totalmente dedicado à divulgação e disseminação da linguagem de programação <a href="http://www.php.net/" target="_blank">PHP</a> no ES. O evento acontece pela primeira vez, fruto da vontade dos usuários de grupo de PHP?ES em ter um evento exclusivo sobre PHP, afim de promover o interesse regional pela linguagem.</p>
<p>O Workshop PHP-ES será realizado no dia 30/05/2009, sábado, no período de 13h até as 18h no Anfiteatro da <a href="http://www.uvv.br/" target="_blank">UVV &#8211; Centro Universitário de Vila Velha</a> &#8211; Campus Boa Vista.</p>
<div>
<p>As inscrições são <strong>GRATUITAS</strong> e <strong>OBRIGATÓRIAS,</strong> pois o número de vagas é limitado, e dão direito ao recebimento do certificado de participação e aos SORTEIOS de vários brindes. Convocamos todos os participantes a trazerem <strong>1kg de alimento não-perecível</strong> que será doado a uma instituição.</div>
<div>Segue a grade do evento:</p>
<p>13:00h &#8211; 13:40h &#8211; Credenciamento<br />
13:40h &#8211; 13:50h &#8211; Abertura<br />
13:50h &#8211; 14:50h &#8211; Nadando em Dinheiro com AJAX e jQuery [Reinaldo de Souza "JuniorZ"]<br />
15:00h &#8211; 16:00h &#8211; Desenvolvimento ágil com Smarty [Gerson Novais]<br />
16:00h &#8211; 16:30h &#8211; Intervalo<br />
16:30h &#8211; 17:30h &#8211; CakePHP [Leonardo "Hackin" Freire]<br />
17:30h &#8211; Fechamento</p></div>
<div>Patrocínio: <a href="http://www.spiritlinux.com.br/" target="_blank">Spirit Linux Professional Linux Services</a> e <a href="http://www.giran.com.br/" target="_blank">Giran Soluções e Ensino</a><br />
Apoio: <a href="http://www.uvv.br/cursos/info_curso.asp?id=5&amp;tpcurso=1" target="_blank">Cursos de Ciência da Computação</a> e <a href="http://www.uvv.br/cursos/info_curso.asp?id=14&amp;tpcurso=1" target="_blank">Sistemas de Informação</a> da UVV , <a href="http://www.gbcreative.com.br" target="_blank">GB Creative &#8211; Design, Publicidade e Propaganda</a></div>
<div></div>
<div><strong>Informações e inscrições podem ser feitas em: <a href="http://www.php-espiritosanto.com.br/" target="_blank">http://www.php-espiritosanto.com.br/</a></strong></div>
<p>Equipe organizadora do Workshop PHP-ES</p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/05/convite-1%c2%ba-workshop-php-es/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>1º Workshop PHP-ES</title>
		<link>http://www.leohackin.com.br/2009/04/1%c2%ba-workshop-php-es/</link>
		<comments>http://www.leohackin.com.br/2009/04/1%c2%ba-workshop-php-es/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 00:49:37 +0000</pubDate>
		<dc:creator>Léo Hackin</dc:creator>
				<category><![CDATA[Ahn?]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tecnologia]]></category>
		<category><![CDATA[evento]]></category>
		<category><![CDATA[phpes]]></category>

		<guid isPermaLink="false">http://leohackin.com.br/blog/?p=85</guid>
		<description><![CDATA[Salve pessoal, É com prazer que informo as primeiras informações sobre o 1º encontro do grupo de usuários PHP do Espírito Santo, vulgo 1º Workshop PHP-ES. Esse evento vem sendo idealizado a algum tempo pela galera do grupo e finalmente saiu do papel graças ao empenho de todos (em especial do amigo Almir M3nd3s), com [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_jade" style="float: right;margin-left: 0.75em;"><script type="text/javascript" src="http://button.topsy.com/widget/retweet-small?url=http://www.leohackin.com.br/2009/04/1%c2%ba-workshop-php-es/&amp;title=1%C2%BA+Workshop+PHP-ES&amp;theme=jade&amp;order=count,retweet,badge&amp;txt_tweet=tuit&amp;txt_retweet=retuit"></script></div><p><img class="alignright size-full wp-image-88" title="homepage" src="http://leohackin.com.br/wp-content/uploads/2009/04/homepage.jpg" alt="homepage" width="205" height="136" />Salve pessoal,</p>
<p>É com prazer que informo as primeiras informações sobre o 1º encontro do grupo de usuários PHP do Espírito Santo, vulgo <strong>1º Workshop PHP-ES</strong>. Esse evento vem sendo idealizado a algum tempo pela galera do grupo e finalmente saiu do papel graças ao empenho de todos (em especial do amigo Almir M3nd3s), com N threads no grupo de discussão e por ai vai.</p>
<p><span id="more-85"></span></p>
<p>O evento será realizado no dia <strong>30 de maio, no Anfiteatro da UVV, a partir das 13:00</strong>. Isso vai cair num <strong>sábado</strong> e vai ser bem tranquilo. O <strong>ingresso será 1 Kg de alimento não perecível</strong>, que será doado para uma instituição de caridade que já está quase definida.</p>
<p>A idéia inicial do evento é apresentar algumas palestras relacionadas ao PHP e tecnologias de entorno, como por exemplo o jQuery, que faz parte do desenvolvimento web e está fortemente relacionada ao nosso mundo PHP. <img src='http://www.leohackin.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Com base nesse pensamento, vão haver três palestras bem legais. Para simplificar, segue a programação prevista:</p>
<p>13:00h &#8211; 13:40h &#8211; Credenciamento<br />
13:40h &#8211; 13:50h &#8211; Abertura<br />
13:50h &#8211; 14:50h - <a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/#palestra1"><strong>Nadando em Dinheiro com <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> e jQuery</strong></a> [<a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/#reinaldo"><em>Reinaldo de Souza "JuniorZ"</em></a>]<br />
15:00h &#8211; 16:00h - <a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/#palestra2"><strong>Desenvolvimento ágil com Smarty</strong></a> [<a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/#gerson"><em>Gerson Novais</em></a>]<br />
16:00h &#8211; 16:30h &#8211; Intervalo<br />
16:30h &#8211; 17:30h - <a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/#palestra3"><strong>CakePHP</strong></a> [<a href="http://www.php-espiritosanto.com.br/wp/eventos/workshop-php-es/#leonardo"><em>Leonardo "Hackin" Freire</em></a>]<br />
17:30h &#8211; Fechamento</p>
<p>Durante o evento, serão sorteados alguns brindes e no ato da inscrição cada um receberá uma caneta e, muito possivelmente, um bloco de papel para rascunhar o que quiserem.</p>
<p>Mais detalhes serão dados com o tempo, pois faltam fechar os patrocinadores e acertar algumas coisas. Para mais informações, cadastrem-se em nosso grupo (<a href="http://br.groups.yahoo.com/group/php-espiritosanto/">http://br.groups.yahoo.com/group/php-espiritosanto/</a>) ou no blog do grupo (<a href="http://www.php-espiritosanto.com.br/wp/workshop-php-es/" target="_blank">http://www.php-espiritosanto.com.br/wp/workshop-php-es/</a>).</p>
<p><strong>Contamos com a presença de todos.  =)</strong></p>

]]></content:encoded>
			<wfw:commentRss>http://www.leohackin.com.br/2009/04/1%c2%ba-workshop-php-es/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
