El uso de Doctest es una herramienta poderosa que te permite escribir pruebas directamente en la documentación del código, lo que facilita que otros desarrolladores comprendan y verifiquen los resultados esperados. Además de los Unit Tests tradicionales, Doctest permite que tus comentarios sean interactivos, ofreciendo ejemplos funcionales que se ejecutan dentro del código de Python. Veamos cómo puedes utilizarlo de manera eficiente.
¿Qué es Doctest y cómo se usa?
Doctest es una librería que está incluida en Python y que permite crear pruebas en los comentarios del código. Esto lo hace práctico ya que puedes escribir pruebas de manera muy similar a una sesión interactiva de Python. Solo debes añadir los ejemplos dentro de los comentarios y ejecutarlos con el comando python -m doctest.
¿Cómo se estructuran las pruebas en Doctest?
Para escribir una prueba, simplemente crea un comentario que simule una sesión interactiva. Estas sesiones se caracterizan por comenzar con >>>. Por ejemplo, si tienes una función de suma en tu clase Calculator, podrías escribir lo siguiente:
>>>sum(5,7)12
Esto se ejecutará como si estuvieras en el shell de Python, y esperará que la salida sea 12. Si el resultado no coincide con lo esperado, Doctest te notificará el error.
¿Qué hacer si hay un error en la prueba?
Si Doctest encuentra un error, revisa el mensaje de error y ajusta el código o la prueba según sea necesario. Por ejemplo, si ejecutas una prueba y esperabas 12 pero el resultado fue 11, Doctest te informará de la discrepancia. Solucionas el error, corriges el comentario, y ejecutas nuevamente.
¿Cómo manejar excepciones en Doctest?
Doctest también te permite probar excepciones. Si tienes una función que lanza un ValueError al intentar dividir por cero, puedes capturar este comportamiento en el comentario:
>>> divide(10,0)Traceback (most recent call last):...ValueError: División por 0 no permitida
Este tipo de pruebas asegura que las excepciones se manejen correctamente y ayuda a otros desarrolladores a entender los casos de error.
¿Por qué es importante documentar con Doctest?
La documentación clara es clave en cualquier proyecto de software, y Doctest facilita agregar ejemplos en el código que no solo explican cómo usar las funciones, sino que además se prueban automáticamente. Esto garantiza que la documentación esté siempre alineada con el comportamiento real del código.
¿Qué reto implica utilizar Doctest?
El reto de este enfoque es agregar suficiente documentación con ejemplos ejecutables que cubran todos los casos, incluyendo los casos de borde, como divisiones por cero o parámetros inválidos. Este proceso no solo mejora la calidad del código, sino también la de la documentación, haciéndola más útil para todo el equipo.
def deposit(self, amount):"""
Deposita una cantidad en la cuenta y devuelve el saldo nuevo.:param amount:Cantidad de dinero a depositar(debe ser positiva).Ejemplos:>>> account =BankAccount(100)>>> account.deposit(50)120>>> account.deposit(-10)150>>> account.deposit(0)150"""
if amount >0: self.balance+= amount
self._log_transaction(f'Deposited {amount}. New balance: {self.balance}')return self.balance```def deposit(self, amount):""" Deposita una cantidad en la cuenta y devuelve el saldo nuevo. :param amount:Cantidad de dinero a depositar(debe ser positiva). Ejemplos:>>> account =BankAccount(100)>>> account.deposit(50)120>>> account.deposit(-10)150>>> account.deposit(0)150""" if amount >0: self.balance+= amount self.\_log\_transaction(f'Deposited {amount}. New balance: {self.balance}')return self.balance
¡Adición de pruebas y posibles casos - Reto Clase!!
🧪 Cómo ejecutar los doctests
Agrega esto al final del archivo:
if __name__ =="__main__":import doctest
doctest.testmod()
def sum(a, b):"""
Suma dos números.>>>sum(5,7)12>>>sum(4,-4)0>>>sum(0,0)0>>>sum(-3,-2)-5>>>sum(1.5,2.5)4.0>>>sum("a","b")'ab'>>>sum([1],[2])[1,2]"""
return a + b
def subtract(a, b):"""
Resta dos números.>>>subtract(10,5)5>>>subtract(0,0)0>>>subtract(-5,-3)-2>>>subtract(2.5,1.0)1.5>>>subtract("a","b")Traceback(most recent call last):...TypeError: unsupported operand type(s)for-:'str' and 'str'"""
return a - b
def multiply(a, b):"""
Multiplica dos valores.>>>multiply(3,4)12>>>multiply(-2,5)-10>>>multiply(0,100)0>>>multiply(2.5,2)5.0>>>multiply("a",3)'aaa'>>>multiply([1],2)[1,1]>>>multiply("a","b")Traceback(most recent call last):...TypeError: can't multiply sequence by non-int of type 'str'
"""
return a * b
def divide(a, b):"""
Divide dos números.Lanza error si el divisor es cero.>>>divide(10,2)5.0>>>divide(5,2)2.5>>>divide(-6,3)-2.0>>>divide(0,5)0.0>>>divide(10,0)Traceback(most recent call last):...ValueError:Cannot divide by zero
>>>divide("a",1)Traceback(most recent call last):...TypeError: unsupported operand type(s)for/:'str' and 'int'"""
if b ==0: raise ValueError("Cannot divide by zero")return a / b
Dejo mi respuesta del reto:
def sum(a, b):"""
Esta función lo que prueba es la suma de dos números eneteros.>>>sum(2,3)5"""
return a + b
def subtract(a, b):""""Esta función lo que prueba es la resta de dos números enteros
>>>subtract(15,3)12"""
return a - b
def multiply(a, b):""""Esta función lo que prueba es la multiplicación de dos números enteros
>>>multiply(10,6)60"""
return a * b
def divide(a, b):""""Esta función prueba la división entre dos números, pero igual lanza un error
para cuando se intenta dividir entre cero.>>>divide(10,0)Traceback(most recent call last):ValueError:Cannot divide by zero
>>>divide(6,3)2.0"""
if(b ==0): raise ValueError("Cannot divide by zero")return a / b