Guia de Ruby do Why e Autospec-notification

Posted by Equipe 1up4dev on abril 27, 2009

O comovente guia de Ruby do Why

Este livro é sensacional e demonstra exatamente o espírito do Ruby: papo de programador.

O livro é bem divertido. As tirinhas das raposas são ótimas. Várias pessoas contribuíram com a tradução para pt-br que está disponível no Github.

Leitura obrigatória. Chunky bacon!

Autospec-notification

O Autospec é um script gerado pelo RSpec que utiliza o Autotest para rodar os testes automaticamente a cada alteração no código.

Unindo o útil ao agradável, foi criado o Autospec-notification, que exibe as notificações do autospec no desktop.

Para instalar, comece pela gem ZenTest:

sudo gem install ZenTest

No linux, instale o Libnotify:

sudo apt-get install libnotify-bin

Agora instale a gem do autotest-notification:

sudo gem install carlosbrando-autotest-notification --source=http://gems.github.com

Ative o autotest-notification e rode o autospec no seu projeto:

an-install
script/autospec

O código está no Github. Escreva seus testes e divirta-se!

TPW – Testando sistemas legados: classes Utils 2

Posted by Rodrigo Panachi on março 03, 2009

Aproveitando o gancho do post anterior sobre manipulação de dependências, decidi dedicar um post apenas sobre este tema, pois acredito ser de grande ajuda para todos desenvolvedores que precisam manter código legado.

Em projetos legados é comum encontrarmos classes Util (aka Helpers) espalhadas por todo o código, fazendo desde coisas simples como formatar datas ou números, até coisas mágicas como cache de objetos, operações com reflection, escrita de logs, etc. Mesmo que tenham sua “utilidade”, são um terror quando falamos de testes! Além de ser um forte indício de um design fraco, as chamadas a seus métodos, geralmente estáticos, geram dependências nas classes que a utilizam.

Este é a estrutura comum (bem simplificada) de uma classe Util com métodos estáticos:

public class MagicUtil {
    public static String getConstanteSecreta() {
        return "VALOR_SECRETO_AMBIENTE";
    }
}

Neste caso, uma boa estratégia para os testes seria encapsular a chamada da classe Util em um método protected, para que seja sobrescrito na classe de teste, assumindo o comportamento desejado. Porém, se a classe Util for largamente referenciada no projeto (o que é comum) seria preciso refatorar todas a classes que a utilizam para escrever um teste completo.

A estratégia proposta é refatorar a classe Util, aplicando o padrão Singleton e transformando os métodos estáticos em métodos de instância, porém mantendo as assinaturas estáticas, que devem referenciar os métodos da instância. Uma vez que a Util pode ser instanciada (mesmo que internamente), é possível manipular seu comportamento através da injeção de um objeto Mock, por exemplo:

public class MagicUtil {
    private static MagicUtil instance = new MagicUtil();
    protected static MagicUtil getInstance() {
        return instance;
    }
    protected static void setInstance(MagicUtil obj) {
        instance = obj;
    }
    public String getConstanteSecretaInstancia() {
        return "VALOR_SECRETO_AMBIENTE";
    }
    public static String getConstanteSecreta() {
        return getInstance().getConstanteSecretaInstancia();
    }
}

Assim, a Util continua com o mesmo comportamento e seu contrato foi mantido. Agora, no seu teste, basta escrever o mock (estendendo a classe e sobrescrevendo os métodos) e injetá-lo na instância interna da Util:

public class ClasseTest {
    @Test
    public void testaMetodoDependenteDeMagicUtil() {
        new MagicUtil() {
            {
                setInstance(this);
            }
            public String getConstanteSecretaInstancia() {
                return "MEU_VALOR_MOCK";
            }
        };
        Assert.assertEquals("MEU_VALOR_MOCK", MagicUtil.getConstanteSecreta());
    }
}

Neste caso a classe anônima (que estende a Util) passa sua própria instância (this) para o método protegido setInstance(). Note que a chamada do método (estático) da Util continua igual ao da classe original, sem o refactoring.

Nos projetos que preciso manter, esta estratégia tem sido muito útil para resolver os problemas das “teias” de Utils. Porém é um recurso paliativo e não deve ser utilizado como o “padrão”. O ideal é sempre evitar classes Utils, lembrando que uma classe deve sempre ter comportamentos bem definidos e o nome já deve indicar sua responsabilidade.

TPW – Testando sistemas legados: manipulando dependências 3

Posted by Rodrigo Panachi on fevereiro 19, 2009

Pela definição de Michael Feather, código legado é código sem testes! Não importa se o código foi escrito semana passada ou alguns anos atrás. Qualquer manutenção será de difícil entendimento por outra pessoa e não haverá garantias de seu funcionamento. Uma vez que não há “controle”, é mais difícil rastrear as alterações; pior do que uma nova funcionalidade que não funciona, é uma funcionalidade antiga que começa a falhar. Este é um risco que um desenvolvedor não pode correr!

Não altere código legado até que seja possível testá-lo

Um dos problemas mais comuns em sistemas legados é a interdependência de classes, ou seja, o alto acoplamento, que sempre está ligado com a baixa coesão. Se estes termos são difíceis de entender, pense em acoplamento como sendo o grau com que as classes referenciam umas as outras e coesão o quanto uma classe está focada em realizar suas responsabilidades.

Para que seja possível testar o comportamento de uma classe “acoplada”, o comportamento de suas dependências precisa ser simulado. Isto normalmente é feito através de objetos falsos, ou mocks, que são injetados na instância da classe em questão. Este padrão é conhecido como Inversão de Controle e Injeção de dependência, onde o controle sobre as dependências da classe são delegados à outro objeto, ou normalmente um container de objetos, responsável por injetar as dependências nas instâncias das classes. Simples, não?! Mas isso será detalhado em outro post…

Voltando para os testes, no post anterior começamos a organizar o projeto automatizando o build e centralizando a execução dos testes para evitar que fiquem “soltos” pelo código. Agora vamos nos concentrar em escrever os casos de teste, refatorando o necessário para lidar com as dependências das classes.

Partindo da premissa que o projeto não possuí nenhum framework de inversão de controle, utilizaremos um certo “padrão” que permite manipular as dependências de uma classe por meio de herança, sem alterar seu comportamento original. A idéia é resolver as dependências da classe através de getters protegidos, que podem ser sobrescritos em uma classe filha no momento do teste. Isso permite que, na classe estendida, o método sobrescrito retorne um objeto mock, por exemplo, com o comportamento esperado para o teste.

Vamos tomar como exemplo, uma classe simples com algumas dependências e responsável por encapsular algumas regras de negócio referentes à Estoque.

public class EstoqueLogic {
    public boolean verificaDisponibilidade(Produto produto, Integer quantidade) {
        EstoqueDAO dao = new EstoqueDAO();
        Estoque estoque = dao.localizaProduto(produto.getCodigo());
        return estoque.getQuantidade() >= quantidade;
    }
}

Da forma como esta classe foi escrita, é impossível testar a regra de disponibilidade independentemente, pois depende do objeto EstoqueDAO para localizar as informações necessárias para o método. Mas com um pequeno refactoring, a responsabilidade de resolver a dependência EstoqueDAO passa a ser responsabilidade da própria classe Estoque:

public class EstoqueLogic {
    public boolean verificaDisponibilidade(Produto produto, Integer quantidade) {
        EstoqueDAO dao = getEstoqueDAO();
        Estoque estoque = dao.localizaProduto(produto.getCodigo());
        return estoque.getQuantidade() >= quantidade;
    }
    protected EstoqueDAO getEstoqueDAO() {
        return new EstoqueDAO();
    }
}

Desta forma, é possível “injetar” um objeto que simule a dependência do EstoqueDAO estendendo a classe e sobrescrevendo o método getEstoqueDAO() para retornar a instância desejada. O teste ficaria mais ou menos assim:

public class EstoqueLogicTest {

    public void testVerificandoDisponibilidadeDeUmProduto() {

        //Criando o objeto EstoqueDAO mock, simulando o comportamento desejado
        final EstoqueDAO estoqueDAOMock = new EstoqueDAO() {
            @Override
            public Estoque localizaProduto(String codigo) {
                Produto produto = new Produto();
                produto.setCodigo(codigo);
                Estoque estoque = new Estoque();
                estoque.setProduto(produto);
                estoque.setQuantidade(5);
                return estoque;
            }
        };

        //Sobrescrevendo o método getEstoqueDAO para retornar o Mock
        EstoqueLogic logic = new EstoqueLogic() {
            @Override
            protected EstoqueDAO getEstoqueDAO() {
                return estoqueDAOMock;
            }
        };

        //Definindo o teste e executando
        Produto produto = new Produto();
        produto.setCodigo("123456");        

        boolean estaDisponivel = logic.verificaDisponibilidade(produto, 10);
        assertTrue(estaDisponivel);

        boolean naoEstaDisponivel = logic.verificaDisponibilidade(produto, 2);
        assertTrue(naoEstaDisponivel);
    }
}

O método getEstoqueDAO() da classe EstoqueLogic foi sobrescrito para retornar o objeto estoqueDAOMock com as informações necessárias para o teste, ou seja, o comportamento das dependências foi simulado, possibilitando que o teste ficasse concentrado apenas da classe Estoque.

Elimine as dependências e teste onde os bugs estão!

Este padrão fornece apenas uma maneira de lidar com as dependências das classes para escrever testes. A dica aqui é manter o foco: defina apenas testes para as funcionalidades que estiver alterando e que exercitem pontos críticos e/ou regras de negócio. Então, refatore apenas as classes necessárias para simular e validar o fluxo destes testes, nem que seja apenas seus “contratos“. Não há necessidade de escrever testes muito granulares nem alterar todas as classes de um sistema legado.

No caso de classes com muitas dependências, o melhor é refatorá-la, separar as responsabilidades e testá-las individualmente. Para classes com dependências de Utils e/ou muitas chamadas à métodos estáticos, uma estratégia parecida pode ser utilizada. Mas estes são assuntos para os próximos posts. Acompanhem!

GEdit para RoR de modo fácil 7

Posted by Roger Leite on agosto 03, 2008

Olá Pessoal, terceira reinauguração do blog, e agora finalmente resolvemos o sonho do dominio próprio ! :D

Uma das grandes dificuldades para quem está iniciando com Ruby on Rails no linux, é descobrir qual editor usar, já que o sempre-citado Textmate é somente para Mac.

O que eu estou usando atualmente é o gedit, editor de texto padrão, que vem com o Ubuntu e provavelmente com o Gnome.

Quando comecei minha busca pelo editor perfeito, encontrei vários tutoriais que ensinavam a encher o gedit de plugins, só que era muito manual, tinha que baixar um por um … quando tive que fazer a segunda vez, desisti, e resolvi buscar por soluções melhores.

Sempre ouvi o Rails Podcast, e em algum destes, o Carlos Brando citou o github. Entrei lá, e fui verificar o que tinha de bom, e até hoje não sei como encontrei os projetos, só sei que comecei a usá-los.

Vamos ao que interessa !

No projeto gedit-rails faça o download aqui ou clique em download na página do projeto (estamos no linux, use o formato tar). Descompacte o arquivo, entre na pasta e execute o install.sh veja a imagem abaixo:

install-gedit-rails

install do gedit-rails

No projeto gedit-themes você encontrará temas para o visual do gedit, o meu preferido é o darkmate, acho muito confortável para os olhos, mas existem várias opções. O processo de instalação é mais simples que os plugins.

Baixe os temas em tar aqui ou no botão download na página do projeto. Descompacte o tar numa pasta separada, e na tela de preferências, fontes e cores do gedit, você consegue adicionar o novo tema que deseja.

Veja o resultado aqui:

Infelizmente estou sem tempo para entrar nos detalhes de cada plugin, de qualquer maneira, vou deixar aos interessados os links, que contém informações valiosas:

Existem muitos plugins para o gedit, caso estejam procurando por mais, tentem na Lista de Plugins para o gedit do Fernando Vieira, e tem também a lista oficial de plugins do gedit.

Dicas de novos plugins, comentários e/ou críticas são bem vindas !

Abraço e sucesso!

UPDATE: Sugestões do Philipe Farias, via comentários ! Valeu pelas dicas !

Plugins:

- Snippets ou Trechos – padrão do Gedit (tem que ativar). Quando o gedit-rails é instalado ele adiciona os snippets para erb, ruby e shoulda;

- gedit_formatter

- gemini

- gedit TODO list

Esta parte é interessante para seguir ao padrão Ruby, “Recomenda-se também configurar a “largura das tabulações” para 2 e ativar “inserir espaços em vez de tabulações” nas preferências do Gedit”.

Aqui já entra configurações mais pessoais que você encontra na tela de preferências do gedit. Também de ativar “mostrar números de linhas”, “destacar linha atual” e “destacar parêntesis correspondentes”.

Quanto ao esquema de cor acho o Oblivion mais “completo” para Rails. Screenshot do gedit com Oblivion: