Domanda

Mi sono imbattuto in questa situazione questo pomeriggio, quindi ho pensato di chiedervi cosa fate.

Disponiamo di un generatore di password casuale per la reimpostazione delle password degli utenti e, mentre risolvevo un problema, ho deciso di spostare la routine nel mio sistema di test (in lenta crescita).

Voglio verificare che le password generate siano conformi alle regole che abbiamo stabilito, ma ovviamente i risultati della funzione saranno randomizzati (o, beh, pseudo-randomizzati).

Cosa fareste nel test unitario?Generare un sacco di password, controllare che passino tutte e considerarle abbastanza buone?

È stato utile?

Soluzione

Un test unitario dovrebbe fare la stessa cosa ogni volta che viene eseguito, altrimenti potresti imbatterti in una situazione in cui il test unitario fallisce solo occasionalmente e il debug potrebbe essere davvero complicato.

Prova a seminare il tuo pseudo-randomizzatore con lo stesso seme ogni volta (nel test, cioè, non nel codice di produzione).In questo modo il tuo test genererà ogni volta lo stesso insieme di input.

Se non puoi controllare il seed e non c'è modo di impedire che la funzione che stai testando venga randomizzata, allora immagino che tu sia bloccato con un test unitario imprevedibile.:(

Altri suggerimenti

La funzione è un'ipotesi che per tutti gli input, l'output sia conforme alle specifiche.Il test unitario è un tentativo di falsificare tale ipotesi.Quindi sì, la cosa migliore che puoi fare in questo caso è generare una grande quantità di output.Se tutti superano le tue specifiche, puoi essere ragionevolmente sicuro che la tua funzione funzioni come specificato.

Considera l'idea di mettere il generatore di numeri casuali all'esterno di questa funzione e di passargli un numero casuale, rendendo la funzione deterministica, invece di farle accedere direttamente al generatore di numeri casuali.In questo modo, puoi generare un gran numero di input casuali nel tuo test cablaggio, passarli tutti alla tua funzione e testare gli output.Se uno fallisce, registra qual è quel valore in modo da avere un caso di test documentato.

Oltre a testarne alcuni per assicurarmi che passino, scriverei un test per assicurarmi che la password sia quella rottura le regole falliscono.

C'è qualcosa nel codebase che controlla le password generate per assicurarsi che siano sufficientemente casuali?In caso contrario, potrei provare a creare la logica per controllare le password generate, testarle e quindi puoi affermare che il generatore di password casuali funziona (poiché quelle "cattive" non verranno fuori).

Una volta che hai questa logica, probabilmente puoi scrivere un test di tipo di integrazione che genererebbe un sacco di password e lo passerebbe attraverso la logica, a quel punto avresti un'idea di quanto sia "buona" la generazione di password casuali.

Bene, considerando che sono casuali, non c'è davvero modo di esserne sicuri, ma testare 100.000 password dovrebbe chiarire la maggior parte dei dubbi :)

Potresti seminare il tuo generatore di numeri casuali con un valore costante per ottenere risultati non casuali e testare tali risultati.

Presumo che le password immesse dall'utente siano conformi alle stesse restrizioni di quelle generate casualmente.Quindi probabilmente vorrai avere un set di password statiche per verificare le condizioni note, e quindi avrai un ciclo che esegue i controlli dinamici delle password.La dimensione del circuito non è troppo importante, ma dovrebbe essere abbastanza grande da ottenere quella calda sensazione confusa dal tuo generatore, ma non così grande da richiedere un'eternità per l'esecuzione dei test.Se qualcosa emerge nel tempo, puoi aggiungere tali casi al tuo elenco statico.

A lungo termine, tuttavia, una password debole non interromperà il tuo programma e la sicurezza della password ricade nelle mani dell'utente.Quindi la tua priorità sarebbe quella di assicurarti che la generazione dinamica e il controllo della forza non rompano il sistema.

Senza sapere quali sono le tue regole è difficile dirlo con certezza, ma supponendo che siano qualcosa del tipo "la password deve contenere almeno 8 caratteri con almeno una lettera maiuscola, una lettera minuscola, un numero e un carattere speciale" allora è impossibile anche con la forza bruta controllare quantità sufficienti di password generate per dimostrare che l'algoritmo è corretto (poiché ciò richiederebbe più di 8^70 = 1,63x10^63 controlli a seconda di quanti caratteri speciali si designano per l'uso, il che richiederebbe un tempo molto , tempi molto lunghi per il completamento).

Alla fine, tutto ciò che puoi fare è testare quante più password possibile e, se qualcuno infrange le regole, allora saprai che l'algoritmo non è corretto.Probabilmente la cosa migliore da fare è lasciarlo acceso tutta la notte, e se tutto va bene al mattino probabilmente starai bene.

Se vuoi essere doppiamente sicuro in produzione, implementa una funzione esterna che chiami la funzione di generazione della password in un ciclo e la controlli rispetto alle regole.Se fallisce, registra un errore che indica questo (così sai che devi risolverlo) e genera un'altra password.Continua finché non ne ottieni uno che soddisfi le regole.

Puoi anche esaminare i test di mutazione (Giullare per Giava, Difficoltà per Rubino)

A mio modesto parere non vuoi un test che a volte passa e a volte fallisce.Alcune persone potrebbero addirittura ritenere che questo tipo di test non sia un test unitario.Ma l'idea principale è assicurarsi che la funzione sia corretta quando vedi la barra verde.

Tenendo presente questo principio potresti provare a eseguirlo un numero ragionevole di volte in modo che la possibilità di avere un falso corretto sia quasi zero.Tuttavia, un singolo fallimento del test ti costringerà a fare test più estesi oltre al debugging dell'errore.

Utilizzare un seme casuale fisso o renderlo riproducibile (ad esempio:derivano dal giorno attuale)

Innanzitutto, usa un seed per il tuo PRNG.Il tuo input non è più casuale ed elimina il problema dell'output imprevedibile, ad es.ora il tuo test unitario è deterministico.

Ciò tuttavia non risolve il problema di testare l'implementazione, ma ecco un esempio di come può essere testato un tipico metodo che si basa sulla casualità.

Immagina di aver implementato una funzione che prende una raccolta di biglie rosse e blu e ne sceglie una a caso, ma è possibile assegnare un peso alla probabilità, ad es.pesi di 2 e 1 significherebbero che le biglie rosse hanno il doppio delle probabilità di essere raccolte rispetto alle biglie blu.

Possiamo testarlo impostando il peso di una scelta a zero e verificando che in tutti i casi (in pratica, per una grande quantità di input di test) Sempre ottenere ad es.marmi blu.Invertire i pesi dovrebbe quindi dare il risultato opposto (tutte le biglie rosse).

Ciò non garantisce che la nostra funzione si comporti come previsto (se passiamo in un numero uguale di biglie rosse e blu e abbiamo pesi uguali, otteniamo sempre una distribuzione 50/50 su un gran numero di prove?) ma in pratica lo è spesso sufficiente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top