Outras respostas são boas, então vou tentar acertar alguns pontos que eles perderam coletivamente até agora.
Eu escrevi (e testei exaustivamente) software para fazer o processamento de imagens usando o Synthetic Aperture Radar (SAR). É de natureza científica / numérica (há muita geometria, física e matemática envolvidas).
Algumas dicas (para testes gerais científicos / numéricos):
1) Use inversos. Qual é o fft
de [1,2,3,4,5]
? Nenhuma idéia. O que é ifft(fft([1,2,3,4,5]))
? Deve ser [1,2,3,4,5]
(ou próximo a isso, erros de ponto flutuante podem aparecer). O mesmo vale para o caso 2D.
2) Use afirmações conhecidas. Se você escrever uma função determinante, pode ser difícil dizer qual é o determinante de uma matriz aleatória de 100x100. Mas você sabe que o determinante da matriz de identidade é 1, mesmo que seja 100x100. Você também sabe que a função deve retornar 0 em uma matriz não-invertível (como 100x100 de todos os 0s).
3) Use afirmações aproximadas em vez de exata afirma. Eu escrevi um código para o processamento de SAR que registraria duas imagens gerando pontos de empate que criam um mapeamento entre imagens e, em seguida, fazendo uma dobra entre eles para fazê-los corresponder. Ele poderia se registrar em um nível de sub-pixel. A priori, é difícil dizer qualquer coisa sobre como o registro de duas imagens pode parecer. Como você pode testá-lo? Coisas como:
EXPECT_TRUE(register(img1, img2).size() < min(img1.size(), img2.size()))
já que você só pode se registrar em partes sobrepostas, a imagem registrada deve ser menor ou igual à sua menor imagem, e também:
scale = 255
EXPECT_PIXEL_EQ_WITH_TOLERANCE(reg(img, img), img, .05*scale)
desde que uma imagem registrada a si mesma deve estar CLOSE a si mesma, mas você pode experimentar um pouco mais do que erros de ponto flutuante devido ao algoritmo em mãos, então verifique se cada pixel está dentro de +/- 5% da faixa dos pixels pode assumir (0-255 é em escala de cinzentos, comum no processamento de imagens). O resultado deve ter pelo menos o mesmo tamanho da entrada.
Você pode até mesmo testar a fumaça (ou seja, chamá-lo e verificar se ele não falha). Em geral, essa técnica é melhor para testes maiores em que o resultado final não pode ser (facilmente) calculado a priori para executar o teste.
4) Use OR STORE uma semente numérica aleatória para o seu RNG.
As execuções do precisam ser reproduzíveis. É falso, no entanto, que a única maneira de obter uma execução reproduzível é fornecer uma semente específica para um gerador de números aleatórios. Às vezes, o teste de aleatoriedade é valioso. Eu vi / ouvi falar de bugs no código científico que surgem em casos degenerados que foram gerados aleatoriamente (em algoritmos complicados, pode ser difícil ver o que o caso degenerado é mesmo ). Em vez de sempre chamar sua função com a mesma semente, gere uma semente aleatória, use essa semente e registre o valor da semente. Dessa forma, cada execução tem uma semente aleatória diferente, mas se ocorrer uma falha, você poderá executar novamente o resultado usando a semente que você registrou para depurar. Eu realmente usei isso na prática e isso atrapalhou um bug, então eu imaginei que eu iria mencionar isso. É certo que isso só aconteceu uma vez, e tenho certeza de que nem sempre vale a pena fazer, então use essa técnica com prudência. Aleatório com a mesma semente é sempre seguro, no entanto. Desvantagem (ao invés de usar a mesma semente o tempo todo): Você precisa registrar suas execuções de teste. Upside: correção e bug nuking.
Seu caso particular
1) Teste que um taskArray
vazio retorna 0 (confirmação conhecida).
2) Gere entradas aleatórias de forma que task.time > 0
, task.due > 0
, e task.importance > 0
para todos task
s, e asseverar que o resultado é maior que 0
(afirmação aproximada, entrada aleatória) . Você não precisa ficar louco e gerar sementes aleatórias, seu algoritmo não é complexo o suficiente para justificar isso. Há cerca de 0 chance de pagar: basta manter o teste simples.
3) Teste se task.importance == 0
para todos task
s, o resultado é 0
(afirmativa )
4) Outras respostas abordaram isso, mas pode ser importante para o seu caso particular : Se você estiver fazendo uma API para ser consumida por usuários fora de sua equipe, é necessário para testar os casos degenerados. Por exemplo, se workPerDay == 0
, certifique-se de lançar um erro bonito que informe ao usuário que é uma entrada inválida. Se você não está fazendo uma API, e é apenas para você e sua equipe, você provavelmente pode pular esta etapa e simplesmente se recusar a chamá-la com o caso degenerado.
HTH.