Primero, disculpas por el título, ¡no podría pensar en la forma más fácil de explicarlo!
Tengo un método para el que quiero escribir pruebas unitarias. Lo mantendré bastante genérico, ya que no quiero discutir la implementación del método, solo probarlo. El metodo es:
public void HandleItem(item a)
{
CreateNewItem();
UpdateStatusOnPreviousItem();
SetNextRunDate();
}
Entonces, esta clase tiene un método público que luego llama a algunos métodos privados para realizar la lógica.
Entonces, al escribir la prueba de la unidad, quiero verificar que se hayan hecho las tres cosas. Como todos se llaman en la misma ejecución, pensé que podría hacerlo como una prueba:
public void GivenItem_WhenRun_Thenxxxxx
{
HandleItem(item);
// Assert item has been created
// Assert status has been set on the previous item
// Assert run date has been set
}
Pero pensé que también podría escribirlo como tres pruebas separadas:
public void GivenItem_WhenRun_ThenItemIsCreated()
{
HandleItem(item);
}
public void GivenItem_WhenRun_ThenStatusIsUpdatedOnPreviousItem()
{
HandleItem(item);
}
public void GivenItem_WhenRun_ThenRunDateIsSet()
{
HandleItem(item);
}
Entonces, para mí, esto parece más agradable, ya que esencialmente enumera los requisitos, pero los tres están relacionados y requieren exactamente el mismo trabajo realizado en el método probado, por lo que estoy ejecutando el mismo código 3 veces.
¿Hay un enfoque recomendado para tomar con esto?
Gracias
fuente
Respuesta corta: es mucho más importante que sus pruebas cubran toda la funcionalidad que cómo lo hacen.
Respuesta más larga: si aún desea elegir entre estas soluciones en gran medida equivalentes, puede utilizar criterios auxiliares para lo que es mejor. Por ejemplo,
fuente
Use una llamada de método con múltiples afirmaciones. Este es el por qué:
Cuando prueba HandleItem (a), está probando que el método ha llevado el elemento al estado correcto. En lugar de "una afirmación por prueba", piense en "un concepto lógico por prueba".
Pregunta: Si un CreateNewItem falla, pero los otros dos métodos tienen éxito, ¿significa esto que HandleItem se completó con éxito? Supongo que no.
Con múltiples afirmaciones (con mensajes apropiados) sabrá exactamente qué ha fallado. Por lo general, prueba un método varias veces para múltiples entradas o estados de entrada, no para evitar múltiples afirmaciones.
En mi opinión, estas preguntas suelen ser un signo de otra cosa. Es una señal de que HandleItem no es realmente algo que pueda "probar unitariamente", ya que parece delegarlo en otros métodos. Cuando simplemente está validando que HandleItem llama a otros métodos correctamente, se convierte en un candidato de prueba de integración (en cuyo caso aún tendría 3 afirmaciones).
Es posible que desee considerar hacer públicos los otros 3 métodos y probarlos de forma independiente. O incluso extraerlos a otra clase.
fuente
Usa el segundo enfoque. Con su primer enfoque, si la prueba falla, no sabrá por qué de inmediato, porque podría ser una de las 3 funciones que fallaron. Con el segundo enfoque, sabrá de inmediato dónde ocurrió el problema. Puede poner código duplicado dentro de su función de configuración de prueba.
fuente
En mi humilde opinión, debe probar las tres partes de este método por separado para que sepa más específicamente dónde van las cosas mal cuando lo hacen, evitando al mismo tiempo pasar la misma parte de su código dos veces.
fuente
No creo que haya un caso sólido para escribir métodos de prueba separados para su caso de uso. Si desea obtener los resultados de las tres condiciones variables, puede probar las tres e imprimir sus fallas concatenando en una
string
y afirmando si la cadena aún está vacía una vez que haya completado la prueba. Al mantenerlos a todos en el mismo método, sus condiciones y mensajes de falla documentan la condición posterior esperada del método en un lugar, en lugar de dividirlo en tres métodos que podrían separarse más adelante.Esto significa que su única prueba tendrá más código, pero si tiene tantas condiciones posteriores que es un problema, probablemente quiera refactorizar sus métodos de prueba para probar métodos individuales dentro de
HandleItem
todos modos.fuente