Come testare i tipi di dati astratti che implemento da solo?

3

Come si può persino testare un tipo di dati astratto?

Voglio dire, oltre al normale (supposto) modo di fare test unitari, dove prendi in giro i collaboratori, li nutri nella classe per testare, insieme con i dati di esempio, e chiama i metodi pubblici, verificando che l'output è il previsto uno, come ti assicuri che gli interni siano ciò che vuoi?

Facciamo un esempio : diciamo che voglio implementare il mio PriorityQueue , ma voglio usare un Heap come rappresentazione interna e anche oltre, un array per il Parte di heap

Il modo normale per testare è controllare i metodi pubblici in diversi scenari, i metodi sono: push, pop, peek.

Ciò non fornisce alcuna garanzia sulle prestazioni dell'algoritmo utilizzato internamente. Potrei e dovrei preoccuparmi di fare alcuni "scenari" per controllare le prestazioni, ma queste sono utili dopo che ho implementato la mia cosa e sono principalmente per la raccolta di metriche.

Quindi, come faccio a testare le parti interne ? O meglio, come posso assicurarmi che la rappresentazione interna usi l'algoritmo che voglio.

So che avrò diversi livelli su internals se vado con l'implementazione "heap" (questi sono ovunque su Internet per implementazioni di PriorityQueues):

1. calcolo di left-child, right-child, parent per un nodo; Potrei estrarli in una classe separata e testarla. Oppure potrei semplicemente proteggerli e testarli nella classe PriorityQueue, ma questo incapsula l'interruzione perché i test guardano nello stato della classe per testare

2. shiftUp e shiftDown; stessi problemi come per quello di cui al punto 1., tranne ora posso farli ricevere l'oggetto che rappresenta lo stato interno, o utilizzare il campo privato diretto, nel caso di un linguaggio orientato agli oggetti. Così, protetto o in un'altra entità?

3. la rappresentazione interna è una matrice, quindi potrei avere un metodo toArray () pubblico e testarlo. Testare l'output di questo può persino "salvarmi" dal test dei due punti precedenti, ma ancora una volta, lo stato interno è esposto al mondo esterno. Voglio davvero farlo?

Le domande qui sono :

  • separi il codice in più pezzi? quando ti fermi con la granularità?
  • quanto sacrifico da KISS per avere alcuni test unitari? Voglio le cose semplici e potrei avere la maggior parte delle cose nella stessa classe e anche i metodi per usare direttamente i campi interni (in caso di OO)
  • ci sono altri "suggerimenti", altri modi per garantire sia la funzionalità della struttura dati che l'algoritmo usato?
posta Belun 11.01.2017 - 15:47
fonte

2 risposte

5

I test non fanno altro che imporre l'implementazione di una classe esattamente nel modo desiderato. A che cosa servono i test è verificare che il comportamento visibile di una classe (o di un'altra unità) corrisponda alle aspettative, ma a un buon test non interessa come la classe ottiene quello.

Se vuoi assicurarti che la tua classe PriorityQueue venga implementata utilizzando un heap che si basa su un array, allora il modo più efficace per garantire che sia eseguire revisioni coerenti del codice per tutte le modifiche che vengono apportate. < br> La ragione di ciò è che i cambiamenti di progettazione che non influiscono sul risultato dell'algoritmo sono molto difficili da rilevare con i casi di test, ma possono essere facilmente individuati da un lettore umano.

    
risposta data 16.01.2017 - 09:24
fonte
2

Se alcune registrazioni possono aggiungere al software sotto test, allora gli attributi interni (ad esempio tempo, spazio, struttura, ecc.) potrebbero essere pubblicati che il codice di test potrebbe ispezionare dopo aver sottoposto l'oggetto ai suoi passi. Con i comuni framework di registrazione, i dati possono passare attraverso un logger dedicato che non sarebbe evidente se il software in prova fosse pubblicato e filtrato per avere un impatto ridotto sulle prestazioni di esecuzione.

Tuttavia, questo solleva la questione di quanti test dovrebbero essere legati ai particolari di un'implementazione piuttosto che al comportamento dell'interfaccia pubblicata. Il mantenimento del codice di test può richiedere un costo significativo. Concentrando i test sul comportamento di PriorityQueue , il suo implementatore può successivamente ottimizzare il codice senza alcuna modifica al codice di test. Pertanto, se è necessario testare l'implementazione, suggerisco di separare i test di implementazione dai test comportamentali in modo che il primo possa essere saltato per aiutare a gestire lo sforzo di test.

    
risposta data 17.02.2018 - 11:08
fonte

Leggi altre domande sui tag