Come faccio a testare la mia convalida senza essere troppo perfezionista, pur lasciando la maggior parte della logica testata?

4

Ad esempio, mi piacerebbe convalidare che il nome sia solo lettere ed abbia una lunghezza compresa tra 4 e 14 lettere. Ho il seguente codice nel modello:

validates: name, :format => { :with => /^[a-zA-Z]+$/,
                              :message => 'Name should be letters only. },
                 :length => { :minimum => 4, :maximum => 14 }

Quindi mi consente chiaramente di fare ciò che voglio.

Ma per quanto riguarda i test unitari, ho un po 'troppo perfezionismo, quindi ho impostato qualcosa come

invalid_names = ['1234',
                 'qwe',
                 '1%#$#$',
                 'Sam1',
                 '%',
                 random_string(15)] #I also have a test method to create random string with parametrized length

valid_names = %w['test',
                 'Travis',
                 'John',
                 random_string(5),
                 random_string(14),
                 random_string(4)]

e testare ciascuno di essi in un ciclo con asserzioni, come

invalid_names.each do |name|
    user = User.new(:name => name)
    user.save
    assert user.errors[:name].any?, "#{name} is valid."
end

Quindi funziona sicuramente alla grande. Ma è troppo prolisso (a causa di array di nomi validi / non validi e aggiunto il metodo random_string ), inoltre non posso essere sicuro che il mio test verifichi effettivamente tutti i simboli e le loro combinazioni possibili e tutte le lunghezze e cose, anche se sono decisamente sicuro che funzioni come previsto.

Quindi qual è il modo accettabile per testare la mia convalida senza essere troppo perfezionista, lasciando comunque la maggior parte della logica testata?

Sono appena finito in un trucco mentale per cercare di scrivere un codice perfetto solo per scrivere un codice perfetto e per dimenticare l'obiettivo principale: prodotto funzionante?

    
posta Konnigun 12.03.2013 - 12:29
fonte

4 risposte

7

Alcuni suggerimenti:

  • mai usa stringhe casuali per i test di unità se non ci sono motivi validi per farlo. Hanno un alto rischio di produrre casi non riproducibili. Se vuoi usare una stringa casuale, scegli la stringa casualmente una volta e l'hardcode che ha scelto la stringa nel test.

  • una vecchia saggezza di test è che non è possibile testare tutte le possibili combinazioni di dati di input se l'intervallo consentito di valori di input è troppo grande. La scelta dei casi di test è una sorta di "arte", l'idea è di utilizzare pochi casi di test necessari per testare il maggior numero possibile di casi di errore.

Ad esempio, classifica il tuo dominio di input in categorie:

  • stringa con lunghezza 0
  • stringhe con lunghezza compresa tra 0 e 4
  • stringhe con lunghezza 4
  • stringhe con lunghezza compresa tra 4 e 14
  • stringhe con lunghezza maggiore di 14

E come seconda classificazione

  • stringhe senza caratteri legali
  • stringhe con alcuni caratteri legali
  • stringa con solo caratteri legali

Ora assicurati di avere almeno un test case per ogni categoria. Ovviamente, questo esempio mostra solo la ricerca di test usando "classi di equivalenza". Altre tecniche stanno progettando i test per i casi limite (come quelli nella risposta di @ MainMa), o i test per ottenere la copertura completa del codice e la copertura delle filiali.

    
risposta data 12.03.2013 - 12:45
fonte
1

Che cosa dovresti testare

  • Generale, caso ordinario. Solo per essere sicuro che funzioni. Questo è il caso più semplice:

    1. Un nome che contiene solo lettere e ha una lunghezza compresa tra 4 e 14.

    2. Un nome che contiene solo lettere e ha una lunghezza compresa tra 1 e 4.

    3. Un nome che contiene solo lettere e ha una lunghezza compresa tra 14 e la lunghezza massima autorizzata.

    4. Un nome che contiene solo lettere e ha esattamente 4 caratteri.

    5. Un nome che contiene solo lettere e ha esattamente 14 caratteri.

    6. Un nome che contiene lettere e qualcos'altro e ha una lunghezza compresa tra 4 e 14.

  • Casi bordo

    1. Una stringa vuota.

    2. Un valore nullo (se il tuo linguaggio fa la differenza tra una stringa vuota e null).

    3. Un gruppo di stringhe Unicode con diversa normalizzazione e caratteri diversi. Questi test dovrebbero corrispondere alla tua documentazione che spiega cosa intendi con "solo lettere". щ una lettera? una lettera? Che dire di e delle sue due possibili rappresentazioni unicode (combinate e normalizzate)?

Cosa non dovresti testare

Non dovresti testare cose ripetitive. Se hai testato sia "test" che "Travis", testare anche "John" non porta nulla di utile, dal momento che contiene solo lettere minuscole e maiuscole, proprio come "Travis", ed è lungo 4 caratteri, proprio come "test".

Allo stesso modo, % , Sam1 sono ridondanti.

Come per le stringhe casuali, non dovresti usarle, poiché se il tuo codice non funziona come previsto, in alcuni casi potrebbero darti risultati casuali: a volte il test passerà, la prossima volta che fallirà per l'esatto stesso codice.

    
risposta data 12.03.2013 - 12:49
fonte
0

Il tuo codice dovrebbe soddisfare un caso d'uso e dovrebbe farlo in un modo relativo al rischio creato dalla mancanza di qualcosa. È illegale nel contesto della tua applicazione permettere numeri / caratteri in un nome (forse questo è un database per i nomi con la sola società di lettere)? Quindi testalo il più possibile.

Non che tu voglia invitare qualcuno a gestirti in modo microscopico, ma prendere in considerazione la quantità di tempo che le persone che pagano per questo software vogliono che tu spenda. Non possono condividere la tua perfezione di livello e non vogliono neanche pagare per questo.

    
risposta data 12.03.2013 - 13:46
fonte
0

So what is acceptable way to test my validation without being too much perfectionist, yet to leave most part of logic tested?

Questo dipende. Diverse persone considerano le cose diverse come "test sufficienti". In alcuni casi, alcuni tipi di test sono imposti dalla natura o dai confini del progetto stesso.

Esempi:

  • Avevamo un progetto in cui dovevamo offrire ai clienti una garanzia di rendimento (messaggi X min elaborati al minuto). Questo è stato testato durante lo sviluppo, nei test notturni. Sono stati identificati i colli di bottiglia delle prestazioni e abbiamo progettato / implementato attorno a loro.

  • Abbiamo avuto un progetto che ha analizzato l'XML e ha dovuto fornire garanzie di sicurezza (non si bloccherà su input non validi). Abbiamo finito per implementare una libreria fuzzing (che ha preso ogni API, ha corrotto uno dei suoi parametri in un modo predefinito e ha chiamato l'API in un ciclo, per ogni corruzione).

Normalmente, voglio vedere che i casi banali di default sono implementati, i casi d'angolo sono implementati, i casi generici sono implementati e forse un caso negativo o due (controlla che i dati corretti siano nell'eccezione generata, quando gli input sono sbagliati) . Nel mio progetto attuale, tuttavia, un tale livello di test non è realistico.

Abbiamo anche avuto un progetto in cui (per accordo) la risoluzione di un difetto implicava anche l'aggiunta di un nuovo test unitario. Quando si esegue la suite di test, la regressione completa verrà eseguita automaticamente (ad esempio, siamo stati in grado di garantire che non abbiamo ricreato nessuno dei vecchi problemi riscontrati nell'applicazione).

Am I just set in a mind trick of trying to write a perfect code just to write a perfect code and forgetting about main finish goal: working product?

Non da quello che potrei dire.

Modifica: pochi altri punti:

  • Se hai bisogno di casualità nei tuoi test, assicurati che sia ripetibile (ad esempio, inizializza il generatore di numeri casuali con un seme costante)

  • Per lo meno, prova per il caso più comune;

  • L'aggiunta di test unitari per la maggior parte dei casi d'angolo è vantaggiosa quando il codice cambia (nel codice, che sarebbe la lunghezza 4 e 14, non sono sicuro dei formati). Quando aggiorniamo un algoritmo, tendiamo a pensare (naturalmente) al caso generale; Questi test controllano cose a cui tu (lo sviluppatore) tendi a non pensare ad ogni modifica.

risposta data 12.03.2013 - 13:35
fonte

Leggi altre domande sui tag