2012-06-11 6 views
5

Ci sono alcuni domini applicativi (ad esempio GameDev) in cui molte funzioni dovrebbero essere create usando valori casuali per produrre il loro output. Uno degli esempi è presentato di seguito:Come convalidare la correttezza delle funzioni che usano random?

def generate_key(monster_key_drop_coef): 
    key_letters = string.ascii_uppercase 
    rand = random.random() 
    if monster_key_drop_coef < rand: 
     return None 

    button = {} 
    button["type"] = random.choice([1,2,3]) 
    button["letter"] = random.choice(key_letters) 
    return button 

Questa funzione genera il calo dell'elemento in base a diverse operazioni casuali. Il problema appare se si desidera convalidare automaticamente la correttezza di questa funzione. I valori generati non sono deterministici e la scrittura di test di regressione sembra impossibile.

Le mie domande sono:

  1. È questo possibile scrivere test di regressione utili per questo tipo di funzioni?
  2. Esiste un approccio generale per la creazione di altri tipi di test in questo caso?
+4

Ci sono interi libri scritti su questo argomento. Esempio: http://www.johndcook.com/Beautiful_Testing_ch10.pdf –

+1

Mettere a punto l'RNG per fornire risultati noti (e quindi testare con output specifici per i quali è noto il risultato desiderato) è un approccio. –

risposta

3

Una delle unità di test utili è la seguente:

def test_generate_key(): 
    button_list = [] 
    for _ in range(1, 1000): 
     button_list.append(generate_key(0.2)) 

    is_all_none = True 
    is_not_none = False 
    for key in button_list: 
     is_all_none &= (key is None) 
     is_not_none |= (key is not None) 

    assert is_all_none == False 
    assert is_not_none == True 

convalida firma funzione, copre tutte le righe di codice (buona probabilità) di funzioni e passerà a 99,999% dei casi. Convalidato anche quella funzione ne produce qualche goccia almeno da 1000 e talvolta non genera drop. 0.2 è la probabilità di caduta di un articolo.

2

Vorrei riscrivere la funzione per utilizzare l'iniezione di dipendenza (il generatore di numeri casuali è passato come parametro alla funzione). Quindi puoi passare una simulazione di un generatore di numeri casuali per testare la tua funzione con diversi input "casuali" deterministici.

Ovviamente è anche possibile testare le asserzioni che non dipendono dai risultati della chiamata a caso. Ad esempio:

  • Le funzioni restituiscono Nessuno o un dict con i tasti "tipo" e "lettera".
  • Se viene restituito un dizionario, i valori sono del tipo e intervallo appropriati.

Non scriverei mai un annuncio che abbia risultati non deterministici, anche 1 su mille. Mi interessa ogni fallimento del test, e risultati stocastici sarebbero inquietanti. Sarebbe meglio incapsulare la casualità, in modo che la funzione possa essere testata indipendentemente dal generatore di numeri casuali.