dez 7 2008

PHPUnit series: Nomeando os testes

Nomeando os testes? E isso é relevante? Eu não sei para você mas isso faz total diferença.

Um teste chamado ValorVerdadeiro é diferente de um teste chamado ValorDaVariavelFooDeveSerVerdadeiro, a diferença não está no fato do código ser diferente, mas na percepção que temos ao ler isso. Ao ler ValorVerdadeiro o nome desse teste oculta o que ele realmente quer fazer. E nós não queremos ocultar nenhum teste, ou omitir o que os testes querem mostrar ;)

A nomeação de um teste não passa só por isso, as vezes, quando não sabemos nem o que testar, quando nomeamos um teste de maneira correta temos um gancho para sabermos o que queremos com esse teste e como vamos implementá-los.

E o nome do teste deve ser claro para que qualquer um possa saber o que você está querendo, em times mistos e com várias pessoas a integração fica bem maior. Ou para um novo desenvolvedor na empresa/projeto, você não precise de imediato explicar para ele todos detalhes do projeto, mas pode mostrar e pedir para ele ler os testes e tentar entender o que está acontecendo ali, é bem mais produtivo. (Se ele for bom, ele pega boa parte da lógica do sistema ao ver os testes).

Coloquem nomes legais e façam uma identidade unica para cada teste, isso pode salvar a pele de vocês um dia, quando um dos testes resolver não funcionar! Você de cara já vai entender o contexto do teste.


dez 3 2008

PHPUnit series: Por que desenvolver orientado a testes?

Eu twittei um dia desses se eles leriam sobre uma série de artigos sobre o PHPUnit e a resposta foi SIM :)

Eu já escrevi aqui sobre o PHPUnit e até uma vez eu disse que ia fazer uma série, comecei como fazer a instalação, aqui tem relatos tanto de windows como de linux, ensinei como integrar o PHPUnit ao CodeIgniter sem o uso de mocks e stubs (por falta de experiência, não é legal) e mostrei como fazer alguma coisa com o PHPUnit.

Mas o que quero mostrar nessa série é algo real, casos reais que eu enfrentei e como eu testei.

Eu vou explanar falando sobre o cake, um projeto estou trabalhando :)

O que eu realmente aprendi com o PHPUnit é que ele não é um simples framework de testes, na realidade, aprendi com todos os tipos de testes que já fiz (RSpec, Test::Unit, Cucumber, SimpleTest). Testes é apenas uma forma racional de você pensar em como desenvolver. Se você não tem a mínima idéia do que você quer saber, teste. Se tem bastante idéia do que você quer fazer, teste. Se você quer ter certeza do que está fazendo, teste! Em qualquer caso que você imaginar, teste!

Criando testes, você força a sua mente a pensar no comportamento da aplicação, na unidade de seus objetos e no que realmente você precisa. Eu já li a respeito de testes, e todos os autores afirmam, testes é uma filosofia, não é somente fazer você escrever menos e fazer mais, mas é realmente uma filosofia, existe pessoas que não conseguem criar guiado a testes, mas nem por isso são péssimos profissionais, é uma filosofia, vai de cada uma.

Você muda a sua forma de pensar, se você não está querendo ou não quer mudar, nem comece a tentar entender o que e para que serve todos esses frameworks, pois você está no caminho errado. Para começar a desenvolver orientado a testes, é necessário que você mude, que você programe menos e pense mais!


nov 17 2008

Tradução: Refatorando seu código legado - Parte 1: No início houve…

Este artigo é uma tradução do artigo Refactoring your legacy code - Part One: In the beginning there was…, caso você encontre erros de português, concordância, tem algum comentário ou agradecimento, FAÇA! É como um amigo meu sempre fala, se você ver alguma coisa errada, conserte!

Lars Jankowfsky é desenvolvedor PHP e participou da International PHP Conference 2008. Ele possui o Frontalaufpral onde ele fala sobre PHP, Agile Development e outros assuntos.

Deixa de papo e vamos a tradução!

Refatorando seu código legado - Parte Um: No início houve…

Como prometido, Tomas e eu iremos procurar mostrar uma visão sobre o que você precisa considerar quando você planejar refatorar suas velhas (legadas) aplicações. Não será um guia detalhado nem muito ordenado. Será mais ou menos nossas experiências e pensamentos nos últimos anos.

Se você precisa de uma introdução mais detalhada (incluindo a nível de código) você deve participar de nosso workshop na Internation PHP Conference 2008. Eu irei ministrar o workshop juntamente com dois dos melhores programadores PHP (Johann Peter Hartmann e Thorsten Rinne), você pode esperar muito mais detalhes.

Com certeza eu irei publicar a apresentação após o IPC - mas não antes ;)

Agora - Refatorando, hmm… Refatorar é, por definição, o meio de modificar (limpando) sem alterar o comportamento. Mas como você pode ter certeza que não está mudando o comportamento se você não está fazendo testes? Isto significa - você só pode refatorar um código se ele possui testes. E é aqui que começa o problema - onde está os testes?

E lá vamos nós. Vamos assumir que você possui um grande projeto - que cresceu durante anos. E agora você está na sorte que seu chefe concorda com você sobre a necessidade dos testes. Mas como iniciar? O time não possui experiência escrevendo testes. Pior ainda, nem sabem o que é Test Driven Development.

Você precisará investir um tempo no time para que eles aprendam como escrever testes. E você experimentará que conhecer e compreender são duas coisas diferentes. Na minha opinião, somente uma coisa pode ser comparada. A diferença entre programação procedural e orientada a objetos. Estranho exemplo? Não.

Deixe-me explicar. É muito fácil pegar um livro e aprender um pouco sobre classes, objetos, etc. Mas somente depois de você usar por um tempo é que você entenderá profundamente o conceito de OOP e buscar o bom senso. O mesmo é para o TDD - escrever testes é mais ou menos questão de minutos. Ou digamos horas se for o seu primeiro teste. Mas entender por quê os testes são importantes e como usá-los. Isto precisa de tempo. E você terá que investir esse tempo.

Depois de eu ter empurrado o time dentro desta direção ( e ei! - isto não foi tão fácil, como muitos desenvolvedores tendem a ser mais conservadores), eles fizeram os testes - simplesmente por quê o chefe disse isso. Mas somente poucas semanas depois, um desenvolvedor disse-me “Ei! Testes são legais! Eu encontrei um bug, eu nunca teria encontrado antes”. Este é o ponto que você precisa para o seu time.

Um pouco mais de teoria. Mas o que dizer dos testes? Por onde começar? Essa resposta é fácil. Você precisa começar com o mais sórdido, mais sujo, e maior arquivo que você pode achar no seu projeto. Eu sei, Eu sei. Eles querem começar com os arquivos mais fáceis, onde os testes são feitos rapidamente e você ver algum progresso. Os desenvolvedores realmente terão medo deste arquivo. Mas o que vai acontecer se você iniciar pelos fáceis? Simples - você verá algum progresso e terá a sensação que as coisas estão tudo bem. Seu time não entenderá os testes completamente - e eles deixam as partes mais sórdidas do código para o final. Você tem que ter forças para resolver os demônios logo no começo. Isso vai demorar um pouco. Mas então você pode ter certeza que o restante vai ser um bom e delicioso pedaço de bolo. De outro modo, você irá mover o parte do risco para o fim do período de refatoração -  e isto não é uma boa idéia.

Você poderia pensar “Esse cara é louco, onde está o problema em escrever testes…?” Ei! Nós estamos falando de velho código crescido ( == espaguete ). Este código é massivamente interconectado. Variáveis globais, classes mistas, selvagens chamadas entre módulos e objetos, etc. É muito difícil escrever testes para isto.

Na verdade, enquanto estiver escrevendo testes você notará que precisa refatorar o código. Você simplesmente tem que refatorar. Pois de outra forma você não pode escrever os testes. Ou - vamos ser honesto - você pode. Se você escrever mocks e stubs que é o triplo do tamanho do seu código. Isto é exatamente o que desenvolvedores sem experiência com TDD irão fazer. Se você ver isso - chutem eles! E em seguida novamente, por que a sensação é muito boa ;).

Cada teste leva ao refatoramento. Como o nó górdio (Vejam no wikipedia) você começará a puxar o worm, e irá puxar, puxar e puxar. E após algum tempo a refatoração estará pronta e o primeiro teste pode ser escrito. Ok, só estava brincando. Mas há alguma verdade nesta afirmação. Você precisa refatorar o código primeiro - então escrever o teste. Sem grandes stubs.

E isto será trabalhoso - especialmente no início, onde tudo está interconectado. E algumas dependencias precisam ser abordadas e resolvidas. Primeiro. Separe o modelo da visão. Na visão, deixe sem lógica - somente I/O. E então teste o modelo. Algumas pessoas até mesmo testam as visões com testes unitários. Eu não. Eu prefiro testar o modelo, com pequenas visões sem lógica e deixar o resto para os testes com selenium.

O sórdido. Leva tempo. Muito trabalho. Mas acredite em mim. Não há outra forma.

Durante a leitura, você pode ficar com a idéia de que você vai fugir com os testes de aceitação. (selenium). Você acha que isso é um bom negócio? A idéia é sensacional. Se você escrever testes do selenium para toda a aplicação - então refatorar - e você não quebrar nenhum teste, você pode ter certeza que você não alterou qualquer funcionalidade. Boa ideia? Não vai funcionar. Desculpe

Lembre-se. Eu estou falando de uma grande aplicação que cresceu. Ela terá toneladas de funcionalidades. Isto significa centenas ou milhares de testes. E estes testes podem durar muito. Eu sei disso. Eu fui até esta estrada - e ela é uma estrada de mão uníca. Nós terminamos com um teste completo rodando por 10 horas. Isso não é desenvolvimento guiado a testes. Para fazer isso que você precisa instantaneamente - instantaneamente - de feedback. Ninguém pode trabalhar assim.

Contínua na parte dois.

Essa foi a primeira parte do artigo. Mais uma vez, espero que vocês gostem. Qualquer dúvida entre em contato! Não deixe de me passar seu feedback.


ago 21 2008

Materiais sobre Metodologias Ágeis

Algumas pessoas entraram em contato comigo procurando materiais sobre metodologias Ágeis.

O material mais atualizado em português é o da Improve It. Você vai encontrar tudo relacionado ao XP e alguma coisa sobre Scrum. Outro lugar sobre XP é o Extreme Programming e aqui você vai encontrar cerca de 8 milhões de páginas sobre Extreme Programming ;)

Sobre Scrum e tudo mais relacionado a Metodologias Ágeis, sugiro a leitura dos seguintes blogs:

Eu tenho uma tag no Google Reader chamada Desenvolvimento, nessa tag eu armazeno todos os blogs que eu considerado interessantes :D

Até a próxima!


ago 12 2008

Criando testes com PHPUnit

Desenvolver orientado a testes não é simples, principalmente por que TDD é uma técnica e nem todos estão aptos a aprender. É preciso disciplina para programar assim, e inicialmente não se tem muitos benefícios e a velocidade para quem está começando é baixa.

Mas os benefícios a longo prazo são incontáveis como códigos mais simples, códigos cobertos por testes, e integração contínua. Além disso fica mais fácil novos desenvolvedores saberem do que se trata toda a aplicação apenas lendo os testes e vendo por que eles foram escritos. Desenvolvimento orientado a testes trazem muitos benefícios e é uma boa prática de desenvolvimento.

Eu já postei aqui como se instala o PHPUnit no Windows e no Linux usando o PEAR. Agora vou demonstrar como por onde você pode começar a desenvolver orientado a testes de uma maneira simples, sem muitos rodeios. Já postei como integrar o PHPUnit e o PHPSpec ao CodeIgniter e muita gente me perguntou “Mas como testar?”, espero responder algumas perguntas neste artigo.

No artigo, eu indiquei para incluir arquivos como Base5.php, Commons.php entre outros, mas eu não fiz isso sem base, primeiro escrevi uma base de testes:

require_once 'config.php';
require_once 'PHPUnit/Framework.php';

class IncludeFilesTest extends PHPUnit_Framework_TestCase {
	public $tasks;

	public function testIncludeBaseClass() {
		ini_set('include_path', ini_get('include_path') .':/home/cairo/workspace/chkList/system/codeigniter/');
		$this->assertEquals(1, include_once('Base5.php'));
	}

	public function testIncludeControllerClass() {
		ini_set('include_path', ini_get('include_path') .':/home/cairo/workspace/chkList/system/libraries/');
		$this->assertEquals(1, require_once('Controller.php'));
	}

	public function testIncludeTasksClass() {
		ini_set('include_path', ini_get('include_path') .':/home/cairo/workspace/chkList/system/app/controllers/');
		$this->assertEquals(1, require_once('tasks.php'));
	}

	public function testIncludeCommonFunctions() {
		$this->assertEquals(1, require_once('Common.php'));
	}

	public function testPossibleCreateTasksControllerObject() {
		$this->tasks = new Tasks;
		$this->assertType('Tasks', $this->tasks);
	}
}

Após todos esses testes estarem funcionando corretamente, é que escrevi o arquivo ‘config.php’ :).

A lógica é essa, escreva testes, faça-os falhar, refatore seu código, refaça os testes e refatore seus códigos até os testes passarem. Não inicie codificando, inicie pelos testes, teste sempre, teste tudo!

Eu demorei muito tempo para colocar esse artigo no ar, principalmente pela falta de tempo que tive ;), vamos testar todo os nossos códigos.

Até a próxima!


ago 6 2008

Documentação Ágil (Agile documentation) com PHPUnit

Agiel team por rewl

Para quem acha que times Ágeis não criam documentação, vocês estão enganados! O que acontece é que a documentação está sempre em mudanças, que levaria bem mais tempo documentar as coisas do que programar ou entender do negócio.

Mas nem por isso times Ágeis não documentam, times Ágeis usam as próprias ferramentas para criar documentação, e com PHPUnit não é diferente. No PHPUnit existe uma forma de criar documentação a partir dos testes utilizando o comando phpunit –testdox ClasseDeTeste.

Esse simples comando gera a partir de seus testes uma breve documentação sobre o que são os testes que você está escrevendo:

phpunit --testdox BankAccountTest
PHPUnit 3.2.10 by Sebastian Bergmann.

BankAccount
 - Balance is initially zero
 - Balance cannot become negative

Exemplo retirado da documentação oficial. Daí você pode exportar para html ou qualquer outro formato de saída que o próprio PHPUnit oferece.

Até a próxima!


jul 19 2008

Futuro do PHPSpec

Olá, para quem não conhece, PHPSpec é um framework BDD para PHP.

Hoje o desenvolvedor do framework, Pádraic Brady, postou um email na lista phpspec-dev (phpspec-dev@googlegroups.com) e um artigo em seu blog sobre o futuro do PHPSpec.

A primeira e mais importante notícia, é que ele quer criar uma DSL decente (Sim, decente). Como ele citou no seu artigo, no Ruby, o BDD é sexy, mas em PHP é feito e chato. Por conta da sintaxe do PHP, a DSL acaba sendo uma coisa totalmente feia. Enquanto que no Ruby temos algo como “should score 0 for gutter game”, em PHP isso acaba virando um método:

    public function itShouldScore0ForGutterGame() {
        for ($i=1; $i<=20; $i++) {
            $this->_bowling->hit(0);
        }
        $this->spec($this->_bowling->score)->should->equal(0);
    }

Para desenvolvedores PHP isso é de fácil leitura, mas infelizmente, isso gera uma barreira enorme para pessoas que não sabem nada de PHP ou de programação, isso acaba fazendo ter um nível de explicação para o cliente ou para o interessado nesse comportamento, e isso vai diretamente contra o principio do BDD, onde todos os envolvidos tem que enteder realmente o que se está fazendo.

A outra notícia, é que ele está retomando a dianteira no desenvolvimento do Framework, desde fevereiro ele não vem dando dedicação necessária ao framework.

A primeira coisa é que ele está fazendo uma varredura nos bugs e liberar mais uma nova versão 0.2.x. Além disso ele fez uma chamada para quem quiser contribuir com alguma coisa para a versão 0.3 :).

Outra coisa importante é que anunciou que possivelmente em setembro ou outubro sairá a versão 5.3 do PHP, e pelo roadmap dele, a versão 0.5 já estará sobre o PHP 5.3 e afirmando que não fará esforços para que o framework funcione nas versões anteriores passando essa responsabilidade para a comunidade.

Agora é esperar até a DSL for sexy o suficiente para todos entender ;).

Até a próxima!


jul 11 2008

Integrando o PHPUnit e o PHPSpec ao CodeIgniter e ao Lumine Framework

Meu grande amigo português Ricardo Mestre me fez a seguinte pergunta esses dias:

Como faço para usar o PHPUnit no CodeIgniter?

O que vou mostrar aqui serve para esses dois frameworks (PHPUnit e PHPSpec) ou para qualquer um outro framework que necessite.

Seguinte, o CodeIgniter possui sua configuração de acesso no index.php, só que na penúltima linha, ele faz chamada ao arquivo BASEPATH.’codeigniter/CodeIgniter.php’;. Quando é requisitado, ele faz a requisição aos arquivos de inicialização e executa o método index da classe default dentro do arquivo system/application/config/routes.php. (UPDATE: o arquivo que define do controlador default a ser chamado assim que a aplicação funcina é em routes.php)

Aí, para usarmos os controladores do CI é necessário utilizar esse arquivo de configuração por conta das contantes que o CI utiliza. Para evitar de quando executarmos nossas classes de testes, elas não venham a executar por conta da saída do CI.

Então, é necessário fazer um arquivo com o mesmo contéudo do index.php, exceto da linha BASEPATH.’codeigniter/CodeIgniter.php’;. Ao fazermos isso é necessário chamar as bibliotecas básicas do CodeIgniter manualmente que estão dentro da pasta /system/codeigniter/. As bibliotecas são BaseN.php (4 para o PHP 4 e 5 para o PHP 5). Common.php e como vamos fazer teste dos controladores, é necessário importar a classe Controlller.php que está dentro da pasta /system/libraries/.

Após isso é só incluir esse arquivo criado dentro das classes de testes.

Resumindo:

  1. Criar arquivo com contéudo do index.php excluindo a penúltima linha que faz chamada ao BASEPATH.’codeigniter/CodeIgniter.php’;
  2. Incluir dentro desse arquivo chamada para /system/codeigniter/BaseN.php (N = 4 ou N = 5);
  3. Incluir dentro desse arquivo chamada para /system/codeigniter/Common.php;
  4. Incluir dentro desse arquivo chamada para /system/libraries/Controller.php;

Bom, agora para utilizar os Models do Lumine, é apenas necessário fazer chamada ao arquivo com as configurações de acesso do Lumine. A critério de convenção, podemos criar um novo arquivo de configuração apenas alterando o nome do banco de dados, assim não prejudicando seu banco de dados.

Depois disso tudo podemos testar nossos controladores e os modelos do Lumine com o PHPUnit, PHPSpec ou qualquer outro framework de testes.

Até a próxima!


jun 18 2008

Behavior Driven Development em PHP com PHPSpec

Comecei a ler muito sobre TDD, depois na comunidade rails-br descobri o BDD li e me pareceu mais simples do que TDD.

Para fazer TDD no rails é bem mais simples do que parece, é só executar os scripts de criação de models, controllers e views que o framework já cria os arquivos básicos para fazer TDD, bastando apenas escrever os casos de testes e executar o comando rake para tudo funcionar.

Para fazer BDD em rails é necessário a instalação de um plugin chamado RSPec, esse plugin é responsável pela criação das especificações em BDD.

Em rails é muito simples fazer TDD e BDD, já que o próprio ambiente te prepara para desenvolver se utilizando dessas técnicas, diferente dos frameworks PHP que poucos deles possuem facilidades como rails (Na sua última versão, o CodeIgniter introduziu TDD em seu core, ainda não tive tempo para dar uma olhada de como funciona. No cakePHP, pelo que eu vi na comunidade, é capaz de se fazer TDD).

Para se fazer TDD e BDD no PHP é necessário a instalação de frameworks para o mesmo, no meu caso eu escolhi o PHPUnit para testes unitários e para BDD eu escolhi o PHPSpec. Só que essa escolha foi por livre e espontânea pressão, é que somente existe esse framework para se trabalhar com BDD em PHP.

Ele foi escrito após o desenvolvedor (Pádraic Brady) ter se aventurado por Ruby e Rails e conhecido RSpec, ele resolveu desenvolver o “RSpec” para PHP e o batizou de PHPSpec.

A documentação é bastante simples e fácil de ler, usei algumas horas e li toda a documentação, e agora estou planejando para utiliza-los nos projetos que faço parte.

Agora vou explicar um pouco de como funciona com um exemplo.

Primeiro, antes da gente começar, devemos especificar o problema, no caso, como um usuário irá fazer um comentário.

Usuário deverá colocar seu nome, depois ele deverá colocar seu email.

Se o usuário tiver um site, poderá coloca-lo.

Então depois o usuário coloca o conteúdo do comentário e clica em enviar.

Agora que temos a especificação, vamos criar nosso primeiro exemplo:

require_once "Post.php";

class DescribeNewPostInBlog extends PHPSpec_Context {

	private $post = null;

	public function before() {
		$this->post = new Post;
	}

	public function itShouldSetName() {
		$this->post->setName("Cairo Noleto");
		$this->spec($this->post->getName())->should->beEqualTo("Cairo Noleto");
	}

	public function itShouldSetEmail() {
		$this->post->setEmail("caironoleto@gmail.com");
		$this->spec($this->post->getEmail())->should->beEqualTo("caironoleto@gmail.com");
	}

	public function itShouldSetWebSite() {
		if ("user set as website") {
			$this->post->setWebSite("http://www.caironoleto.com/");
		}

		$this->spec($this->post->getWebSite())->should->beEmpty();
	}

	public function itShouldSetContent() {
		$this->post->setContent("Aqui vai o comentário do post :P");
		$this->spec($this->post->getContent())->should->be("Aqui vai o comentário do post :P");
	}
}

Se rodarmos no terminal, teremos o resultado:
cairo@angus:~/BDDonPHP$ phpspec DescribeNewPostInBlog
E
Fatal error: Call to undefined method Post::setName() in /home/cairo/BDDonPHP/DescribeNewPostInBlog.php on line 15

Da erro por que nossa classe Post não contém o método setName, e vai da erro a cada um dos métodos que não funciona, então irei cria-los:

class Post {

	private $name;
	private $email;
	private $website;
	private $content;

	public function setName($name) {
		$this->name = $name;
	}

	public function setEmail ($email) {
		$this->email = $email;
	}

	public function setWebSite($website) {
		$this->website = $website;
	}

	public function setContent($content) {
		$this->content = $content;
	}

	public function getName() {
		return $this->name;
	}

	public function getEmail() {
		return $this->email;
	}

	public function getWebSite() {
		return $this->website;
	}

	public function getContent() {
		return $this->content;
	}
}

Agora rode mais uma o código e veja tudo rodando perfeitinho :D

Algumas considerações:

A primeira e mais importante é que o framework está na versão 0.2.3 e ainda não saiu nenhuma versão release, todas as versões são betas.

Por ser beta, falta alguns métodos (Como os “Matchers” beAnInstaceOf, beString, beOfType). Por assinar a lista, foi resolvido hoje e inserido o método beString, ainda não sei como faço pra pegar a versão do SVN que seria bem mais interessante, vou colocar um email na lista perguntando como faço e blogo aqui.

O Framework como está funcionando já da pra escrever muita especificação, então é bola pra frente.

Até a próxima!


jun 17 2008

Qualidade do software

Qualidade do software é uma das áreas de estudo em Engenharia de Software onde o principal objetivo é que o produto final atenda ao maior numero de requisitos em que ele foi solicitado.

Só que aí entra um grande problema, que é a definição do termo “Qualidade” e o termo “Qualidade do software”.

O termo “Qualidade” é definido como “aquilo que caracteriza uma pessoa ou coisa e que a distingue das outras”. Só que a interpretação do termo é extremamente pessoal, o que pode ser qualidade para uma pessoa, pode não ser para outra pessoa, que pode ser ou não para o restante das pessoas.

E isso se extende a qualidade do software. É dificil definir se um software é de boa ou má qualidade, por conta desse conceito ser extremamente pessoal.

Mas uma coisa é certa, o que determina a qualidade do software, é a qualidade no processo de desenvolvimento de softwares (Mas não é difícil determinar qualidade?).

Analisando os resultados dos softwares, foi detectado vários padrões e criado várias metodologias de desenvolvimento. CMMI, SPICE, ISO 12207, MPS.BR, SCRUM, XP, e muito mais foram criados para determinar essa qualidade do software.

Mas o mais importante, independente de se usar padrões, metodologias ou qualquer outro tipo de tendencia, é garantir com que o seu software atenda aos requisitos de seu cliente, e que este atenda as necessidades do mesmo. Assim você está garantindo que seu software tem a qualidade ideal para seu cliente.

Até a próxima!