tipos - ¿Cómo puedo incluir caracteres especiales(tabulación, nueva línea) en una cadena de resultados de doctest de python?




tipos de variables en python (4)

Conseguí que funcionara al escapar del carácter de tabulación en la cadena esperada:

>>> function_that_returns_tabbed_text()
'\\t\\t\\tsometext\\t\\t'

en lugar de

>>> function_that_returns_tabbed_text()
\t\t\tsometext\t\t

Dado el siguiente script de python:

# dedupe.py
import re

def dedupe_whitespace(s,spacechars='\t '):
    """Merge repeated whitespace characters.
    Example:
    >>> dedupe_whitespace(r"Green\t\tGround")  # doctest: +REPORT_NDIFF
    'Green\tGround'
    """
    for w in spacechars:
        s = re.sub(r"("+w+"+)", w, s)
    return s

La función funciona según lo previsto en el intérprete de python:

$ python
>>> import dedupe
>>> dedupe.dedupe_whitespace('Purple\t\tHaze')
'Purple\tHaze'
>>> print dedupe.dedupe_whitespace('Blue\t\tSky')
Blue    Sky

Sin embargo, el ejemplo de doctest falla porque los caracteres de la pestaña se convierten en espacios antes de la comparación con la cadena de resultados:

>>> import doctest, dedupe
>>> doctest.testmod(dedupe)

da

Failed example:
    dedupe_whitespace(r"Green           Ground")  #doctest: +REPORT_NDIFF
Differences (ndiff with -expected +actual):
    - 'Green  Ground'
    ?       -
    + 'Green Ground'

¿Cómo puedo codificar los caracteres de tabulación en una cadena heredoc doctest para que la comparación de los resultados de la prueba se realice correctamente?


Debe establecer el NORMALIZE_WHITESPACE . O, alternativamente, capture la salida y compárela con el valor esperado:

def dedupe_whitespace(s,spacechars='\t '):
    """Merge repeated whitespace characters.
    Example:
    >>> output = dedupe_whitespace(r"Black\t\tGround")  #doctest: +REPORT_NDIFF
    >>> output == 'Black\tGround'
    True
    """

De la sección de documentación de doctest ¿Cómo se reconocen los ejemplos de Docstring? :

Todos los caracteres de las pestañas duras se expanden a espacios, utilizando tabulaciones de 8 columnas. Las pestañas en la salida generada por el código probado no se modifican. Debido a que todas las pestañas duras en la salida de muestra están expandidas, esto significa que si la salida del código incluye pestañas duras, la única manera en que puede pasar el doctest es si la opción o directiva NORMALIZE_WHITESPACE está vigente. Alternativamente, la prueba se puede reescribir para capturar la salida y compararla con un valor esperado como parte de la prueba. Este manejo de las pestañas en la fuente se realizó mediante prueba y error, y ha demostrado ser la forma menos propensa a manejarlas. Es posible usar un algoritmo diferente para manejar las pestañas escribiendo una clase personalizada DocTestParser .

Edit: Mi error, entendí los documentos al revés. Las pestañas se expanden a 8 espacios tanto en el argumento de cadena que se pasa a dedupe_whitespace como en el literal de cadena que se compara en la siguiente línea, por lo que la output contiene:

"Black Ground"

y se está comparando con:

"Black        Ground"

No puedo encontrar una manera de superar esta limitación sin escribir su propio DocTestParser o probar los espacios deduplicados en lugar de pestañas.


Esta es básicamente la respuesta de YatharhROCK, pero un poco más explícita. Puede utilizar cadenas en bruto o doble de escape. ¿Pero por qué?

Necesita que la cadena literal contenga un código de Python válido que, cuando se interpreta, es el código que desea ejecutar / probar. Estos dos funcionan:

#!/usr/bin/env python

def split_raw(val, sep='\n'):
  r"""Split a string on newlines (by default).

  >>> split_raw('alpha\nbeta\ngamma')
  ['alpha', 'beta', 'gamma']
  """
  return val.split(sep)


def split_esc(val, sep='\n'):
  """Split a string on newlines (by default).

  >>> split_esc('alpha\\nbeta\\ngamma')
  ['alpha', 'beta', 'gamma']
  """
  return val.split(sep)

import doctest
doctest.testmod()

El efecto de usar cadenas en bruto y el efecto de doble escape (escape de la barra) ambos deja en la cadena dos caracteres, la barra y la n. Este código se pasa al intérprete de Python, que toma "barra diagonal luego n" para significar "carácter de nueva línea" dentro de una cadena literal.

Usa lo que prefieras.


He conseguido que esto funcione con la notación de cadena literal para la cadena de documentos:

def join_with_tab(iterable):
    r"""
    >>> join_with_tab(['1', '2'])
    '1\t2'
    """

    return '\t'.join(iterable)

if __name__ == "__main__":
    import doctest
    doctest.testmod()




doctest