Test di una classe di conversione

7

Ho una classe che è responsabile per l'esecuzione di conversioni da / a tipi di venti-qualcosa. Chiamiamo questa classe ConvertUtils .

Per i programmatori C # là fuori - questa classe espande la classe .Net Convert .

Sembra qualcosa del tipo:

public static class ConvertUtils {
    public static object ChangeType(object obj, Type newType) {
        if (conversionSupportedByFramework)
            return Convert.ChangeType(obj, newType);
        else
            ConvertSpecialCases(obj, newType);
    }
}

Come faresti a testarlo? Suppongo che abbiamo bisogno di testare questo codice in black-box.

I due modi in cui abbiamo pensato sono:

  1. Scrittura di 400+ test unitari - copre tutte le combinazioni da / a quelle a cui possiamo pensare.
  2. Scrivi test solo per le nuove conversioni - quelle non supportate dalla classe Convert - in realtà testando solo la funzione ConvertSpecialCases() [che non è il nostro obiettivo, come detto sopra]

Il vantaggio della prima possibilità è di avere troppi test - il che prolunga i tempi di costruzione, implica il mantenimento di più codice, ecc.

Il controllo della seconda possibilità è di non controllare completamente la responsabilità della classe - cosa succede se una determinata istruzione if decide di implementare una logica personalizzata (errata), invece di lasciare che Convert faccia il suo lavoro? per esempio. appena prima che if (conversionSupportedByFramework) qualcuno decida di chiamare qualche logica personalizzata?

Che cosa ne pensi di questo problema?

    
posta Berlo 23.06.2015 - 22:26
fonte

4 risposte

4

Non è necessario testare il codice di .NET Framework nel caso specifico, perché:

  • Non puoi ereditare dalla classe Convert , poiché questa classe è statica; anche se potessi farlo, ad esempio se Convert class non fosse statico:

  • La classe Convert non ha metodi virtuali,

  • Non ci sono metodi di istanza,

  • Non ci sono metodi astratti,

  • non può sostituire i metodi statici in una classe,

  • Non dovresti nascondere i metodi utilizzando% di parole chiavenew comunque (e se lo fai, l'analisi del codice ti urlerà)

L'unico modo in cui potresti essere in grado di sfruttare le funzionalità esistenti è tramite Reflection. Se usi Reflection per giocare con le parti interne della classe Convert , allora sì, devi studiare e verificare l'impatto che potrebbe avere.

Altrimenti, devi solo testare il nuovo codice che scrivi nella classe personalizzata.

    
risposta data 24.06.2015 - 14:36
fonte
3

Dipende da come è la tua classe di conversione. Se appare così:

  class MyConvert
  {
       public static Foo1 ToFoo1(Bar1 bar){...}
       public static Foo2 ToFoo2(Bar1 bar){...}
       public static Foo3 ToFoo3(Bar1 bar){...}
       // ...
       public static Foo1 ToFoo1(Bar2 bar){...}
       public static Foo2 ToFoo2(Bar2 bar){...}
       // ...
       public static Foo20 ToFoo20(Bar20 bar){...}
  }

dovresti implementare almeno un test (meglio due o tre) per ciascun metodo. E se hai 400 metodi, hai bisogno di un piccolo multiplo di 400 test.

Se, tuttavia, la tua classe ha un aspetto diverso e hai qualcosa come una "classe di rappresentazione interna" per tutti gli oggetti Bar , puoi ridurre il numero di test. Assumi qualcosa del genere:

  class MyConvert
  {
       public static Foo1 ToFoo1(object bar)
       {
           MyInternalObj myObj = new MyInternalObj(bar);
           return myObj.ToFoo1();
       }
       public static Foo2 ToFoo2(object bar)
       {
           MyInternalObj myObj = new MyInternalObj(bar);
           return myObj.ToFoo2();
       }
      // ...
  }

dovrai solo scrivere test per il costruttore di MyInternalObj per tutti i tipi di oggetti consentiti (almeno 20) e test aggiuntivi per i metodi ToFoo1 , ToFoo2 , ..., di MyInternalObj (anche almeno 20 o un piccolo multiplo di quelli).

Sapere che la tua implementazione è simile a questa, ma non vuoi accedere direttamente a MyInternalObj , puoi anche applicare gli stessi test chiamando MyConvert.ToFoo1 con 20 tipi di Bar diversi e MyConvert.ToFooXYZ in tutte le 20 varianti utilizzando il stesso tipo "Bar".

O più generale: assicurati di ottenere un buon codice e una copertura di ramificazioni di tutto il codice che hai scritto.

    
risposta data 24.06.2015 - 13:34
fonte
2

Il fatto che la classe sia una classe di conversione, il fatto che sia statica e il fatto che espanda una classe framework esistente sono tutti irrilevanti. Questa domanda è un'istanza della più generale domanda di test black-box vs. white-box .

In lack of any very good reason to perform white-box testing, all testing should be black-box testing.

Questo significa che il tuo codice di test non dovrebbe fare alcuna ipotesi sui componenti interni del sistema sotto test.

Questo a sua volta significa che il tuo codice di test non dovrebbe presumere che la tua classe di conversione deleghi ad un'altra classe di conversione. (Proprio perché potrebbe delegare, e poi di nuovo chi lo sa, potrebbe non delegare). Quindi, testare l'intera interfaccia pubblica della tua classe di conversione è la strada da percorrere.

Detto questo, lasciatemi aggiungere che poiché stai scrivendo una classe statica che espande le funzionalità di un'altra classe statica, il modo per ridurre il tuo codice di test è astenendosi espressamente dal duplicare la funzionalità della classe framework esistente. Se si desidera una delle conversioni fornite dalla classe framework, richiamare la classe framework. Se vuoi una delle conversioni fornite dalla tua classe, invoca la tua classe. Non vi è alcun motivo per racchiudere la funzionalità di una classe framework statica all'interno di una classe statica personalizzata, non c'è nemmeno un vero involucro in corso, solo una finzione, poiché la funzionalità della classe framework è ancora disponibile pubblicamente per qualsiasi parte di codice che desideri per invocarlo.

    
risposta data 25.06.2015 - 12:34
fonte
0

In primo luogo, determina se le tue modifiche avranno un impatto su altri metodi pubblici dalla classe Convert. Se lo faranno, scoprirai quali sono interessati. Ora sei più preparato per prendere una decisione.

Nel caso in cui non ci sia alcun impatto in altri metodi e funzionalità pubbliche, concentrati solo sulle nuove cose che aggiungi o su quelle che modifichi.

Se la modifica interessa altre aree della classe del convertitore, inizia a testare ciò che hai aggiunto o modificato, quindi verifica i metodi con i quali le tue modifiche hanno avuto un impatto.

Un altro consiglio è che se le tue modifiche influiscono sulle funzionalità esistenti, quando si testano le funzionalità esistenti si dà priorità a quelle che si stanno già utilizzando. Probabilmente non saranno un grande numero.

Qualcos'altro da considerare è il seguente. Per i metodi che non sono stati modificati, utilizzare la classe del convertitore originale. Usa il tuo nuovo solo per gli elementi che cambiano. Quando si è sicuri che la nuova classe del convertitore funzioni, quindi apportare tutte le modifiche. Anche se utilizzi molti di questi metodi di conversione, la modifica non sarà troppo difficile perché le firme dei metodi non cambieranno e poiché sei sicuro che il nuovo convertitore funzioni, il tuo software non dovrebbe avere alcun impatto.

    
risposta data 24.06.2015 - 05:13
fonte

Leggi altre domande sui tag