19

给定以下 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

该函数在 python 解释器中按预期工作:

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

但是,doctest 示例失败,因为制表符在与结果字符串比较之前转换为空格:

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

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

如何在 doctest heredoc 字符串中对制表符进行编码,以便正确执行测试结果比较?

4

6 回答 6

16

我已经使用文档字符串的文字字符串表示法来实现这一点:

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

    return '\t'.join(iterable)

if __name__ == "__main__":
    import doctest
    doctest.testmod()
于 2012-01-13T11:21:16.667 回答
12

是原始的 heredoc 字符串表示法 ( r""") 起到了作用:

# 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 __name__ == "__main__":
    doctest.testmod()
于 2012-01-13T23:15:24.050 回答
3

TL;DR:转义反斜杠,即在您未修改的字符串中使用\\n\\t代替\n或;\t

您可能不想让您的文档字符串原始,因为那样您将无法使用任何 Python 字符串转义,包括您可能想要的那些。

对于支持使用正常转义的方法,只需在反斜杠字符转义中转义反斜杠,以便在 Python 解释它之后,它会留下一个文字反斜杠,后跟doctest可以解析的字符。

于 2013-08-14T13:38:36.000 回答
2

这基本上是 YatharhROCK 的回答,但更明确一点。您可以使用原始字符串双重转义。但为什么?

您需要字符串文字包含有效的 Python 代码,在解释时,这些代码就是您要运行/测试的代码。这些都有效:

#!/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()

使用原始字符串的效果和双重转义(转义斜杠)的效果都在字符串中留下两个字符,斜杠和 n。这段代码被传递给 Python 解释器,它使用“slash then n”来表示字符串文字中的“换行符”。

使用任何你喜欢的。

于 2015-03-07T20:04:52.563 回答
1

您必须设置NORMALIZE_WHITESPACE或者,捕获输出并将其与预期值进行比较:

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
    """

doctest文档部分如何识别文档字符串示例?

所有硬制表符都扩展为空格,使用 8 列制表位。测试代码生成的输出中的选项卡不会被修改。因为示例输出中的任何硬标签都已展开,这意味着如果代码输出包含硬标签,则 doctest 可以通过的唯一方法是 NORMALIZE_WHITESPACE 选项或指令有效。或者,可以重写测试以捕获输出并将其与预期值进行比较,作为测试的一部分。源代码中选项卡的这种处理是通过反复试验得出的,并且已被证明是处理它们的最不容易出错的方式。通过编写自定义DocTestParser类,可以使用不同的算法来处理选项卡。

编辑:我的错误,我以相反的方式理解文档。dedupe_whitespace在传递给的字符串参数和在下一行比较的字符串文字处,制表符被扩展为 8 个空格,因此output包含:

"Black Ground"

并被比较:

"Black        Ground"

DocTestParser如果不自己编写或测试去重空格而不是制表符,我无法找到克服此限制的方法。

于 2012-01-12T12:34:47.233 回答
1

我通过转义预期字符串中的制表符来使其工作:

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

代替

>>> function_that_returns_tabbed_text()
\t\t\tsometext\t\t
于 2018-10-19T14:28:01.580 回答