Devo creare oggetti finti da zero o modificare il risultato di chiamate reali in lingue debolmente tipizzate?

0

In risposta a il codice è testabile codice migliore? I showed in che modo il codice dipendente dal tempo può essere verificabile utilizzando i mock anziché modificare l'implementazione:

def time_of_day():
    return datetime.datetime.utcnow().strftime('%H:%M:%S')

Codice test:

@unittest.patch('datetime.datetime.utcnow')
def test_handle_leap_second(self, utcnow_mock):
    utcnow_mock.return_value = datetime.datetime(
        year=2015, month=6, day=30, hour=23, minute=59, second=60)
    actual = time_of_day()
    expected = '23:59:60'
    self.assertEquals(actual, expected)

Il problema qui (a parte Python che non gestisce i secondi bisestili ) è che il codice di test presuppone che utcnow restituirà un oggetto datetime.datetime in tutte le situazioni. Potrebbe essere vero in questo momento per questa funzione specifica con l'interprete corrente ecc., ma se il tipo di ritorno cambia per qualsiasi ragione il test passerà quando probabilmente dovrebbe fallire. Quindi per una robusta suite di test sarebbe meglio garantire che il valore di ritorno fittizio abbia la stessa classe del valore di ritorno della funzione originale. Questo è ovviamente possibile solo nelle lingue in cui il tipo di ritorno è applicato dal compilatore o dall'interprete. Puoi aggirare questo problema modificando un valore di ritorno della funzione originale piuttosto che crearne uno tuo:

utcnow_mock.return_value = datetime.datetime.utcnow().replace(
    year=2015, month=6, day=30, hour=23, minute=59, second=60)

Ora stiamo operando con un diverso insieme di ipotesi:

  • replace modifica l'oggetto restituito da utcnow invece di restituire qualche oggetto diverso . Questo non sarà un problema se le proprietà dell'oggetto rilevanti sono scrivibili.
  • utcnow restituisce sempre oggetti con la stessa classe.

Quale metodo è più probabile che generi una suite di test robusta? Tieni presente che, a differenza di questo esempio, la creazione e la modifica di un oggetto potrebbe essere più semplice della creazione con le proprietà corrette da zero.

    
posta l0b0 04.07.2015 - 17:27
fonte

1 risposta

1

Dipende da cosa intendi per "robusta suite di test".

Una possibile definizione sarebbe "i miei test non testano mai la cosa sbagliata, anche se i requisiti di base del sistema cambiano", e penso che questa sia la definizione alla quale ti stai proponendo con la descrizione del problema. Onestamente, penso che questo sia un problema irrisolvibile (cosa succede se nella prossima revisione della libreria, utcnow() non restituisce alcun valore e invece è destinato ad essere utilizzato per acquisire un blocco su una tabella DB?). Si noti inoltre che quando si richiede "non dare un falso positivo" (non si ha un test fallito se non ci sono effettivamente bug), di solito si devono tollerare alcuni falsi negativi (il test potrebbe dire che non c'è bug, ma in realtà c'è uno).

Un'altra possibile definizione potrebbe essere "il mio test rileva sempre quando un cambiamento potrebbe innescare un bug nel mio programma, in termini di come i requisiti sono stati compresi quando questo test è stato scritto". Penso che questa sia la definizione più comunemente usata (anche se molti di noi non pensano esplicitamente a queste definizioni né alla distinzione tra loro). In base a questa definizione, preferiresti usare gli oggetti mock piuttosto che mutare gli oggetti esistenti, ma se risultasse più conveniente mutazione degli oggetti esistenti rispetto a quelli finti, va bene lo stesso. L'intuizione chiave qui è che se sei preoccupato che utcnow() possa cambiare in modo tale da introdurre un bug nel tuo sistema, allora non dovresti scrivere test solo per verificare che time_of_day() funzioni come ti aspetti , ma dovresti anche scrivere test che verificano che utcnow() funzioni come previsto.

Si noti che con questa filosofia puntiamo a "non falsi negativi" (se c'è un bug, dovrebbe essere il caso che alcuni test falliscano), e quindi tolleriamo un po 'di falsi positivi (a volte un il test dirà che c'è un bug, ma dopo l'ispezione, ci rendiamo conto che in realtà non ci sono bug, il test stava solo testando la cosa sbagliata.

    
risposta data 04.07.2015 - 22:05
fonte

Leggi altre domande sui tag