Os testes de unidade são realmente usados ​​como documentação?

22

Não consigo contar o número de vezes que leio declarações na veia de 'testes de unidade são uma fonte muito importante de documentação do código em teste'. Não nego que sejam verdadeiras.

Mas, pessoalmente, nunca me vi usando-os como documentação. Para as estruturas típicas que eu uso, as declarações do método documentam seu comportamento e é tudo o que preciso. E suponho que os testes de unidade façam backup de tudo o que está mencionado nessa documentação, além de provavelmente algumas coisas mais internas; portanto, por um lado, duplica a ducumentação, enquanto, por outro, pode adicionar mais algumas coisas irrelevantes.

Portanto, a pergunta é: quando os testes de unidade são usados ​​como documentação? Quando os comentários não cobrem tudo? Por desenvolvedores estendendo a fonte? E o que eles expõem que podem ser úteis e relevantes que a própria documentação não pode expor?

stijn
fonte
4
Nunca pensei em usar o teste de unidade diretamente como documentação. Eu acho que os testes de unidade geralmente são ilegíveis, porque muitos desenvolvedores não levam tempo para escrevê-los claramente.
SuperM
10
Os comentários podem estar errados.
2
Eu sei que você está perguntando especificamente sobre testes de unidade, mas também observaria que testes de integração / sistema também são documentação realmente útil, apenas em um nível diferente
jk.
3
Eu já vi testes de unidade que seriam melhor caracterizados como "experimentos de unidade". Sua dependência de fatores externos era quase o suficiente para torná-los quase inúteis. Eles também não eram muito claros. (Sim, eu tenho um objetivo de longo prazo para refatorar-los a ser melhor, mas eu fazer outras coisas também ...)
Donal Fellows
4
Os testes de unidade @Ant invocam o código real e documentam a resposta esperada e a comparam com a resposta real. Se o código invocado está correto ou não, não é o ponto - os testes documentam como invocá-lo.

Respostas:

17

Eles NÃO são uma Documentação de Referência ABSOLUTA

Observe que muitas das opções a seguir também se aplicam aos comentários, pois eles podem ficar fora de sincronia com o código, como testes (embora seja menos aplicável).

Portanto, no final, a melhor maneira de entender o código é ter um código de trabalho legível .

Se possível e não escrever seções de código de baixo nível conectadas por cabo ou condições particularmente complicadas, uma documentação adicional será crucial.

  • Os testes podem estar incompletos:
    • A API foi alterada e não foi testada,
    • A pessoa que escreveu o código escreveu os testes para os métodos mais fáceis de testar primeiro, em vez dos métodos mais importantes para testar, e depois não teve tempo para concluir.
  • Os testes podem ser obsoletos.
  • Os testes podem sofrer um curto-circuito de maneiras não óbvias e não serem realmente executados.

Mas eles ainda são um complemento útil da documentação

No entanto, quando tenho dúvidas sobre o que uma determinada classe faz, especialmente se for bastante demorada, obscura e sem comentários (você sabe o tipo ...), tento rapidamente encontrar suas classes de teste e verificar:

  • o que eles realmente tentam verificar (dá uma dica sobre os petiscos mais importantes, exceto se o desenvolvedor cometeu o erro mencionado acima ao implementar apenas os testes "fáceis"),
  • e se houver esquinas.

Além disso, se escritas usando um estilo BDD , elas fornecem uma definição bastante boa do contrato da classe . Abra seu IDE (ou use grep) para ver apenas nomes de métodos e tada: você tem uma lista de comportamentos.

Regressões e bugs também precisam de testes

Além disso, é uma boa prática escrever testes para regressão e relatórios de erros: você corrige algo, escreve um teste para reproduzir o caso. Ao olhar para eles, é uma boa maneira de encontrar o relatório de erros relevante e todos os detalhes sobre um problema antigo, por exemplo.

Eu diria que eles são um bom complemento para a documentação real e, pelo menos, um recurso valioso a esse respeito. É uma boa ferramenta, se usada corretamente. Se você começar a testar no início do projeto e criar um hábito, poderá ser uma documentação de referência muito boa. Em um projeto existente com maus hábitos de codificação que já cheiram mal a base de código, manuseie-os com cuidado.

haylem
fonte
Posso perguntar por que fui derrotado? O que te incomoda lá ou o que você não concorda?
haylem
2
A melhor parte (IMO) do seu argumento é escrita na menor fonte - a melhor maneira de entender o código é ter um código legível em primeiro lugar. Eu mudaria isso para "código legível e funcional", mas concordo. Então, se você olhar para os testes de unidade novamente - os testes em execução estão funcionando como código (e, como todo código, devem ser legíveis), por isso é realmente uma documentação muito boa (se muitas vezes local demais) quando bem feita.
Joris Timmermans
@MadKeithV: obrigado. Atualizei para "código legível e funcional" e subi um pouco mais.
haylem
11

Uma interpretação é que os testes de unidade são "documentação executável". Você pode executar os testes de unidade com o código e ele informará se ele ainda está executando como estava quando os testes foram escritos para serem aprovados ou não. Dessa forma, a unidade testa "documenta" a funcionalidade do sistema em algum momento, de maneira executável.

Por outro lado, também raramente eu realmente li o código de teste de unidade como "documentação" para entender a funcionalidade. Um único teste de unidade é muito localizado, específico e abstrato, de forma a poder lhe dizer muito sobre o sistema real que está por trás da classe que está sendo testada.

Joris Timmermans
fonte
5

Se por documentação você quer dizer que eu quero algo para descobrir como o código funciona , os testes de unidade são pequenos exemplos perfeitos de como as unidades do código funcionam nos casos esperado , de borda e de erro (também conhecido como erro ). Além disso, seus testes podem ser criados antes que o código seja gravado, subjacente ao que o código deve fazer do ponto de vista de negócios / requisitos.

Eles estão substituindo a documentação? Não.

Eles são um adendo útil à documentação? Sim.

Sardathrion - Restabelecer Monica
fonte
4

Vejo testes de unidade como:

  • uma maneira de provar que a documentação está correta (supondo que a documentação corresponda à implementação da API).
  • uma maneira de demonstrar para um desenvolvedor como usar um recurso específico; os equipamentos de teste de unidade / teste de unidade são geralmente pequenos o suficiente para que você possa aprender rapidamente com ele.
  • e, obviamente, detectar qualquer erro de regressão.

Até certo ponto, eles podem ser vistos como um complemento para uma documentação existente, mas não como a documentação.

David Andreoletti
fonte
3

Vou responder à sua pergunta fazendo outra.

Com que frequência ao trabalhar com uma nova API / rotina você solicitou ajuda para procurar um exemplo de código do que você está tentando usar? Na falta de mudança para o Google para uma pesquisa on-line de exemplos de código?

É exatamente quando você usaria testes de unidade como documentação.

  • De fato, os testes de unidade podem ser um pouco mais rigorosos que os exemplos de código normais, porque você deve ter vários testes (exemplos).
  • Espero que seus testes de unidade ilustrem o uso adequado . Por exemplo, eles mostram claramente todas as dependências essenciais por meio de objetos normais ou objetos simulados. (Caso contrário, eles não são particularmente bons testes de unidade.)
  • NOTA: Se seus comentários ou "documentação normal" fornecerem exemplos de código, você estará violando os princípios DRY. E esses exemplos de código podem facilmente ficar incorretos ao longo do tempo, enquanto há significativamente menos chances disso com testes de unidade executados regularmente.
  • Se os testes de unidade forem completos (geralmente um grande se ), eles deverão fornecer informações adicionais:
    • Todos os casos de borda conhecidos estão claramente ilustrados.
    • Todas as exceções esperadas que podem ser lançadas.
    • Todos os erros encontrados anteriormente (isso é provavelmente mais útil ao estender a unidade sob teste do que ao escrever um novo cliente para a unidade).
    • Todas as regras de negócios subjacentes associadas à unidade. (caso existam)

Eu suspeito que existem algumas razões pelas quais o teste de unidade não costuma ser usado como documentação, embora possa ser um excelente complemento para a documentação mais tradicional:

  • Atrevo-me a sugerir que frequentemente os testes em si não são suficientemente bem escritos para esse fim. Outras respostas já aludiram a testes que são:
    • Incompleto.
    • Confuso. (Vi casos de teste que não chamam o método sob teste diretamente - você vai a 3/4 dos níveis na pilha de chamadas antes que ela seja chamada e as pré-condições para chamar o método estão espalhadas em lugares diferentes em uma hierarquia de classes complexa. )
    • Desatualizado. (geralmente os testes devem falhar quando estão desatualizados, mas esse nem sempre é o caso).
  • Geralmente, existem muitos exemplos de uso disponíveis no código de produção sempre que surgir a necessidade de um exemplo.
  • A unidade em teste é tão bem escrita (auto-documentada) que os métodos não precisam de exemplos. Eu gostaria!
  • Na minha experiência como programador, tendemos a gostar bastante de entrar no fundo do poço e RTFM na próxima terça-feira ...
  • Documentação e comentários que violam o princípio DRY.
Desiludido
fonte
2

Os testes de unidade TL; DR e os comentários da API são complementares - algumas coisas são melhor descritas no código e outras na prosa.

Os testes de unidade são úteis principalmente para documentar casos especiais e condições de borda difíceis (e complicadas) de descrever nos comentários da API. Além disso, os comentários da API geralmente são direcionados para pessoas que desejam usar a API.

Se você deseja modificar o código, normalmente há muito mais que você precisa saber, e parte disso é difícil de colocar em comentários (e esses comentários ficam obsoletos rapidamente). Nesse caso, um teste de unidade também funciona como documentação.

Um exemplo: você tem um método m (a, b)que executa um determinado cálculo. Devido aos requisitos de compatibilidade com versões anteriores, ele deve incluir entradas de casos especiais de a=0e a=-1, mas somente se bfor NULL. Colocar isso em um comentário é complicado, detalhado e provavelmente ficará obsoleto se o requisito for removido posteriormente.

Se você fizer alguns testes de unidade que verificam o comportamento de m(0, NULL), m(-1, x)obtém vários benefícios:

  • A descrição do comportamento correto é clara, os equívocos são reduzidos
  • As pessoas não podem ignorar o requisito quando alteram o código, diferente de um comentário
sleske
fonte
mas, por exemplo, se esse comportamento não estiver documentado no comentário, um usuário poderá obter resultados inesperados para esse caso extremo. O que não é exatamente uma coisa boa.
Stijn
@stijn: Verdadeiro. Nesse caso, a melhor maneira seria provavelmente fazer uma breve menção do caso especial nos documentos, além dos testes de unidade para obter detalhes confusos.
sleske