Étant donné le script python suivant:
# 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 fonction fonctionne comme prévu dans l'interpréteur python:
$ python
>>> import dedupe
>>> dedupe.dedupe_whitespace('Purple\t\tHaze')
'Purple\tHaze'
>>> print dedupe.dedupe_whitespace('Blue\t\tSky')
Blue Sky
Cependant, l'exemple de doctest échoue car les caractères de tabulation sont convertis en espaces avant la comparaison avec la chaîne de résultat:
>>> import doctest, dedupe
>>> doctest.testmod(dedupe)
donne
Failed example:
dedupe_whitespace(r"Green Ground") #doctest: +REPORT_NDIFF
Differences (ndiff with -expected +actual):
- 'Green Ground'
? -
+ 'Green Ground'
Comment puis-je encoder des caractères de tabulation dans une chaîne doctest heredoc afin qu'une comparaison des résultats de test soit effectuée correctement?
J'ai réussi à utiliser la notation littérale pour la chaîne de caractères:
def join_with_tab(iterable):
r"""
>>> join_with_tab(['1', '2'])
'1\t2'
"""
return '\t'.join(iterable)
if __== "__main__":
import doctest
doctest.testmod()
C'est la notation de chaîne heredoc brute (r"""
) qui a fait l'affaire:
# filename: dedupe.py
import re,doctest
def dedupe_whitespace(s,spacechars='\t '):
r"""Merge repeated whitespace characters.
Example:
>>> dedupe_whitespace('Black\t\tGround') #doctest: +REPORT_NDIFF
'Black\tGround'
"""
for w in spacechars:
s = re.sub(r"("+w+"+)", w, s)
return s
if __== "__main__":
doctest.testmod()
C'est la réponse de YatharhROCK, mais un peu plus explicite. Vous pouvez utiliser des chaînes brutes ou double escaping. Mais pourquoi?
Vous avez besoin que le littéral de chaîne contienne un code Python valide qui, une fois interprété, correspond au code que vous souhaitez exécuter/tester. Ces deux fonctionnent:
#!/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()
L’effet de l’utilisation de chaînes brutes et l’effet de double échappement (échappent à la barre oblique) laissent dans la chaîne deux caractères, la barre oblique et le n. Ce code est transmis à l'interpréteur Python, qui prend "slash then n" pour signifier "caractère de nouvelle ligne" dans un littéral de chaîne.
Utilisez ce que vous préférez.
TL; DR: Échappe à la barre oblique inversée, c’est-à-dire, utilisez \\n
ou \\t
au lieu de \n
ou \t
dans vos chaînes non modifiées;
Vous ne voulez probablement pas rendre vos docstrings brutes car vous ne pourrez plus utiliser d’échappements de chaînes Python, y compris ceux que vous voudrez peut-être.
Pour une méthode prenant en charge les échappements normaux, il suffit d'échapper la barre oblique inversée dans l'échappement de barre oblique inversée afin que, une fois que Python l'interprète, elle laisse une barre oblique inverse littérale suivie du caractère que doctest
peut analyser.
Vous devez définir le NORMALIZE_WHITESPACE . Ou, alternativement, capturez le résultat et comparez-le à la valeur attendue:
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 section doctest
de la documentation comment les exemples de docstring sont-ils reconnus? :
Tous les caractères de tabulation sont développés en espaces, en utilisant des taquets de tabulation à 8 colonnes. Les onglets en sortie générés par le code testé ne sont pas modifiés. Etant donné que tous les onglets durs de l'exemple de sortie sont développés , cela signifie que si la sortie de code comprend des onglets durs, le doctest ne peut passer que si NORMALIZE_WHITESPACE L'option ou la directive est en vigueur. Sinon, le test peut être réécrit pour capturer la sortie et la comparer à une valeur attendue dans le cadre du test. Cette manipulation des onglets dans la source a été obtenue par essais et erreurs, et s’est révélée être le moyen le moins sujet aux erreurs. Il est possible d'utiliser un algorithme différent pour gérer les onglets en écrivant une classe personnalisée
DocTestParser
.
Edit: Mon erreur, j'ai compris la documentation à l'envers. L'argument de chaîne passé à dedupe_whitespace
et le littéral de chaîne en cours de comparaison sur la ligne suivante sont étendus à 8 espaces, de sorte que output
contienne:
"Black Ground"
et est comparé à:
"Black Ground"
Je ne peux pas trouver un moyen de surmonter cette limitation sans écrire votre propre DocTestParser
ou tester des espaces dédupliqués au lieu de tabulations.
Je l'ai fait fonctionner en échappant le caractère de tabulation dans la chaîne attendue:
>>> function_that_returns_tabbed_text()
'\\t\\t\\tsometext\\t\\t'
au lieu de
>>> function_that_returns_tabbed_text()
\t\t\tsometext\t\t