DRY, string, e unit test

6

Ho una domanda ricorrente durante la scrittura di unit test per il codice che implica valori di stringa costante.

Prendiamo un esempio di un metodo / funzione che esegue qualche elaborazione e restituisce una stringa contenente una costante predefinita. In Python, sarebbe qualcosa di simile:

STRING_TEMPLATE = "/some/constant/string/with/%s/that/needs/interpolation/"

def process(some_param):
    # We do some meaningful work that gives us a value
    result = _some_meaningful_action()
    return STRING_TEMPLATE % result

Se voglio test unitario process , uno dei miei test controllerà il valore restituito. È qui che mi chiedo quale sia la soluzione migliore.

Nel mio test di unità, posso:

  1. applica DRY e utilizza la costante già definita
  2. ripeti me stesso e riscrivo l'intera stringa
def test_foo_should_return_correct_url():
    string_result = process()

    # Applying DRY and using the already defined constant
    assert STRING_TEMPLATE % "1234" == string_result

    # Repeating myself, repeating myself
    assert "/some/constant/string/with/1234/that/needs/interpolation/" == url

Il vantaggio che vedo nel primo è che il mio test si interromperà se inserirò il valore di stringa sbagliato nella mia costante. L'inconveniente è che potrei riscrivere la stessa stringa più e più volte attraverso diversi test di unità.

    
posta Rodrigue 01.07.2012 - 18:33
fonte

4 risposte

9

C'è un piccolo avvertimento sul principio ASCIUTTO di cui molte persone non sono consapevoli: non essere così ossessionato dall'evitare la ripetizione di rimuovere "duplicati" di cose che sembrano essere le stesse ma in realtà concettualmente molto diverse.

Come esempio estremo, non proverai a rimuovere la ripetizione dei duplicati di "/ s", "th", "on", "nt", ecc all'interno della tua stringa originale.

Nel tuo esempio particolare, non devi / non preoccuparti dei dettagli di implementazione del tuo codice sotto test. (Ad esempio, utilizza STRING_TEMPLATE const.) Il tuo test si preoccupa del fatto che quando tu:

void Test() {
  DoSetup(...);
  ActualResult = DoProcess(...);
  Check(ActualResult == "/some/constant/string/with/1234/that/needs/interpolation/");
}

Il fatto che "/ some / constant / string / with / 1234 / that / needs / interpolation /" sia simile a STRING_TEMPLATE dovrebbe essere considerato casuale, non una violazione di DRY.

NOTE: This of course doesn't apply if you're actually testing some localisation aspect of your system, or if your system is affected by localisation that you initially set up via STRING_TEMPLATE. Because then the duplication is explicit.

    
risposta data 02.07.2012 - 02:21
fonte
2

Prima di tutto nel tuo esempio, stai effettivamente testando due cose in un singolo test, un test unitario dovrebbe testare solo una cosa alla volta.

Cosa dovresti provare:

  1. il valore costante è nel formato o un URL corretto con una singola posizione jolly % .
  2. la sostituzione della stringa all'interno della funzione build_url produce effettivamente un URL valido dato un input valido per la funzione

inoltre dovresti testare

  1. la costante non riesce a convalidare il valore costante se non è un pattern URL valido con una posizione % (e tutte le mutazioni di questo)
  2. la sostituzione delle stringhe all'interno della funzione non riesce a creare URL validi con input non valido

Questi dovrebbero essere due test unitari separati.

    
risposta data 01.07.2012 - 19:20
fonte
1

Di solito preferisco specificare manualmente il risultato previsto. Sebbene sia improbabile che l'interpolazione della stringa nell'esempio si interrompa, potrebbe esserci un caso in cui si utilizza una libreria di terze parti per creare il risultato. L'uso dei risultati manuali rivelerà le incompatibilità di versione in queste librerie. Inoltre, c'è sempre il pericolo di strane circostanze ambientali che potrebbero interrompere la funzione, come le impostazioni locali, la codifica, le piattaforme a 32/64 bit o simili. A volte, quelli effettivamente rompono la funzione. Altre volte, hanno appena superato i test unitari con i risultati digitati manualmente. In entrambi i casi, vale la pena controllare.

Se si testano le funzioni senza effetti collaterali, è possibile utilizzare test basati sui dati, che consente di mantenere uniti gli input di test e le uscite previste.

Tuttavia, nel tuo particolare esempio, potrebbe essere una buona idea non codificare il URL_TEMPLATE , ma leggerlo da qualche file di configurazione. Ciò faciliterà la transizione tra diversi ambienti.

    
risposta data 01.07.2012 - 19:24
fonte
-2

Questo è un buon candidato per "Cose che non dovrebbero essere testate da unità".

Quale logica aziendale stai testando?

Che la costante è impostata correttamente? Il test sta semplicemente ripetendo il codice (che è un segno che non dovresti testarlo).

Che la lingua sta facendo correttamente la sostituzione delle stringhe? Non è compito tuo testare la lingua.

    
risposta data 01.07.2012 - 18:38
fonte

Leggi altre domande sui tag