ADOLFO GUSTAVO SERRA SECA NETO TÉCNICAS ÁGEIS PARA O DESENVOLVIMENTO DE SOFTWARE EM JAVA Apostila para curso de extensão ministrado na Universidade Tecnológica Federal do Paraná. CURITIBA 2009 Sumário 1. Introdução........................................................................................................................................................4 2. Introdução a Métodos Ágeis............................................................................................................................5 2.1. O Manifesto Ágil.....................................................................................................................................6 2.2. E se você não conhece Engenharia de Software?....................................................................................7 3. Desenvolvimento Dirigido por Testes.............................................................................................................9 3.1. Testes Automatizados..............................................................................................................................9 3.1.1. Problemas dos testes manuais..........................................................................................................9 3.1.2. Benefícios dos testes automatizados..............................................................................................10 3.2 Testes Unitários......................................................................................................................................11 3.3 O Processo de Desenvolvimento Dirigido por Testes............................................................................12 3.4 Testes de Aceitação................................................................................................................................14 4. Programação Pareada....................................................................................................................................15 5. Refatoração....................................................................................................................................................17 6. Considerações Finais.....................................................................................................................................18 Referências........................................................................................................................................................19 Outros materiais utilizados................................................................................................................................21 Fonte: http://creativecommons.org/licenses/by-nc-sa/2.5/br/ 1. Introdução Os métodos ágeis para o desenvolvimento de software vieram para ficar. Em minha opinião, eles apresentam uma forma de desenvolver software de forma divertida e com mais qualidade. Até o ano 2000, os principais livros de Engenharia de Software sequer mencionavam a existência de métodos ágeis. De lá para cá, os métodos ágeis tornaram-se tema obrigatório de pelo menos um capítulo destes livros. Esta é a primeira versão desta apostila. É um texto em construção. Versões novas serão liberadas futuramente. Agradeço quaisquer sugestões e indicações de erros, os quais poderão ser enviados para [email protected]. Observação: neste documento não segui estritamente as normas da ABNT. Em alguns momentos usei estas normas mas em outros (por exemplo, na citação de páginas da internet) não as segui. O objetivo foi facilitar a distribuição deste material em formato digital, permitindo que os links ao longo do texto sejam clicáveis. 2. Introdução a Métodos Ágeis O que são Métodos Ágeis? A resposta a esta pergunta depende de uma outra pergunta. Você sabe o que é Engenharia de Software? Algumas respostas possíveis: 1. Sim, pois já fiz um bom curso de Engenharia de Software (ES) na Universidade. 2. Sim, pois já li um bom livro sobre Engenharia de Software. 3. Não, apenas desenvolvo software há bastante tempo. 4. Não, estou começando a desenvolver software 5. NDA (se for nenhuma das anteriores, me diga, pois quero saber qual é a sua resposta!!!) Se você já conhece ES, provavelmente você já leu algum dos livros mais "tradicionais" sobre Engenharia de Software. Se colocarmos o termo "Software Engineering" (entre aspas) na Amazon (http://www.amazon.com) selecionando "Books" na opção de busca, provavelmente os dois primeiros itens retornados serão: • Software Engineering: (Update) (8th Edition) by Ian Sommerville • Software Engineering: A Practitioner's Approach by Roger Pressman Ambos os livros foram traduzidos para o português. Resultados semelhantes são obtidos em mecanismos de busca (Google, Bing, Curl) ao se colocar os termos "Software Engineering" e Book. No Google, os dois primeiros links levam ao livro do Sommerville. Estes dois livros, que de agora em diante chamarei de "o Sommerville" e "o Pressman" são os mais tradicionais livros sobre Engenharia de Software. Se você pelo menos já folheou com atenção estes dois livros, sabe que eles falam de Engenharia de Software como a aplicação de técnicas/princípios/métodos de engenharias tradicionais (civil, mecânica, elétricas) na construção de software. Quando eu estudei por estes livros (e posteriormente quando eu lecionei ES usando estes livros), na primeira metade da década de 1990, nada se falava sobre métodos ágeis. As mais recentes edições destes livros possuem capítulos dedicados a estes métodos. Quem conhece ES deve saber que os Métodos Ágeis (MAs) surgiram em clara oposição à ES que era preconizada por estes livros. Os MAs surgiram como uma espécie de "revolta" de vários "praticantes" de desenvolvimento de software (isto é, pessoas que desenvolviam software na prática, seja como programadores-desenvolvedores, seja como gerentes de projetos) contra o excesso de burocracia dos métodos "tradicionais" (não tão tradicionais assim pois a Engenharia de Software não é tão antiga quanto outras engenharias). O primeiro grande passo para a popularização dos MAs foi o lançamento do Manifesto Ágil. 2.1. O Manifesto Ágil A “revolta” contra os métodos tradicionais fica clara no chamado Manifesto Ágil (BEEDLE, 2001), que reproduzimos abaixo na sua versão traduzida para o português pela empresa ImproveIt (veja em http://www.manifestoagil.com.br/ ou em http://improveit.com.br/xp/manifesto_agil): "Estamos descobrindo maneiras melhores de desenvolver software fazendo-o nós mesmos e ajudando outros a fazê-lo. Através desse trabalho, passamos a valorizar: • Indivíduos e interação entre eles mais que processos e ferramentas • Software em funcionamento mais que documentação abrangente • Colaboração com o cliente mais que negociação de contratos • Responder a mudanças mais que seguir um plano. Ou seja, mesmo havendo valor nos itens à direita, valorizamos mais os itens à esquerda. Kent Beck, Mike Beedle, Arie van Bennekum, Alistair Cockburn, Ward Cunningham, Martin Fowler, James Grenning, Jim Highsmith, Andrew Hunt, Ron Jeffries, Jon Kern, Brian Marick, Robert C. Martin, Steve Mellor, Ken Schwaber, Jeff Sutherland e Dave Thomas. ©2001, Autores acima citados. Esta declaração pode ser livremente copiada, sob qualquer forma, mas apenas na sua totalidade através do presente aviso." Fica clara a ideia de oposição, não fica? Os quatro itens principais do manifesto são no seguinte formato (se os reescrevermos): "valorizamos mais X do que Y", onde Y é algo enfatizado pela Engenharia de Software tradicional. Não está dentro do escopo deste texto explicar tudo sobre métodos ágeis. Nas referências vocês encontrarão indicações de leitura para aprender mais sobre métodos ágeis. Sugiro que leiam também (na mesma página do Manifesto Ágil) os "princípios por trás do manifesto ágil". 2.2. E se você não conhece Engenharia de Software? Neste caso, é uma excelente oportunidade para começar a desenvolver software da maneira certa (ou pelo menos da maneira que "eu" acho certo). Algumas ideias: • desenvolver software deve ser prazeroso; • software é algo flexível, relativamente fácil de ser modificado; • durante o desenvolvimento de um software devemos estar prontos para mudanças de rumo, principalmente as causadas por mudanças de requisitos (isto é, o "dono" do software, aquele que quer que o software seja feito, mudou de ideia em relação ao que ele quer que o software faça); • desenvolver software deve seguir alguns princípios; • não deve existir nenhuma camisa de força para os desenvolvedores de software. Eles devem ter certa liberdade sobre o que fazer. Desenvolvedor de software não é pedreiro. É um trabalhador criativo. Está mais para artista; • devemos minimizar a quantidade de defeitos (bugs) no software (bem óbvio, não?); • nem tudo que o "dono" do software quer que seja implementado realmente deve ser implementado. Muitas vezes o dono quer uma funcionalidade que custa muito mais do que o valor que receberá por ela. Muitas funcionalidades de softwares existentes nunca são ou raramente são utilizadas; • “fazer o software certo” é mais importante do que “fazer certo” o software; • documente apenas o necessário. E o que é o necessário? Você e o seu cliente decidem! Para quê ter um monte de diagramas UML elaborados com uma ferramenta maravilhosa se eles estiverem desatualizados em relação ao código? Para conhecer mais, leia sobre métodos ágeis e conheça alguns métodos específicos (por exemplo, XP e Crystal). Escolha o que melhor se adequa a você e à sua organização. É possível misturar métodos, seguir apenas parcialmente alguns métodos. Não é uma camisa de força. Além disso, compartilhe suas experiências com outras pessoas. Participe de eventos sobre métodos ágeis. Eles reúnem pessoas apaixonadas por desenvolvimento de software. Por último, fique sempre com um pé atrás em relação ao marketing. Como em toda e qualquer área, tem sempre gente querendo lucrar dando um nome diferente a algo que já existe. Por exemplo, tem gente que chama métodos ágeis de "o Agile". Não vejo necessidade disso. Outro problema já bem identificado e criticado pela própria comunidade de entusiastas dos MAs são as certificações para Scrum (veja, por exemplo, http://improveit.com.br/scrum/certificacao). 3. Desenvolvimento Dirigido por Testes Desenvolvimento Dirigido por Testes (DDT) é uma técnica ágil para o desenvolvimento de software que preconiza que os testes devem ser escritos antes do código que será testado. Nesta seção, antes de descrever o que é DDT e como DDT é feito, mostraremos o que são testes automatizados e testes unitários. Por fim, após apresentar o processo de DDT, discutiremos brevemente testes de integração no contexto de DDT. 3.1. Testes Automatizados Testes automatizados são testes que podem ser executados. Isto é, são testes que podem ser escritos, como quando escrevemos um programa, e depois executados. Em geral, para fazer-se testes automatizados utiliza-se um arcabouço (framework) para testes automatizados (como, por exemplo, o JUnit (JUNIT COMMUNITY, 2009)) que se encarrega de facilitar a escrita dos testes, permitir a execução de suítes de testes e exibir os resultados de forma agradável, entre outras coisas. Como se fazia teste de software antigamente (isto é, antes da existência dos testes automatizados)? Executava-se o programa a ser testado com alguma entrada e conferia-se visualmente os resultados obtidos (CHEQUE, 2008). E como são feitos testes automatizados? Executa-se um programa (ou script executável) que roda o programa a ser testado e faz verificações automáticas em cima dos efeitos colaterais obtidos (CHEQUE, 2008). Isto é, no teste está escrito qual é a saída esperada para um programa dadas certas entradas. O arcabouço roda o programa que está sendo testado passando as entradas e verifica se a saída é igual à esperada. Observação importante: testar NÃO é depurar! Testar é verificar a presença de erros. Depurar é seguir o fluxo para identificar um erro conhecido (CHEQUE, 2008). Depurar tem papel importante quando os testes indicam a presença de erros. Mas, de agora em diante, limitaremo-nos a falar de testes. 3.1.1. Problemas dos testes manuais Por que utilizar testes automatizados? Por que os testes manuais (testes não automatizados) apresentam vários problemas. Vejamos alguns destes problemas (CHEQUE, 2008): • É difícil repetir os testes; • É demorado; • É cansativo; • Os testes acabam sendo feitos poucas vezes, com poucos casos, com casos muito simples; • Quando os testes falham, gasta-se muito tempo fazendo a depuração; • Os erros terminam sendo encontrados tardiamente, gerando pressão, desconforto, estresse, perda de confiança. 3.1.2. Benefícios dos testes automatizados E estes são alguns dos benefícios comprovados (ou pretendidos1) com os testes automatizados (CHEQUE, 2008): • Todos os testes podem ser executados a qualquer momento; • O código é submetido a testes mais vezes; • Escrever testes automatizados ajuda a encontrar erros mais cedo; • Escrever testes automatizados aumenta a velocidade do desenvolvimento; • Escrever testes automatizados melhora a qualidade do código, diminuindo a quantidade de erros; • Diminui o tempo gasto com depuração e correção; • Aumenta o tempo gasto com a validação do software; • Os desenvolvedores tem mais segurança para fazer mudanças no código, tais como: • Adicionar novas funcionalidades; • Corrigir erros (se a correção adicionar um novo erro, os testes pegarão); • Refatorações; • Segurança para mudanças externas; • Mudanças de infra-estrutura; • Mudanças nas configurações de arcabouços; • Escrever testes automatizados aumenta a vida útil do software. 1 Obs.: Nem todos estes benefícios podem ser provado. São listados aqui a partir da experiência de desenvolvedores defensores dos testes automatizados. 3.2 Testes Unitários Testes unitários são testes em que são testadas unidades individuais de código-fonte (WIKIPEDIA CONTRIBUTORS, 2009). Em Java, a principal unidade de código-fonte é a classe, portanto cada teste unitário em Java testa as funcionalidades de uma única classe. Existem vários arcabouços disponíveis para fazer testes unitários em Java. Os mais conhecidos são o JUnit e o TestNG (TESTNG COMMUNITY, 2009). Iremos usar o JUnit na versão 4.x. A melhor forma de entender o que são testes unitários é vendo um exemplo. Apresentarei aqui um exemplo que é uma variação do exemplo disponível no Livro de Receitas do Junit (JUNIT COMMUNITY, 2009): 1. @Test 2. 3. 4. 5. 6. 7. 8. } public void simpleAdd() { Moeda m12BRL = new Moeda(12, "BRL"); Moeda m14BRL = new Moeda(14, "BRL"); Moeda esperado = new Moeda(26, "BRL"); Moeda resultado = m12BRL.add(m14BRL); assertTrue(esperado.equals(resultado)); O método acima é um método de teste que testa o construtor e o método add da classe Moeda. Na linha 1 colocamos a anotação @Test para indicar que este é um método de teste do JUnit. Na linha 2 definimos a assinatura do método. Nas linhas 3 e 4 criamos dois objetos da classe moeda. O primeiro objeto representa 12 reais (“BRL” representa “Brazilian Real”, ou seja, “Real Brasileiro”, a moeda do brasil). O segundo, 14 reais. O objeto esperado (linha 5) representa 26 reais. O objeto resultado é o resultado da adição de m14BRL a m12BRL, portanto deverá ser 26 reais se a implementação do método add estiver correta. A chamada a assertTrue na linha 7 verifica isso: ao executar esta classe com o JUnit, se esperado for igual a resultado, aparecerá a luz verde. Se não for, aparecerá a luz vermelha. Em que classe deve ficar este teste? Eu sugiro que seja colocado numa classe chamada MoedaTeste, que ficará numa pasta de código-fonte do projeto chamada tests. A pasta de código-fonte principal do projeto deve ser chamada de src. Deste modo isolamos o código de teste (que não precisa ser utilizado para gerar a versão final para o cliente) do código de produção. Para que este teste seja corretamente compilado são necessários dois imports: import static org.junit.Assert.assertTrue; import org.junit.Test; O primeiro é utilizado para que se possa utilizar o método assertTrue. O segundo, para a anotação @Test. Para que estes imports possam ser feitos, a biblioteca junit.jar deve estar entre as bibliotecas do projeto. O JUnit versão 4.x dispõe de vários outros recursos para a criação de testes unitários, dentre os quais destacamos: • Anotação @Before: usada para declarar um método que será executado antes da execução de cada método de teste. Por exemplo, pode ser usada para criar uma coleção de objetos que são usados por vários métodos de teste; • Anotação @After: usada para declarar um método que será executado depois da execução de cada método de teste; • Anotações @BeforeClass e @AfterClass: usadas para declarar métodos que serão executados apenas uma vez antes/depois da execução de todos os métodos de teste; • Anotação @Ignore: usada para (temporariamente) excluir um teste do conjunto de testes que serão executados; • Diversos métodos do tipo assert*, como assertEquals, assertNull, assertSame (ver http://junit.org/apidocs/org/junit/Assert.html); • Parâmetro expected: provê uma forma de testar o lançamento de exceções (expected=AnException.class), onde AnException é o nome da classe da exceção que se espera ser lançada durante a execução do teste; • Parâmetro timeout: permite definir um período de tempo (em milissegundos) após o qual o teste falha se o método de teste não finalizar o seu processamento. 3.3 O Processo de Desenvolvimento Dirigido por Testes Nas metologias tradicionais, os testes são feitos após a implementação. O objetivo do DDT é que os testes sejam escritos antes da implementação da funcionalidade para que o projeto das classes que estão sendo testadas seja feito durante a escrita dos testes. O processo de utilização do DDT (que é repetido a cada implementação de funcionalidade) pode ser visto como um processo circular (veja Figura 1): 1. Escreva um teste; 2. Execute todos os testes e acontecerá uma falha; 3. Escreva o código para passar no teste que foi escrito no passo 1; 4. Execute os testes e veja todos os testes passarem (se o código escrito no passo 4 estiver correto); 5. Refatore o código escrito no passo 4. Figura 1. Uma representação gráfica do ciclo de desenvolvimento sugerido pelo DDT usando fluxogramas. Fonte: (WIKIPEDIA CONTRIBUTORS, 2009b) Este processo pressupõe que se esteja escrevendo testes automatizados, isto é, que os testes possam ser escritos como um programa. Portanto, no passo 1 é escrito algum teste (um trecho de programa) que verifica alguma funcionalidade desejada para o sistema (que também será representado como um programa). Um teste (ou um “caso de teste”), contém em geral uma ou mais entradas e uma ou mais saídas esperadas. Por exemplo, para testar um sistema que faz cálculos aritméticos básicos (supondo que eles não sejam oferecidos pela linguagem), podemos escrever um caso de teste que testa a operação de adição (+) dizendo que se oferecermos 2 e 2 como entrada a saída esperada é 4. No passo 2 executam-se todos os testes. Aqui supõe-se que já exista um conjunto de testes para o sistema. Se no passo 1 foi escrito o primeiro teste, este conjunto conterá apenas um teste. Neste momento, é esperado que o conjunto de testes falhe, pois provavelmente a funcionalidade que será verificada pelo último teste escrito ainda não foi implementada (está é a ideia do DDT). No passo 3 escreve-se o código de produção para passar no teste escrito no passo 1. Usamos o termo “código de produção” para diferenciar do código de teste pois, afinal de contas ambos são código. Continuando o exemplo do passo 1, aqui implementaríamos o código do método que faz a adição de dois números. No passo 4 executam-se novamente todos os testes. Neste momento, é esperado que todos os testes passem. Caso isso não aconteça, volta-se ao passo 3 para corrigir o código de produção. Após passar em todos os testes, no passo 5 o código de produção é refatorado, isto é, é reescrito para que fique mais limpo, mais bonito, mais fácil de entender (ver mais sobre refatoração na seção 5). Se forem feitas mudanças no código de produção que exijam alterações no testes escritos no passo 1, volta-se ao passo 1. Caso contrário, executam-se novamente todos os testes. Se todos passarem, volta-se ao passo 1 para criar um novo caso de teste. Se algum teste falhar, vai-se ao passo 3 para corrigir o que deu errado. 3.4 Testes de Aceitação Testes de aceitação são testes do tipo caixa-preta, que testam as funcionalidades do sistema sem conhecer o projeto do sistema. Eles podem verificar a correção do sistema como um todo ou apenas de uma parte dele (por exemplo, de uma estória). DDT e Testes Automatizados também podem ser utilizados para fazer testes de aceitação (JAIN, 2008). Existem arcabouços específicos para automatizar testes de aceitação (por exemplo, o Selenium (SELENIUM COMMUNITY 2009)), mas em alguns casos simples os arcabouços para testes unitários podem ser usados para fazer testes de aceitação. Neste caso, basta implementar classes de testes que instanciem objetos de diferentes classes e que sigam roteiros de interação entre as classes. 4. Programação Pareada Programação Pareada é a técnica em que dois desenvolvedores desenvolvem conjuntamente e simultaneamente uma solução para uma tarefa. A ideia inicial é que dois programadores dividam a mesma máquina para implementar uma mesma funcionalidade. Um fica de posse do teclado e o outro fica ao lado dando sugestões e apontando erros. Antes vamos dar nomes aos bois, digo, aos papéis (WILLIAMS, Laurie APUD NETO, 2009): • Chamaremos o programador que está controlando o teclado de “piloto” (ou “motorista”); • E o programador que está observando o trabalho do motorista, identificando problemas, fazendo perguntas e sugestões é chamado de “co-piloto” (ou “navegador”). Um (o piloto) controla o teclado e o mouse. O outro (o co-piloto) observa criticamente. Os dois estão continuamente dialogando. De tempos em tempos, ao longo de uma sessão de implementação, o controle muda de mãos. E, ao longo de um projeto, os companheiros são trocados de pares. Vale a pena? Aparentemente não... A empresa usa dois “recursos” em vez de um. Isto é, tem que pagar o salário de dois desenvolvedores para trabalhar num mesmo problema? Os dois usam o mesmo computador a maior parte do tempo (o computador do outro programador fica ocioso). Mas diversas pesquisas (WILLIAMS & KESSLER, 2003), mostraram que a programação pareada aumenta a qualidade do software. Além disso, as tarefas são completadas em menos tempo (mas não necessariamente em menos da metade do tempo que um programador sozinho gasta). E tão importante quanto a programação pareada são a análise pareada e o projeto (design) pareado. Além disso, o trabalho do programador/desenvolvedor fica menos chato, menos solitário, mais social. À medida que os pares se acostumam a trabalhar em pares, a produtividade aumenta. A retroalimentação, o debate e a troca de idéias entre os parceiros diminuem significativamente a probabilidade de se continuar com um mau design. A presença do outro força cada programador a concentrar-se totalmente no problema em questão. Cada parceiro ajuda o outro a manter a disciplina de escrever testes primeiro. E funciona como um treinamento cruzado: um programador ensina o outro. Quando fica difícil fazer programação pareada? Por exemplo, quando o desenvolvimento é distribuído e os membros da equipe estão em lugares diferentes. Porém, mesmo neste caso, tendo uma conexão rápida de internet é possível fazer programação pareada. Basta usar algum sistema que permite a edição do código de forma simultânea e usar alguma forma de comunicação instantânea (MSN, Google Talk). Outra dificuldade acontece quando a cultura do país dificulta a proximidade dos programadores. Mas isto com certeza não se aplica aos brasileiros... Terminamos esta seção com as palavras de Obie Fernandez, um famoso desenvolvedor, escritor e blogueiro, proferidas em sua palestra no Rails Summit Latin America 2008: a principal vantagem da programação pareada é que “quando se está trabalhando em par se trabalha o dia todo. Pois ao trabalhar sozinho, você vê o seu e-mail, lê blogs e etc. E essas coisas não acontecem com programação em par. Ao fim de um dia de programação em par você está cansado, pois você realmente pensou e trabalhou o dia todo. Mas você fica contente, pois sabe que teve o trabalho realizado”. (FERNANDEZ, Obie APUD MERGULHÃO, 2008). 5. Refatoração Refatoração é basicamente reescrever código que já está funcionando. Ou seja, temos uma classe ou método que já faz o que deveria fazer. Mas alguma coisa (que não afeta o resultado da implementação) não está muito boa. Pode ser algum problema na implementação do método ou na distribuição de funcionalidade entre as classes. Exemplos de problemas são: classe está muito grande, o método é muito longo, etc. Em outras palavras, “refatorar é melhorar o código sem alterar sua funcionalidade. Antes de fazer uma mudança, você refatora o código para que a mudança seja simples de fazer. Refatoração contínua possibilita manter um design legal, mesmo com mudanças frequentes.” (CIRNE, Walfredo APUD NETO, 2008). Os Ambientes Integrados de Desenvolvimento para Java mais utilizados (por exemplo, Eclipse e Netbeans) dispõem de funcionalidades para facilitar os casos mais comuns de refatoração. É possível, por exemplo, renomear classes, renomear métodos, incluir/excluir parâmetros em/de métodos, etc. São muitas as refatorações possíveis. Um bom catálogo de refatorações possíveis está disponível no livro Refatoração, de Martin Fowler (FOWLER, 2004). Este livro contém dezenas de “receitas de refatoração”. Alguns exemplos são: • Extrair Método; • Mover Método; • Mover Atributo; • Extrair Classe. Extrair Método, por exemplo, transforma uma sequência de comandos num método. Mais informações sobre as refatorações possíveis podem ser encontradas em (FOWLER, 2009), na seção Catalog. 6. Considerações Finais Os métodos ágeis estão em constante transformação. Muito do que está escrito aqui poderá estar desatualizado em questão de meses. Portanto, a minha sugestão é que você se mantenha atualizado acessando as principais páginas disponíveis sobre métodos ágeis e participando de cursos/eventos ágeis. Procuro manter alguns links para sites interessantes sobre métodos ágeis na página: • http://adolfoneto.wikidot.com/metodologias-ageis Particularmente úteis são os sites da Agilcoop e da InfoQ. Os artigos da Wikipedia (em inglês) sobre métodos ágeis e temas relacionados em geral são muito bons. Além disso, estou no Twitter em: • http://twitter.com/adolfont onde procuro divulgar eventos, cursos, artigos e posts interessantes sobre métodos ágeis. Alguns dos twiteiros ágeis que sigo estão na minha lista em: • http://twitter.com/adolfont/agil Por fim, eventualmente no meu blog: • http://professoradolfo.blogspot.com/ publico ou republico artigos sobre métodos ágeis. Referências BEEDLE, Mike et al. Agile Manifesto. 2001. Disponível em: <http://agilemanifesto.org/>. Acesso em: 07. out. 2009. CHEQUE, Paulo. Introdução a Testes Automatizados. Curso de Verão 2008 - IME/USP. Disponível em: <http://ccsl.ime.usp.br/agilcoop/files/AgilCoop-Verao08-Testes.pdf>. Acesso em: 07 out. 2009. FOWLER, Martin. Refatoração: Aperfeiçoando o Projeto de Código Existente. Porto Alegre: Editora Bookman, 2004. Links: http://bit.ly/32kaxh (página do livro no site da Editora) e http://bit.ly/OI8ok (página do livro na Livraria Cultura). FOWLER, 2009. Refactoring site. Disponível em: <http://www.refactoring.com>. Acesso em: 18 nov. 2009. JAIN, Naresh. Acceptance Test Driven Development. Disponível em: <http://www.slideshare.net/nashjain/acceptance-test-driven-development-350264>. Acesso em: 18 nov. 2009. JUNIT COMMUNITY. JUnit. Disponível em: <http://junit.org/>. Acesso em: 18 nov. 2009. MERGULHÃO, Sylvestre. Rails Summit dia 16: Obie Fernandez. 16 de outubro de 2008. Disponível em: <http://bit.ly/4qkbOH>. Acesso em: 18 nov. 2009. NETO, Adolfo. Metodologias Ágeis para o Desenvolvimento de Software. Disponível em: <http://bit.ly/3WUFfp>. 2008. Acesso em: 18 nov. 2009. NETO, Adolfo. Programação Pareada. Disponível em: <http://adolfoneto.wikidot.com/programacaopareada>. Acesso em: 18 nov. 2009. SELENIUM COMMUNITY. Selenium. Disponível em: <http://seleniumhq.org>. Acesso em: 18 Nov. 2009. TESTNG COMMUNITY. TestNG. Disponível em: <http://testng.org>. Acesso em: 18 Nov. 2009. WIKIPEDIA CONTRIBUTORS. Unit testing. Wikipedia - The Free Encyclopedia. Disponível em: <http://en.wikipedia.org/w/index.php?title=Unit_testing&oldid=325780704>. Acesso em: Nov. 16, 2009. (a) WIKIPEDIA CONTRIBUTORS. Test-driven development. Wikipedia - The Free Encyclopedia. Disponível em: <http://en.wikipedia.org/wiki/Test-driven_development>. Acesso em: Nov. 16, 2009. (b) WILLIAMS, Laurie; KESSLER, Robert. Pair Programming Illuminated. Addison Wesley, 2003. Outros materiais utilizados BECK, Kent; SAVOIA, Alberto. JUnit 4 and Java SE 5: Better Testing by Design. 2006. Disponível em: <http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-1580&yr=2006&track=tools>. Acesso em: 07. out. 2009. DEMARCO, Tom. Software Engineering: an idea whose time has come and gone? IEEE Software, p.95-96, July/August 2009. Disponível em:<http://www2.computer.org/portal/web/csdl/doi/10.1109/MS.2009.101>. Acesso em: 07 out. 2009. RUSTAM. Thoughts on Extreme Programming. Disponível em: <http://code.az/article/xp>. Acesso em: 18 nov. 2009. SATO, Danilo; BRAVO, Mariana. Introdução a Métodos Ágeis. Curso de Verão 2008 - IME/USP. Disponível em: <http://ccsl.ime.usp.br/agilcoop/files/AgilCoop-Verao08-Introducao.pdf>. Acesso em: 07. out. 2009. TELES, Vinícius Manhães. Extreme programming: aprenda como encantar seus usuários desenvolvendo software com agilidade e alta qualidade. São Paulo: Novatec, 2004. 316 p. ISBN 85-7522-047-0.