Pergunta

Eu encontrei essa situação esta tarde, então pensei em perguntar o que vocês fazem.

Temos um gerador de senha randomizada para redefinições de senha do usuário e, ao corrigir um problema, decidi mover a rotina para o meu chicote de teste (de crescimento lento).

Quero testar que as senhas geradas em conformidade com as regras que estabelecemos, mas é claro que os resultados da função serão randomizados (ou, bem, pseudo-randomizados).

O que vocês fariam no teste de unidade? Gere um monte de senhas, verifique se todas elas passam e consideram isso bom o suficiente?

Foi útil?

Solução

Um teste de unidade deve fazer a mesma coisa toda vez que ele é executado; caso contrário, você poderá encontrar uma situação em que o teste de unidade só falha ocasionalmente, e isso pode ser uma dor real de depurar.

Tente semear seu pseudo-aleator com a mesma semente sempre (no teste, ou seja, não no código de produção). Dessa forma, seu teste gerará o mesmo conjunto de entradas todas as vezes.

Se você não pode controlar a semente e não há como impedir que a função que você esteja testando seja randomizada, acho que você está preso a um teste de unidade imprevisível. :(

Outras dicas

A função é uma hipótese de que, para todas as entradas, a saída está em conformidade com as especificações. O teste de unidade é uma tentativa de falsificar essa hipótese. Então, sim, o melhor que você pode fazer neste caso é gerar uma grande quantidade de saídas. Se todos eles passarem sua especificação, você poderá ter certeza de que sua função funciona conforme especificado.

Considere colocar o gerador de números aleatórios fora dessa função e passar um número aleatório, tornando a função determinística, em vez de acessar diretamente o gerador de números aleatórios. Dessa forma, você pode gerar um grande número de entradas aleatórias em seu chicote de teste, passar todas para sua função e testar as saídas. Se alguém falhar, registre o que é esse valor para que você tenha um caso de teste documentado.

Além de testar alguns para garantir que eles passem, eu escreveria um teste para garantir que as senhas que parar as regras falham.

Existe algo na base de código que está verificando as senhas geradas para garantir que sejam aleatórias o suficiente? Caso contrário, posso procurar criar a lógica para verificar as senhas geradas, testar isso e, em seguida, você pode afirmar que o gerador de senha aleatória está funcionando (como as "ruins" não saem).

Depois de obter essa lógica, você provavelmente pode escrever um teste de tipo de integração que geraria cargas de barco de senhas e passá -lo pela lógica; nesse momento, você terá uma idéia de como é "bom" sua senha aleatória.

Bem, considerando que eles são aleatórios, não há realmente maneira de ter certeza, mas testar para 100.000 senha deve limpar a maioria das dúvidas :)

Você pode semear seu gerador de números aleatórios com um valor constante para obter resultados não aleatórios e testar esses resultados.

Estou assumindo que as senhas digitadas pelo usuário estão em conformidade com as mesmas restrições que as geradas aleatórias. Portanto, você provavelmente deseja ter um conjunto de senhas estáticas para verificar as condições conhecidas e, em seguida, terá um loop que faz as verificações de senha dinâmica. O tamanho do loop não é muito importante, mas deve ser grande o suficiente para que você tenha essa sensação quente e confusa do seu gerador, mas não tão grande que seus testes levam uma eternidade para correr. Se alguma coisa surge com o tempo, você poderá adicionar esses casos à sua lista estática.

A longo prazo, porém, uma senha fraca não vai quebrar seu programa e a segurança da senha cai nas mãos do usuário. Portanto, sua prioridade seria garantir que a geração dinâmica e a verificação de força não quebrem o sistema.

Sem saber quais são suas regras, é difícil dizer com certeza, mas supondo Impossível mesmo com força bruta para verificar quantidades suficientes de senhas geradas para provar que o algoritmo está correto (pois isso exigiria em algum lugar acima de 8^70 = 1,63x10^63 verifica, dependendo de quantos caracteres especiais você designou para uso, o que levaria muito , muito tempo para concluir).

Por fim, tudo o que você pode fazer é testar o máximo de senhas possível e, se houver alguma quebra das regras, sabe que o algoritmo está incorreto. Provavelmente, a melhor coisa a fazer é deixá -lo correndo durante a noite e, se estiver tudo bem de manhã, você provavelmente ficará bem.

Se você deseja ter certeza duplamente na produção, implemente uma função externa que chama a função de geração de senha em um loop e a verifique as regras. Se falhar, registre um erro indicando isso (para que você saiba que precisa corrigi -lo) e gerar outra senha. Continue até obter um que atenda às regras.

Você também pode procurar testes de mutação (Bobinho Para Java, Heckle Para Ruby)

Na minha humilde opinião, você não deseja um teste que às vezes passa e às vezes falha. Algumas pessoas podem até considerar que esse tipo de teste não é um teste de unidade. Mas a idéia principal é ter certeza de que a função está bem quando você vê a barra verde.

Com esse princípio em mente, você pode tentar executá -lo um número razoável de vezes, para que a chance de ter um falso correto seja quase Cero. No entanto, a falha única da UNE do teste o forçará a fazer testes mais extensos, além de debbugar a falha.

Use semente aleatória fixa ou faça com que seja reproduzível (ou seja: deriva do dia atual)

Em primeiro lugar, use uma semente para o seu PRNG. Sua entrada não é mais aleatória e se livra do problema da saída imprevisível - ou seja, seu teste de unidade é determinístico.

No entanto, isso não resolve o problema de testar a implementação, mas aqui está um exemplo de como um método típico que se baseia na aleatoriedade pode ser testado.

Imagine que implementamos uma função que pega uma coleção de bolinhas de gude vermelho e azul e escolhe um aleatoriamente, mas uma ponderação pode ser atribuída à probabilidade, ou seja, pesos de 2 e 1 significariam mármores azuis.

Podemos testar isso definindo o peso de uma opção para zero e verificar isso em todos os casos (na prática, por uma grande quantidade de entrada de teste) nós sempre Pegue, por exemplo, bolinhas azuis. A reversão dos pesos deve dar o resultado oposto (todas as mármores vermelhos).

Isso não garante que nossa função esteja se comportando como pretendido (se passarmos em um número igual de bolinhas de gude vermelho e azul e terem pesos iguais, sempre obtemos uma distribuição de 50/50 em um grande número de ensaios?) Mas na prática é muitas vezes suficiente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top