1

我正在探索各种测试策略(微分、回归、单元等),并被分配了测试 GNUsCoreutils fmt实用程序的任务。我正在尝试应用随机差分测试并创建一个预言机,以断言满足实用程序的描述的后置条件。


我想做的是创建一个 Python 实用程序,它生成一个随机字符串,将文本换行应用于字符串(直到给定的行宽)以生成预期的输出,然后在生成的字符串上调用 fmt 实用程序并断言输出与预期输出匹配。为此,我正在尝试利用textwrapPython 模块。但是,我还没有找到一种方法来确保保持缩进。考虑一个包含内容的文件(file.txt)

\s\s\s\sLorem ipsum dolor sit amet, consectetuer-adipiscing elit. Curabitur dignissim venenatis pede. Quisque dui dui, ultricies ut, facilisis non, pulvinar non.

作为 fmt 实用程序的输入。调用命令fmt -w 50 file.txt会导致输出:

 \s\s\s\sLorem ipsum dolor sit amet,
 \s\s\s\sconsectetuer-adipiscing elit. Curabitur
 \s\s\s\sdignissim venenatis pede. Quisque dui dui,
 \s\s\s\sultricies ut, facilisis non, pulvinar non.

根据 fmt 实用程序文档,

默认情况下,输出中会保留空行、单词之间的空格和缩进;不连接具有不同缩进的连续输入行;选项卡在输入时扩展并在输出时引入。

fmt 更喜欢在句尾换行,并尽量避免在句子的第一个单词之后或句子的最后一个单词之前换行。断句定义为段落的结尾或以任何“.?!”结尾的单词,后跟两个空格或行尾,忽略任何插入的括号或引号。

在我尝试模仿与 fmt 实用程序相同的输出行为时,我决定使用 textwrap 模块fill功能,如下所示:

textwrap.fill(in_str, width=50, expand_tabs=True, drop_whitespace=False, fix_sentence_endings=True, break_on_hyphens=False)

根据 Python 文档,应该执行以下操作:

  1. 包裹线的最大长度将等于宽度参数 (50)。
  2. 输入中的所有制表符都将扩展为空格。
  3. 每行开头和结尾的空格(在换行之后但在缩进之前)不会被删除。
  4. 假设一个句子结尾由一个小写字母后跟“.”、“!”或“?”之一,可能后跟“””或“'”之一,后跟一个空格。
  5. 只有空格才会被认为是换行的好地方。

但是,同一输入上的 textwrap.fill 函数的输出返回:

\s\s\s\sLorem ipsum dolor sit amet, 
consectetuer-adipiscing elit.  Curabitur dignissim
 venenatis pede.  Quisque dui dui, ultricies ut, 
facilisis non, pulvinar non.  Duis quis arcu a 
purus volutpat iaculis.  Morbi id dui in diam 
ornare dictum.  Praesent consectetuer vehicula 
ipsum.  Praesent tortor massa, congue et, ornare 
in, posuere eget, pede.

如您所见,缩进级别未保持。


我可以最好地利用什么工具和/或差异测试策略来最有效地测试 fmt 实用程序?任何建议都非常感谢!

4

1 回答 1

0

尝试使用以下代码运行此代码段py.test

#!/usr/bin/env python2.7
from textwrap import TextWrapper

input_tx = """\s\s\s\sLorem ipsum dolor sit amet, consectetuer-adipiscing elit. Curabitur dignissim venenatis pede. Quisque dui dui, ultricies ut, facilisis non, pulvinar non."""
output_tx1 = """\s\s\s\sLorem ipsum dolor sit amet, consectetuer-
\s\s\s\sadipiscing elit. Curabitur dignissim
\s\s\s\svenenatis pede. Quisque dui dui, ultricies
\s\s\s\sut, facilisis non, pulvinar non."""
output_tx2 = """\s\s\s\sLorem ipsum dolor sit amet,
\s\s\s\sconsectetuer-adipiscing elit. Curabitur
\s\s\s\sdignissim venenatis pede. Quisque dui dui,
\s\s\s\sultricies ut, facilisis non, pulvinar non."""

class Test_TextWrapper:
    def test_stackoverflow_q32753000_1(self):
        sut = TextWrapper(width=50, subsequent_indent="\s\s\s\s")
        assert sut.fill(input_tx) == output_tx1

    def test_stackoverflow_q32753000_2(self):
        sut = TextWrapper(width=50, subsequent_indent="\s\s\s\s",
                          fix_sentence_endings=False,
                          break_on_hyphens=False)
        assert sut.fill(input_tx) == output_tx2

它应该向您显示如下内容:

> py.test -v -k Test_TextWrapper 
============================================== test session starts ===============================================
platform linux2 -- Python 2.7.11, pytest-2.9.0, py-1.4.31, pluggy-0.3.1 -- /usr/bin/python
cachedir: .cache
...
plugins: cov-2.2.1
collected 6 items 

test_fmt.py::Test_TextWrapper::test_stackoverflow_q32753000_1 PASSED
test_fmt.py::Test_TextWrapper::test_stackoverflow_q32753000_2 PASSED

=================================== 4 tests deselected by '-kTest_TextWrapper' ===================================
===================================== 2 passed, 4 deselected in 0.03 seconds =====================================

如您所见,我的第二个测试用例产生的输出与您的问题示例中所示的输出相同。

我目前正在为 Python 标准库类编写一个小型 Python 包装器textwrap.TextWrapper类。这个派生类将提供一个新的prefix关键字参数,它结合了initial_indentsubsequent_indent参数的效果,并从输入文本中删除了前缀。(类似于实用程序的-p选项fmt)在寻找现有技术和灵感时,我在这里找到了你的问题。

于 2016-03-28T21:02:10.440 回答