Tengo un montón de clases que se ocupan de la validación de valores. Por ejemplo, una RangeValidator
clase verifica si un valor está dentro del rango especificado.
Cada clase de validador contiene dos métodos: is_valid(value)
que devuelve True
o False
depende del valor, y ensure_valid(value)
que busca un valor específico y no hace nada si el valor es válido o arroja una excepción específica si el valor no coincide con las reglas predefinidas.
Actualmente hay dos pruebas unitarias asociadas con este método:
El que pasa un valor no válido y asegura que se lanzó la excepción.
def test_outside_range(self): with self.assertRaises(demo.ValidationException): demo.RangeValidator(0, 100).ensure_valid(-5)
El que pasa un valor válido.
def test_in_range(self): demo.RangeValidator(0, 100).ensure_valid(25)
Aunque la segunda prueba hace su trabajo, falla si se lanza la excepción y tiene éxito si ensure_valid
no arroja nada, el hecho de que no haya assert
s adentro parece extraño. Alguien que lea dicho código se preguntará de inmediato por qué hay una prueba que parece no estar haciendo nada.
¿Es esta una práctica actual cuando se prueban métodos que no devuelven un valor y no tienen efectos secundarios? ¿O debería reescribir la prueba de una manera diferente? ¿O simplemente poner un comentario explicando lo que estoy haciendo?
fuente
self
referencia) y no devuelve ningún resultado, no es una función pura.void
en muchos idiomas y tiene reglas tontas). Alternativamente, podría tener un infinito loop (que funciona incluso cuando "no devuelve ningún resultado" realmente significa que no devuelve ningún resultado.unit -> unit
en cualquier idioma que considera la unidad como un tipo de datos estándar en lugar de algo mágicamente especial. Desafortunadamente, solo devuelve la unidad y no hace nada más.Respuestas:
La mayoría de los marcos de prueba tienen una afirmación explícita para "No arroja", por ejemplo, Jasmine tiene
expect(() => {}).not.toThrow();
ynUnit y sus amigos también tienen una.fuente
Esto depende en gran medida del lenguaje y el marco utilizado. Hablando en términos de
NUnit
, hayAssert.Throws(...)
métodos. Puedes pasarles un método lambda:que se ejecuta dentro de
Assert.Throws
. La llamada a la lambda probablemente estará envuelta por untry { } catch { }
bloque y la afirmación falla, si se detecta una excepción.Si su marco no proporciona estos medios, puede solucionarlo, ajustando la llamada usted mismo (estoy escribiendo en C #):
Esto hace que la intención sea más clara, pero satura el código en cierta medida. (Por supuesto, puede envolver todo esto en un método). Al final, dependerá de usted.
Editar
Como Doc Brown señaló en los comentarios, el problema no ha sido indicar que el método arroja, sino que no arroja. En NUnit también hay una afirmación para eso
fuente
Simplemente agregue un comentario para aclarar por qué no se necesita ninguna afirmación y por qué no la olvidó.
Como puede ver en las otras respuestas, cualquier otra cosa hace que el código sea más complicado y desordenado. Con el comentario allí, otros programadores sabrán la intención de la prueba.
Dicho esto, este tipo de prueba debería ser una excepción (sin juego de palabras). Si te encuentras escribiendo algo así regularmente, entonces probablemente las pruebas te digan que el diseño no es óptimo.
fuente
También podría afirmar que algunos métodos se llaman (o no se llaman) correctamente.
Por ejemplo:
En tu prueba:
fuente