O último D em TDD é para Arquitetura

February 3rd, 2009 § 6 comments

No meu último artigo, comentei bastante sobre a minha opinião de que testes devem ser sobre o relacionamento entre partes específicas do seu código e não sobre interfaces ou contratos. Na minha experiência, os testes mais duradouros e de maior valor são aqueles que exercem as interfaces e contratos indiretamente, através do arquitetura particular oferecida pelos mesmos.

O ressurgimento de testes como uma ferramenta ágil é uma coisa recente e, obviamente, uma excelente oportunidade para conversar sobre técnicas, filosofia e metodologia de desenvolvimento. Em especial, a comunidade Rails tem feito um trabalho excepcional de evangelização sobre o assunto, tornando testes um participante de primeira classe no discurso de desenvolvimento de software.

Entretanto, como é fácil acontecer, o próprio sucesso do assunto está se convertendo em uma fonte de perigos para desenvolvedores iniciantes ou que não tenham tanto familiaridade com TDD e BDD. A própria multiplicação dos pães, digo, dos frameworks de teste está contribuindo para isso no sentido de que, em um afã de criar mais features do que o concorrente, alguns framework estão simplesmente promovendo técnicas péssimas de testes em troca de um falso senso de segurança.

Isso volta um pouco na discussão sobre a diferença entre TDD e BDD, mas acho que o ponto merece uma ênfase. Em resumo, é imprescindível evitar substituir arquitetura, mesmo quando se está fazendo TDD, por meros testes.

Isso fica mais fácil de ser percebido com algumas ilustrações. Tomando o Shoulda como exemplo, é muito comum ver código como o seguinte:

class UserTest < ActiveRecord::TestCase
  should_belong_to :account
  should_have_many :posts
  should_have_named_scope('recent(5)').finding(:limit => 5)  
  should_have_index :age
end

Esse tipo de código não prova absolutamente nada sobre o desenho próprio de sua classe. O código acima:

  1. É redundante, porque as três primeiras cláusulas já serão testadas automaticamente em outras partes do código, especificamente em controller;

  2. É quebradiço, porque é diretamente relacionado à implementação e não ao comportamento da classe em si;

  3. É pouco mais do que um teste de sanidade para descobrir se o desenvolvedor colocou algumas poucas linhas de código em seu modelo;

  4. Expõe detalhes de implementação, como no caso do matcher para índice.

Em outras palavras, todos os testes acima são absolutamente inúteis. O teste de escopo é o único com algum valor para o teste do modelo em si, mas continua sendo redundante.

Pior ainda, existem exemplos como shouldhavebeforesavecallback, proveniente do Remarkable. Esse é o tipo de asserção que chega a ser contraproducente. É um teste que expõe a funcionalidade subjacente de um modelo, que por regras de encapsulamento deveria ser completamente isolada e invisível para as demais partes da aplicação, é um desvio completo do que TDD representa.

Testes, mais uma vez, são sobre interoperabilidade entre facetas do código. São parte de uma conversa arquitetural que procura se focar o mínimo em detalhes internos de implementação. O objetivo é escrever o menor corpo possível de testes–axiomas–que possa dar uma indicação da validade de um dado corpo de código. E como eu repito freqüentemente aqui, simplicidade é um alvo explícito de boas arquiteturas.

Tagged

§ 6 Responses to O último D em TDD é para Arquitetura"

  • Daniel says:

    Muito bom Ronaldo! Mas por outro lado, você não deveria dar exemplos de como deve ser feito também?

    Se você já apontou o problema, poderia apontar uma solução! :)

  • Daniel says:

    Ah, e eu discordo que os três primeiros testes sejam redundantes devido ao fato que eles serão testados no controller.

    Por exemplo no rspec, como bem se sabe, no controller devemos usar mocks! :)

  • Concordo com você, para mim teste tem que ser sobre a entrada e a saida. E não se preocupar como a entrada gerou a saida.

  • Ronaldo says:

    Daniel, com certeza. :) Esse foi um artigo pequeno e rápido sobre o problema em si. Vou emendar um na seqüência sobre boas práticas.

    “Como bem se sabe” é um convite para não discutir. Mocking é uma escola. Não é necessariamente uma verdade. Esse é um dos pontos em que o pessoal mais tem problema hoje. Mock em tudo sem testes reais.

    Leonardo, exato.

  • Manter o foco na arquitetura muda bastante as regras do jogo, e esses teus últimos 2 posts foram um verdadeiro balde de aguá fria na forma como eu estava construindo meus testes aqui.

    Assim como o Daniel, também aguardo pequenas demonstrações praticas daquilo que você considera como sendo a forma “mais correta” 😉

    Abraço,
    Tailor.

  • Ronaldo says:

    Opa! Não precisa se assustar tanto. :)

    O exemplo foi bem particular e não significa que testes de modelo são absolutamente inúteis em si. Os exemplos acima são, mas testes de modelo–ou unitários, usando a palavra correta–tem seu valor desde que usados para testar funcionalidade real. O problema é que muita gente só testa aquilo e deixa como a funcionalidade toda estivesse coberta.

    Existe um ponto de equilíbrio entre o uso da funcionalidade e a descrição da funcionalidade que pode ser atingida de maneira bem fácil. Basta começar pela preocupação arquitetural mais alta e ir descendo. Isso dá uma boa indicação de quais são os valores necessários para os testes.

Leave a Reply

Your email address will not be published. Required fields are marked *

What's this?

You are currently reading O último D em TDD é para Arquitetura at Superfície Reflexiva.

meta