2009-10-02 10 views
10

Diciamo che per esempio ha questa classe che genera numeri di Fibonacci:C#: come si verifica il metodo IEnumerable.GetEnumerator()?

public class FibonacciSequence : IEnumerable<ulong> 
{ 
    public IEnumerator<ulong> GetEnumerator() 
    { 
     var a = 0UL; 
     var b = 1UL; 
     var c = a + b; 
     while (true) 
     { 
      yield return c; 
      c = a + b; 
      a = b; 
      b = c; 
     } 
    } 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Posso quindi scrivere un test che consente di verificare che i n primi numeri della sequenza sono corrette.

[Test] 
    public void GetEnumerator_FirstFifteenNumbers_AreCorrect() 
    { 
     var sequence = new FibonacciSequence().Take(15).ToArray(); 
     CollectionAssert.AreEqual(sequence, new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610}); 
    } 

Quando controllo per la copertura comunque, vedrò che il metodo IEnumerable.GetEnumerator() non è testato, e la mia copertura sarà inferiore a quello che ha davvero bisogno di essere. Giusto. Ma come dovrei testare quel metodo?

Come si gestisce di solito questo?

+0

hmm, per curiosità come si controlla la copertura del test? Sembra una caratteristica interessante. – Ian

+1

Sì, me lo sono chiesto anch'io, hehe. Ma trovato un pulsante per esso in TestDriven.Net, che è abbastanza impressionante a proposito. Se non l'hai provato, dovresti! Dopo averlo installato, puoi fare clic con il tasto destro sulla soluzione (in solution explorer) e selezionare Test con -> Copertura. Semplice :) – Svish

+0

Se si dispone della versione di VS Team System, gli strumenti di test includono anche uno strumento di copertura, che può essere attivato con TestDriven.Net o nell'interfaccia regolare. Altrimenti, se utilizzi google strumenti di copertura di prova per Visual Studio, ce ne sono diversi là fuori. NCover potrebbe essere il più usato. – McMuttons

risposta

11

EDIT: aggiornamento sulla base di quello che Marc ha detto.

Ebbene si potrebbe ottenere la copertura da fare:

// Helper extension method 
public static IEnumerable AsWeakEnumerable(this IEnumerable source) 
{ 
    foreach (object o in source) 
    { 
     yield return o; 
    } 
} 

... 

[Test] 
public void GetEnumerator_FirstFifteenNumbers_AreCorrect() 
{ 
    IEnumerable weak = new FibonacciSequence().AsWeakEnumerable(); 
    var sequence = weak.Cast<int>().Take(15).ToArray(); 
    CollectionAssert.AreEqual(sequence, 
     new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610}); 
} 

noti che weak è dichiarato di essere il IEnumerable tipo non generico ... il che significa che è necessario chiamare Cast su di esso per lanciare ogni restituito oggetto a int.

Non sono sicuro che avrei fastidio se ...

+1

No - Ho controllato, e 'Cast ' controlla effettivamente tramite 'as' per' IEnumerable ', quindi finirai usando' IEnumerable .GetEnumerator() ', non' IEnumerable.GetEnumerator() ' –

+0

Questo è quello che ho visto anche io. Quindi non ero abbastanza sicuro di come farlo, hehe. – Svish

+0

Risolto, grazie ragazzi - è un caso di avvolgere la versione forte nei deboli ... –

3

È necessario utilizzare l'uso IEnumerable (non generico); Ho inviato una risposta tramite Cast<T>, ma che sarà ancora imbrogliare (è controllato per il tipo desiderato come un caso speciale) - potrebbe essere necessario qualcosa di simile:

public static int CountUntyped(this IEnumerable source) { 
    int count = 0; 
    foreach(object obj in source) { count++; } 
    return count; 
} 

IEnumerable<T> source = ... 
Assert.AreEqual(typed.Count(), source.CountUntyped()); 
+1

Tuttavia, sarebbe sufficiente confrontare il conteggio degli articoli negli enumerabili, vero? E nel mio caso questo funzionerebbe male, dal momento che FibonacciSequence non finisce mai: p – Svish

+0

Lol! Sì, prendo il tuo punto lì. Ma la cosa che sto cercando di evidenziare è lavorare con 'IEnumerable' piuttosto che' IEnumerable '- e non penso che tu possa semplicemente usare' Cast ', 'perché sembra ... –

4

non vorrei provarlo. Proverei a filtrare il metodo dallo strumento di copertura. Penso che la copertura dovrebbe controllare le cose che voglio avere coperto e non tutto. Da altri commenti sembra che tu stia usando TestDriven.Net. Non so quanto bene quei filtri, ma era possibile con NCover. Puoi provare anche PartCover.

+0

Ovviamente, e non sto battendo me stesso sopra questo o niente. Semplicemente curioso di vedere come gli altri si occupano di esso :) – Svish

+0

@Svish - scusa, la risposta sembra snippier di quanto intendessi. Ma vorrei davvero filtrare le cose. Penso che sia meglio che provare ad aggiungere un test per questo. –

Problemi correlati