Marco UnitTest - Doctest

La distribución estándar de Python contiene el módulo 'Doctest'. La funcionalidad de este módulo permite buscar fragmentos de texto que parecen sesiones interactivas de Python y ejecuta estas sesiones para ver si funcionan exactamente como se muestran.

Doctest puede ser muy útil en los siguientes escenarios:

  • Para verificar que las cadenas de documentación de un módulo estén actualizadas verificando que todos los ejemplos interactivos aún funcionen como se documenta.

  • Para realizar pruebas de regresión verificando que los ejemplos interactivos de un archivo de prueba o un objeto de prueba funcionen como se esperaba.

  • Para escribir documentación de tutorial para un paquete, ilustrada abundantemente con ejemplos de entrada y salida

En Python, una 'docstring' es una cadena literal que aparece como la primera expresión en una clase, función o módulo. Se ignora cuando se ejecuta la suite, pero el compilador lo reconoce y se coloca en el__doc__atributo de la clase, función o módulo adjunto. Dado que está disponible a través de la introspección, es el lugar canónico para la documentación del objeto.

Es una práctica habitual poner el uso de ejemplo de diferentes partes del código Python dentro de la cadena de documentos. El módulo doctest permite verificar que estas cadenas de documentos estén actualizadas con las revisiones intermitentes en el código.

En el siguiente código, se define una función factorial intercalada con el uso de ejemplo. Para verificar si el uso del ejemplo es correcto, llame a la función testmod () en el módulo doctest.

"""
This is the "example" module.

The example module supplies one function, factorial(). For example,

>>> factorial(5)
120
"""

def factorial(x):
   """Return the factorial of n, an exact integer >= 0.
   >>> factorial(-1)
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
   """
   
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testmod()

Ingrese y guarde el script anterior como FactDocTest.py e intente ejecutar este script desde la línea de comando.

Python FactDocTest.py

No se mostrará ningún resultado a menos que el ejemplo falle. Ahora, cambie la línea de comando a lo siguiente:

Python FactDocTest.py –v

La consola ahora mostrará el siguiente resultado:

C:\Python27>python FactDocTest.py -v
Trying:
   factorial(5)
Expecting:
   120
ok
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

Si, por otro lado, el código de la función factorial () no da el resultado esperado en la cadena de documentos, se mostrará el resultado de la falla. Por ejemplo, cambie f = 2 en lugar de f = 1 en el script anterior y ejecute el doctest nuevamente. El resultado será el siguiente:

Trying:
   factorial(5)
Expecting:
   120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
   120
Got:
   240
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
1 items passed all tests:
   1 tests in __main__.factorial
**********************************************************************
1 items had failures:
   1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.

Doctest: comprobación de ejemplos en un archivo de texto

Otra aplicación sencilla de doctest es probar ejemplos interactivos en un archivo de texto. Esto se puede hacer con la función testfile ().

El siguiente texto se almacena en un archivo de texto llamado 'ejemplo.txt'.

Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
   >>> from example import factorial
Now use it:
   >>> factorial(5)
   120

El contenido del archivo se trata como una cadena de documentos. Para verificar los ejemplos en el archivo de texto, use la función testfile () del módulo doctest.

def factorial(x):
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testfile("example.txt")
  • Al igual que con testmod (), testfile () no mostrará nada a menos que falle un ejemplo. Si un ejemplo falla, entonces los ejemplos que fallaron y las causas de las fallas se imprimen en la consola, usando el mismo formato que testmod ().

  • En la mayoría de los casos, copiar y pegar una sesión de consola interactiva funciona bien, pero doctest no intenta hacer una emulación exacta de ningún shell de Python específico.

  • Cualquier salida esperada debe seguir inmediatamente a la línea final '>>>' o '...' que contiene el código, y la salida esperada (si la hay) se extiende a la siguiente línea '>>>' o espacio en blanco.

  • La salida esperada no puede contener una línea de espacios en blanco, ya que dicha línea se toma para señalar el final de la salida esperada. Si la salida esperada contiene una línea en blanco, coloque <BLANKLINE> en su ejemplo de prueba de documentos en cada lugar donde se espera una línea en blanco.