As declarações e os testes de unidade servem como documentação para uma base de código e como um meio de descobrir bugs. As principais diferenças são que afirmações funcionam como verificações de sanidade e veem entradas reais, enquanto testes de unidade são executados em entradas simuladas específicas e são testes contra uma única "resposta correta" bem definida. Quais são os méritos relativos do uso de afirmações versus testes de unidade como o principal meio de verificar a correção? Qual você acha que deveria ser enfatizado mais fortemente?
testing
unit-testing
assertions
dsimcha
fonte
fonte
:-)
Respostas:
As declarações são úteis para informar sobre o estado interno do programa . Por exemplo, que suas estruturas de dados têm um estado válido, por exemplo, que uma
Time
estrutura de dados não retém o valor de25:61:61
. As condições verificadas por afirmações são:Condições prévias, que garantem que o chamador mantém seu contrato,
Pós-condições, que garantem que o receptor mantenha seu contrato e
Invariantes, que garantem que a estrutura de dados sempre mantenha alguma propriedade após o retorno da função. Uma invariante é uma condição que é uma pré-condição e uma pós-condição.
Os testes de unidade são úteis para informar sobre o comportamento externo do módulo . Você
Stack
pode ter um estado consistente após apush()
chamada do método, mas se o tamanho da pilha não aumentar em três após ser chamado três vezes, isso é um erro. (Por exemplo, o caso trivial em que apush()
implementação incorreta verifica apenas as declarações e saídas.)A rigor, a principal diferença entre afirmações e testes de unidade é que os testes de unidade possuem dados de teste (valores para executar o programa), enquanto os de afirmações não. Ou seja, você pode executar seus testes de unidade automaticamente, enquanto não pode dizer o mesmo para afirmações. Para o início desta discussão, assumi que você está falando sobre a execução do programa no contexto de testes de funções de ordem superior (que executam todo o programa e não conduzem módulos como testes de unidade). Se você não está falando sobre testes de função automatizados como meio de "ver entradas reais", então claramente o valor está na automação e, portanto, os testes de unidade vencem. Se você está falando sobre isso no contexto de testes de função (automatizados), veja abaixo.
Pode haver alguma sobreposição no que está sendo testado. Por exemplo, a
Stack
pós-condição de uma pessoa pode realmente afirmar que o tamanho da pilha aumenta em um. Mas há limites para o que pode ser executado nessa afirmação: ele também deve verificar se o elemento superior foi o que acabou de ser adicionado?Para ambos, o objetivo é aumentar a qualidade. Para testes de unidade, o objetivo é encontrar erros. Para afirmações, o objetivo é facilitar a depuração, observando estados inválidos do programa assim que eles ocorrem.
Observe que nenhuma técnica verifica a correção. De fato, se você realizar testes de unidade com o objetivo de verificar se o programa está correto, provavelmente encontrará um teste desinteressante que sabe que funcionará. É um efeito psicológico: você fará o que for para atingir seu objetivo. Se seu objetivo é encontrar erros, suas atividades refletirão isso.
Ambos são importantes e têm seus próprios propósitos.
[Como nota final sobre as afirmações: para obter o máximo de valor, você precisa usá-las em todos os pontos críticos do seu programa, e não em algumas funções-chave. Caso contrário, a fonte original do problema pode ter sido mascarada e difícil de detectar sem horas de depuração.]
fonte
Ao falar sobre afirmações, lembre-se de que elas podem ser desativadas ao pressionar um botão.
Exemplo de uma afirmação muito ruim:
Por que isso é ruim? Porque nenhuma verificação de erro é feita se essa afirmação for ignorada devido à definição de algo como NDEBUG.
Um teste de unidade (provavelmente) apenas falha no código acima. Claro, ele fez o seu trabalho dizendo que algo deu errado, ou fez? Qual a probabilidade
malloc()
de falha no teste?As asserções são para fins de depuração quando um programador precisa sugerir que nenhum evento 'normal' causaria o disparo da asserção.
malloc()
falhar é, de fato, um evento normal, portanto nunca deve ser afirmado.Existem muitos outros casos em que asserções são usadas em vez de lidar adequadamente com coisas que podem dar errado. É por isso que as asserções têm uma má reputação e por que idiomas como o Go não as incluem.
Os testes de unidade são projetados para informar quando algo que você alterou quebrou outra coisa. Eles foram projetados para evitar que você (na maioria dos casos) passe por todos os recursos do programa (no entanto, os testadores são importantes para lançamentos) toda vez que você faz uma compilação.
Realmente não há nenhuma correlação distinta entre os dois, exceto os dois dizendo que algo deu errado. Pense em uma afirmação como um ponto de interrupção em algo em que você está trabalhando, sem precisar usar um depurador. Pense em um teste de unidade como algo que informa se você quebrou algo em que não está trabalhando.
fonte
Ambas são ferramentas usadas para ajudar a melhorar a qualidade geral do sistema que você está construindo. Depende muito do idioma que você está usando, do tipo de aplicativo que está criando e de onde é melhor gastar seu tempo. Sem mencionar que você tem algumas escolas de pensamento sobre isso.
Para começar, se você estiver usando um idioma sem uma
assert
palavra - chave, não poderá usar declarações (pelo menos não da maneira como estamos falando aqui). Por um longo tempo, o Java não teve umaassert
palavra - chave e várias linguagens ainda não. O teste de unidade torna-se um pouco mais importante. Em algumas linguagens, as asserções são executadas apenas quando um sinalizador é definido (novamente com Java aqui). Quando as proteções nem sempre estão lá, não é um recurso muito útil.Há uma escola de pensamento que diz que se você está "afirmar" algo, assim como você pode escrever um
if
/throw
bloco de exceção significativa. Esse processo de pensamento vem de muitas afirmações colocadas no início de um método para garantir que todos os valores estejam dentro dos limites. Testar suas pré-condições é uma parte muito importante de se ter uma pós-condição esperada.O teste de unidade é um código extra que deve ser escrito e mantido. Para muitos, isso é uma desvantagem. No entanto, com a colheita atual de estruturas de teste de unidade disponíveis, é possível gerar um número maior de condições de teste com comparativamente pouco código. Testes e "teorias" parametrizados realizarão o mesmo teste com um grande número de amostras de dados que podem descobrir alguns erros difíceis de encontrar.
Pessoalmente, acho que obtenho mais quilometragem com testes de unidade do que com declarações de aspersão, mas isso se deve às plataformas que desenvolvo na maioria das vezes (Java / C #). Outros idiomas têm um suporte de afirmação mais robusto e até o "Design by Contract" (veja abaixo) para fornecer ainda mais garantias. Se eu estivesse trabalhando com um desses idiomas, poderia usar o DBC mais do que o teste de unidade.
http://en.wikipedia.org/wiki/Design_by_contract#Languages_with_native_support
fonte