2008-09-26 23 views
21

Ocasionalmente me encuentro con una prueba unitaria que no afirma nada. El ejemplo particular que encontré esta mañana fue probar que se escribió un archivo de registro cuando se cumplió una condición. La suposición era que si no se producía ningún error, la prueba pasaba.Prueba unitaria sin aserciones

Personalmente no tengo un problema con esto, sin embargo, parece ser un poco "olor a código" escribir una prueba de unidad que no tenga ninguna aserción asociada.

¿Qué opinan las personas sobre este tema?

Respuesta

16

Esta sería la forma oficial de hacerlo:

// Act 
Exception ex = Record.Exception(() => someCode()); 

// Assert 
Assert.Null(ex); 
2

En cierto sentido, está haciendo una afirmación implícita: que el código no arroja una excepción. Por supuesto, sería más valioso agarrar el archivo y encontrar la línea adecuada, pero supongo que algo es mejor que nada.

2

En general, veo que esto ocurre en las pruebas de integración, solo el hecho de que algo se completó satisfactoriamente es suficiente. En este caso estoy genial con eso.

Supongo que si lo volviera a ver una y otra vez en pruebas de unidad Me gustaría saber qué tan útiles fueron realmente las pruebas.

EDITAR: En el ejemplo dado por el OP, hay algún resultado comprobable (resultado de archivo de registro), por lo que se supone que si no se produjo ningún error que funcionó es flojo.

17

Es simplemente una prueba muy mínima, y ​​debe documentarse como tal. Solo verifica que no explota cuando se ejecuta. La peor parte de las pruebas como esta es que presentan una falsa sensación de seguridad. Su cobertura de código aumentará, pero es ilusoria. Muy mal olor.

2

Puede ser una buena solución pragmática, especialmente si la alternativa no es ninguna prueba en absoluto.

El problema es que la prueba pasaría si todas las funciones llamadas no funcionaran. Pero a veces simplemente no es factible verificar que los efectos secundarios sean los esperados. En el mundo ideal, habría tiempo suficiente para escribir los cheques para cada prueba ... pero no vivo allí.

El otro lugar en el que he usado este patrón es para incorporar algunas pruebas de rendimiento en las pruebas unitarias porque era una forma fácil de ejecutar cada compilación. Las pruebas no afirman nada, pero miden cuánto tiempo tomó la prueba e inician sesión.

+1

no estoy de acuerdo - no es pragmático, es vago;) – ryw

+0

la pereza es una buena motivación para escribir el código de mantenimiento :) –

0

Tengo que admitir que nunca he escrito una prueba de unidad que haya verificado que estoy iniciando sesión correctamente. Pero lo pensé y encontré este discussion de cómo podría hacerse con JUnit y Log4J. No es muy bonito, pero parece que funcionaría.

+0

Cuando uso un marco de terceros para el registro, tiendo a probar que el acto de registro funcionó correctamente, en lugar de probando el resultado del archivo de registro. Intentaría interconectar el marco de trabajo para poder falsificarlo bajo prueba y simplemente asegurarme de que se estaban llamando a los métodos correctos. –

5

Tal prueba huele. Debería verificar que el archivo se haya escrito, al menos que la hora modificada se actualizó tal vez.

He visto bastantes pruebas escritas de esta manera que terminaron sin probar nada, es decir, el código no funcionó, pero tampoco explotó.

Si usted tiene algún requerimiento explícito de que el código bajo prueba no produce una excepción y que desea llamar explícitamente este hecho (pruebas como los requisitos de documentación), entonces me gustaría hacer algo como esto:

try 
{ 
    unitUnderTest.DoWork() 
} 
catch 
{ 
    Assert.Fail("code should never throw exceptions but failed with ...") 
} 

... pero esto todavía huele un poco a mí, probablemente porque está tratando de demostrar que es negativo.

+0

Tengo que estar de acuerdo. Personalmente estoy de acuerdo en que desea verificar de alguna manera que la escritura ocurrió, no necesariamente que la escritura fue correcta. – lomaxx

0

Las pruebas siempre deben afirmar algo; de lo contrario, ¿qué está probando y cómo puede reproducir consistentemente la evidencia de que su código funciona?

+1

Creo que la afirmación "siempre debe afirmar algo" es engañosa. Las pruebas siempre deben "probar" algo, pero eso no requiere una declaración de "afirmación". – codeLes

0

Hacemos esto todo el tiempo. Nos burlamos de nuestras dependencias usando JMock, así que supongo que, en cierto sentido, el framework JMock está haciendo la afirmación por nosotros ... pero va más o menos así. Tenemos un controlador que queremos prueba:

Class Controller { 
    private Validator validator; 

    public void control(){ 
    validator.validate; 
    } 

    public setValidator(Validator validator){ this.validator = validator; } 
} 

Ahora, cuando el regulador prueban que 'no queremos poner a prueba de validación, ya que tiene su propio pruebas. por lo que tenemos una prueba con JMock sólo para asegurarse de que llamamos validación:

public void testControlShouldCallValidate(){ 
    mockValidator.expects(once()).method("validate"); 
    controller.control; 
} 

Y eso es todo, no hay una "afirmación" de ver, pero cuando se llama al método de "validación" de control y no se llama entonces el El framework JMock arroja una excepción (algo así como "método esperado no invocado" o algo así).

Tenemos esos por todo el lugar. Es un poco al revés ya que básicamente configura su afirmación ENTONCES realice la llamada al método probado.

1

He visto algo así antes y creo que esto se hizo solo para apuntalar los números de cobertura del código. Probablemente no esté realmente probando el comportamiento del código. En cualquier caso, acepto que (la intención) debe documentarse en la prueba para mayor claridad.

5

Se conocen como pruebas de humo y son comunes. Son controles básicos de cordura. Pero no deberían ser los únicos tipos de pruebas que tienes. Todavía necesitarías algún tipo de verificación en otra prueba.

+0

Estas no son pruebas de humo necesarias: http://softwaretestingfundamentals.com/smoke-testing/ – camposer

+0

Es una prueba de humo en el sentido de que si se ejecuta sin lanzar una excepción, pasa. –

11

Si no hay ninguna afirmación, no es una prueba.

Deje de ser flojo: puede tomar un poco de tiempo averiguar cómo obtener la afirmación allí, pero vale la pena saber que hizo lo que esperaba que hiciera.

+0

ha ... Tiendo a sentirme de esta manera, pero me preguntaba si había una razón válida para el uso de pruebas sin aserciones :) – lomaxx

+0

Para una vista contraria a "Si no hay una afirmación, no es una prueba "(al menos con Pytest), vea el comentario de Nick Chammas en https://stackoverflow.com/a/20275035/805141 – Daniel

0

A veces utilizo mi marco de prueba de unidades de prueba (NUnit) para construir métodos que actúen como puntos de entrada en partes específicas de mi código. Estos métodos son útiles para perfilar el rendimiento, el consumo de memoria y el consumo de recursos de un subconjunto del código.

Estos métodos definitivamente no son pruebas unitarias (aunque están marcados con el atributo [Prueba]) y siempre se marcan para que se ignoren y se documenten explícitamente cuando se controlan en el control de código fuente.

De vez en cuando uso estos métodos como puntos de entrada para el depurador de Visual Studio. Uso Resharper para pasar directamente a la prueba y luego al código que quiero depurar. Estos métodos no llegan tan lejos como el control de fuente, o adquieren sus propios asertos.

Mis pruebas de unidad "reales" se crean durante ciclos de TDD normales, y siempre afirman algo, aunque no siempre directamente - a veces las aseveraciones son parte del marco burlón, y a veces puedo refactorizar aserciones similares en una solo método. Los nombres de esos métodos refactorizados siempre comienzan con el prefijo "Assert" para que sea obvio para mí.

1

El nombre de la prueba debe documentar esto.

void TestLogDoesNotThrowException(void) { 
    log("blah blah"); 
} 

¿Cómo verifica la prueba si el registro está escrito sin aserción?