Tener pruebas que verifiquen solo una cosa facilita la solución de problemas. No quiere decir que tampoco deba tener pruebas que prueben varias cosas, o múltiples pruebas que compartan la misma configuración/desmontaje.
Aquí debería haber un ejemplo ilustrativo. Digamos que usted tiene una clase de pila con consultas:
y métodos para mutar la pila
Ahora, consideremos el siguiente caso de prueba para que (estoy usando Python como pseudo-código para este ejemplo.)
class TestCase():
def setup():
self.stack = new Stack()
def test():
stack.push(1)
stack.push(2)
stack.pop()
assert stack.top() == 1, "top() isn't showing correct object"
assert stack.getSize() == 1, "getSize() call failed"
A partir de este caso de prueba, se puede determinar si algo está mal, pero no si está aislado en las implementaciones push()
o pop()
, o en las consultas que devuelven valores: top()
y getSize()
.
Si agregamos casos de prueba individuales para cada método y su comportamiento, las cosas se vuelven mucho más fáciles de diagnosticar. Además, al hacer una configuración nueva para cada caso de prueba, podemos garantizar que el problema está completamente dentro de los métodos que el método de prueba fallido llamó.
def test_size():
assert stack.getSize() == 0
assert stack.isEmpty()
def test_push():
self.stack.push(1)
assert stack.top() == 1, "top returns wrong object after push"
assert stack.getSize() == 1, "getSize wrong after push"
def test_pop():
stack.push(1)
stack.pop()
assert stack.getSize() == 0, "getSize wrong after push"
En lo que se refiere al desarrollo basado en pruebas. Personalmente escribo "pruebas funcionales" más grandes que terminan probando múltiples métodos al principio, y luego creo pruebas unitarias a medida que comienzo a implementar piezas individuales.
Otra forma de verlo son las pruebas unitarias que verifican el contrato de cada método individual, mientras que las pruebas más grandes verifican el contrato que deben seguir los objetos y el sistema en su conjunto.
Todavía estoy usando tres llamadas a métodos en test_push
, sin embargo, tanto top()
como getSize()
son consultas que se prueban con métodos de prueba separados.
Puede obtener una funcionalidad similar al agregar más afirmaciones a la prueba individual, pero luego se ocultarán las fallas de afirmación posteriores.
Bueno, es posible que no detecte un error en el código que solo ocurre cuando se agrega y no se elimina. –
Porque si prueba varias cosas, se llamaría prueba de plétora. – tchen
La respuesta a "¿Crees que las pruebas unitarias son la bomba?" por lo general se reduce a la pregunta "¿Qué tan bueno eres en los simulacros y la arquitectura del código?". Si no puedes dividir tu código en unidades individuales para probar (simula las entradas y salidas, y solo ejecutas el código que estás probando), entonces las pruebas unitarias simplemente no encajarán. Te encontrarás escribiendo las mismas configuraciones/desmantelamientos una y otra vez y tardarán una eternidad en ejecutarse. – TheGrimmScientist