Asserts são úteis para falar sobre o estado interno do programa . Por exemplo, que suas estruturas de dados têm um estado válido, por exemplo, que uma estrutura de dados Time
não manterá o valor de 25:61:61
. As condições verificadas por afirmações são:
-
Pré-condições, que garantem que o chamador mantenha seu contrato,
-
Postconditions, que garantem que o candidato mantenha seu contrato e
-
Invariantes, que asseguram que a estrutura de dados sempre mantenha alguma propriedade após a função retornar. Um invariante é uma condição que é uma pré-condição e uma pós-condição.
Testes de unidade são úteis para falar sobre o comportamento externo do módulo . Seu Stack
pode ter um estado consistente após o método push()
ser chamado, 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 a implementação push()
incorreta apenas verifica as declarações e saídas.)
Estritamente falando, a principal diferença entre testes de unidade e testes é que os testes de unidade possuem dados de teste (valores para executar o programa), enquanto que as declarações não. Isto é, você pode executar seus testes unitários automaticamente, enquanto você não pode dizer o mesmo para asserções. Por causa desta discussão, eu assumi que você está falando sobre a execução do programa no contexto de testes de função de ordem superior (que executam o programa inteiro e não conduzem módulos como testes de unidade). Se você não está falando sobre testes de função automatizada como o meio de "ver insumos reais", então, claramente, o valor está na automação e, portanto, os testes de unidade ganhariam. 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, uma pós-condição de Stack
pode realmente afirmar que o tamanho da pilha aumenta em um. Mas há limites para o que pode ser feito nessa afirmação: ele também deve verificar se o elemento principal é o que acabou de ser adicionado?
Para ambos, o objetivo é aumentar a qualidade. Para testes unitários, o objetivo é encontrar bugs. Para asserções, o objetivo é tornar a depuração mais fácil observando os estados de programa inválidos assim que eles ocorrem.
Note que a técnica nenhuma verifica a correção. Na verdade, se você realizar testes unitários com o objetivo de verificar se o programa está correto, provavelmente você fará testes desinteressantes que você sabe que funcionarão. É um efeito psicológico: você fará o que for para atingir seu objetivo. Se seu objetivo é encontrar bugs, suas atividades refletirão isso.
Ambos são importantes e têm seus próprios propósitos.
[Como nota final sobre asserções: Para obter o máximo de valor, você precisa usá-las em todos os pontos críticos do programa e não em algumas funções importantes. Caso contrário, a fonte original do problema pode ter sido mascarada e difícil de detectar sem horas de depuração.]