mocks mock fowler fake entre diferencia aren and .net mocking tdd assert stub

.net - fowler - mocks aren t stubs



Uso de Assert.Inconclusive (4)

Assert.Inconclusive indica que:

Todavía no he escrito la prueba, solo he creado el método de prueba

-o-

Mi prueba tiene una dependencia y esa dependencia no está disponible. Por ejemplo

List<Customer> custs = o.GetAllCustomers(); if (custs.Count == 0) { Assert.Inconclusive("No customers to test"); return; }

Me pregunto cómo alguien debería usar Assert.Inconclusive ().

Lo estoy usando si mi prueba de unidad estaría a punto de fallar por una razón diferente a la que es la prueba.

Por ejemplo, tengo un método en una clase que calcula la suma de una matriz de ints. En la misma clase, también hay un método para calcular el promedio del elemento. Se implementa llamando a la suma y dividiéndola por la longitud de la matriz.

Escribir una prueba de unidad para Sum () es simple. Sin embargo, cuando escribo una prueba para Average () y Sum () falla, es probable que también Average () falle.

El fallo de Average no es explícito sobre la razón por la que falló; falló por una razón diferente a la que debería probar. Por eso verificaría si Sum () devuelve el resultado correcto, de lo contrario, I Assert.Inconclusive ().

¿Es esto para ser considerado una buena práctica? ¿Para qué es Assert.Inconclusive? ¿O debería más bien resolver el ejemplo anterior mediante un Marco de Aislamiento?


Cuando uso VS para generar las pruebas unitarias, obtuve Assert.Inclusive para los métodos de prueba generados y, por lo general, cambio la aserción para que sea algo más cuando los trabajo. Utilizo los signos de interrogación de Assert.Inclusive en los resultados de las pruebas como marcadores para decirme rápidamente qué pruebas aún no he completado.

Bueno, es solo la forma en que lo uso. Por su nombre "Inconclusive", supongo que puede usarlo para indicar su estado no determinista siempre que documente lo que significa.

Sin embargo, a partir de la descripción de su método de Average() , creo que tal vez su prueba de unidad no sea lo suficientemente atómica para cubrir solo una "unidad", un escenario específico. A veces, escribo métodos de prueba de 2 o 3 unidades para un solo método. O puede dividir su método de Average() en métodos más pequeños que cubren responsabilidades individuales. De esa manera, puede probar en una unidad los métodos más pequeños antes de realizar la prueba de unidad en Average() .

Johannes,

Así es como implementaría los métodos Sum() y Average() .

public static class MyMath { private static void ValidateInput(ICollection<int> numbers) { if (numbers == null) throw new ArgumentNullException("numbers", "Null input. Nothing to compute!"); if (numbers.Count == 0) throw new ArgumentException("Input is empty. Nothing to compute!"); } public static int Sum(int[] numbers) { ValidateInput(numbers); var total = 0; foreach (var number in numbers) total += number; return total; } public static double Average(int[] numbers) { ValidateInput(numbers); return Sum(numbers) / numbers.Length; } }

Para simplificar, simplemente lanzo excepciones ArgumentException del método ValidateInput(ICollection<int>) . También puede verificar la posibilidad de desbordar y lanzar OverflowException en el método ValidateInput(ICollection<int>) .

Dicho esto, he aquí cómo probaría la función Average(int[]) .

[TestMethod] public void AverageTest_GoodInput() { int[] numbers = {1, 2, 3}; const double expected = 2.0; var actual = MyMath.Average(numbers); Assert.AreEqual(expected, actual); } [TestMethod] [ExpectedException(typeof(ArgumentNullException))] public void AverageTest_NullInput() { int[] numbers = null; MyMath.Average(numbers); } [TestMethod] [ExpectedException(typeof(ArgumentException))] public void AverageTest_EmptyInput() { var numbers = new int[0]; MyMath.Average(numbers); }

Con esta configuración de pruebas, puedo estar seguro de que cuando todas las pruebas pasen, mi función es correcta. Bueno, salvo el caso de desbordamiento. Ahora puedo volver al método ValidateInput(ICollection<int>) para agregar lógica para verificar el desbordamiento, luego agregar una prueba más para esperar que se OverflowException la OverflowException para el tipo de entradas que causan el desbordamiento. O hazlo en el orden opuesto si quieres acercarte usando TDD.

Espero que esto ayude a aclarar la idea.


La prueba no concluyente es una prueba para la cual no se puede determinar el resultado. Por ejemplo, qué sucede si se realizó una prueba que utiliza algún tipo de recurso externo (conexión a Internet, por ejemplo). Si la conexión no está disponible actualmente, esto no significa que la prueba sea una falla. Por otro lado, no solo debes marcarlo como exitoso sin ejecutarlo realmente. Así que lo marca como no concluyente y esto se puede ver en el informe de la prueba.

NOTA: En general, no debe usar dichos recursos externos en sus pruebas, ya que esto puede hacer que las pruebas sean frágiles.

Para las pruebas que aún no se han terminado, utilizo el atributo Explicit de MbUnit.


Sólo afirmo. No concluyo en pruebas unitarias. Aún no he escrito. A veces cuando escribo algo me doy cuenta de un caso de esquina que no quiero perder. Así que rápidamente salto, escribo el método de prueba con un nombre descriptivo y agrego una sola línea de Assert.Inconclusive.

La razón para hacer esto es que proporciona documentación sobre cosas que necesito probar sin interrumpir demasiado mi flujo de trabajo. También hace posible filtrar las fallas de prueba rápidamente en la lista de resultados. Tener una falla no concluyente significa que no he roto nada, solo más pruebas para escribir.