2009-10-02 12 views
10

Digamos que, por ejemplo, tiene esta clase que genera números de Fibonacci:C#: ¿Cómo se prueba el método 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(); 
    } 
} 

entonces puedo escribir una prueba que se asegura de que los primeros n números en la secuencia son correctos.

[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}); 
    } 

Cuando compruebo para la cobertura sin embargo, se verá que el método IEnumerable.GetEnumerator() no se ha probado, y mi cobertura será menor de lo que realmente tiene que ser. Lo suficientemente justo. ¿Pero cómo debería probar ese método?

¿Cómo se suele lidiar con esto?

+0

hmm, por curiosidad, ¿cómo verifica la cobertura de las pruebas? Suena como una característica interesante. – Ian

+1

Sí, también me pregunté sobre eso, jeje. Pero encontré un botón para ello en TestDriven.Net, que es bastante impresionante por cierto. Si no lo has probado, ¡deberías! Después de instalarlo, puede hacer clic con el botón derecho en su solución (en el explorador de soluciones) y seleccionar Probar con -> Cobertura. Tan fácil como eso :) – Svish

+0

Si tiene la edición VS Team System, las herramientas de prueba también incluyen una herramienta de cobertura, que puede activar con TestDriven.Net o en la interfaz habitual. De lo contrario, si pruebas herramientas de cobertura de prueba de Google para Visual Studio, hay varias por ahí. NCover podría ser el más utilizado. – McMuttons

Respuesta

11

EDIT: Actualización sobre la base de lo que Marc dijo.

Bien se podía obtener la cobertura por hacer:

// 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}); 
} 

Tenga en cuenta que weak se declara ser el tipo no genérico IEnumerable ... lo que significa que tiene que llamar Cast en él para emitir cada uno regresó objetar al int.

No estoy seguro de que me moleste, aunque ...

+1

No - Lo revisé, y 'Cast ' realmente comprueba a través de 'as' para' IEnumerable ', por lo que terminará usando' IEnumerable .GetEnumerator() ', no' IEnumerable.GetEnumerator() ' –

+0

Eso es lo que vi también. Entonces no estaba muy seguro de cómo hacerlo, jeje. – Svish

+0

Reparado, gracias chicos - es un caso de envolver la versión fuerte en el débil ... –

3

Tendría que usar el uso IEnumerable (no genérico); He publicado una respuesta a través de Cast<T>, pero que todavía engañaré (lo revisen para el tipo deseado como un caso especial) - es posible que tenga algo como:

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

Pero eso simplemente compararía el conteo de artículos en los enumerables, ¿o no? Y eso funcionaría mal en mi caso, ya que la secuencia Fibonacci nunca termina realmente: p – Svish

+0

¡Lol! Sí, entiendo tu punto allí. Pero lo que estoy tratando de resaltar es trabajar con 'IEnumerable' en lugar de' IEnumerable '- y no creo que pueda simplemente usar' Cast ', 'porque parece ... –

4

no me probarlo. Intentaría filtrar el método fuera de la herramienta de cobertura. Creo que la cobertura debe verificar las cosas que quiero haber cubierto y no todo. De otros comentarios parece que está usando TestDriven.Net. No sé qué tan bien esos filtros, pero fue posible con NCover. Podrías probar PartCover también.

+0

Por supuesto, y no estoy latiendo yo mismo sobre esto o cualquier cosa. Solo curiosidad por ver cómo los demás lo enfrentan :) – Svish

+0

@Svish - lo siento, la respuesta suena más snippier de lo que pretendía. Pero realmente buscaría filtrar las cosas. Creo que es mejor que tratar de agregar una prueba para ello. –

Cuestiones relacionadas