【问题标题】:Hamcrest isEqualIgnoringWhitespace does not Ignore whitespaceHamcrest isEqualIgnoringWhitespace 不会忽略空格
【发布时间】:2017-11-09 09:46:41
【问题描述】:

因此,当我们需要将一些 HTML 解析为 XML 并验证 HTML 中的所有内容是否都在 XML 文件中时,我们在 Unittests 中使用 Hamcrest 进行验证。因为我们不能在 XML 文件中包含更多或更少的信息,所以我们有一个不使用 contains 而是使用 equalTo 的匹配器非常重要。问题是我们解析但必须提取某些元素,因为它们在外部管理的数据模型中是不允许的。我们发现在某些情况下这样做可能会添加额外的空格(与 Jsoup 有关)。

因此,由于空格与实际内容无关,我们决定暂时忽略这些(因为这纯粹是 PoC),但我们确实希望验证我们的概念。为此,我想出了一个解决方案,它可以去除每个空格 (String.replaceAll("\\s","")),它还去除了换行符和制表符。然后将所有文本连接到一个 String 对象中,这使得阅读起来很糟糕,而且在调试时也不是一个很好的做法。因此,我选择使用 Hamcrests IsEqualIgnoringWhitespace。在测试时,我发现它根本不像名字所暗示的那样做任何事情。在代码中没有删除空格、制表符或换行符,而是检查当前字符是否为空格,如果是,则之前的字符是否也包含空格。如果是这种情况,它将删除一个空格。所以基本上它只会将空格规范化为在两个单词之间只包含其中一个。

下面是类中使用的stripSpace方法的代码:

public String stripSpace(String toBeStripped) {
    final StringBuilder result = new StringBuilder();
    boolean lastWasSpace = true;
    for (int i = 0; i < toBeStripped.length(); i++) {
        char c = toBeStripped.charAt(i);
        if (isWhitespace(c)) {
            if (!lastWasSpace) {
                result.append(' ');
            }
            lastWasSpace = true;
        } else {
            result.append(c);
            lastWasSpace = false;
        }
    }
    return result.toString().trim();
}

所以本质上它根本不会忽略空格。那为什么会这样命名呢?

举一些我们想要相互匹配的输入示例,这里是一些有空格但不应该有空格的文本(文本是荷兰语,但这无关紧要):

m2m 2(HTML 原文:m&lt;sup&gt;2&lt;/sup&gt;

Tabel 3.1Tabel 3 .1(HTML 原文:Tabel &lt;a href="link to table"&gt;3&lt;/a&gt;.1

因此,由于这些文本永远不会被普通的 equalTo 匹配器匹配,equalToIgnoringWhitespaces 实际上应该根据名称匹配它,但它不会。

你们中的任何人都知道是否真的存在实际上忽略空格的匹配器吗?

【问题讨论】:

  • Hamcrest 已弃用此功能并将其重命名为:Matchers.equalToCompressingWhiteSpace 也许有人听到了您的声音。 :-)

标签: java unit-testing whitespace matcher hamcrest


【解决方案1】:

根据 Javadocs IsEqualIgnoringWhitespace

创建一个字符串匹配器,当检查的字符串等于指定的预期字符串时匹配,而空白差异(大部分)被忽略。

这在Matchers Javadocs 中有更详细的解释:

创建一个字符串匹配器,当检查的字符串等于指定的预期字符串时匹配,而空格差异(大部分)被忽略。确切地说,应用了以下空格规则:

  • 预期字符串和检查字符串的所有前导和尾随空格都将被忽略
  • 出现在任一字符串中的任何剩余空格在比较之前都将折叠为一个单个空格

以下测试验证了这种行为:

@Test
public void testIsEqualIgnoringWhitespace() {
    // leading and trailing spaces are ignored
    assertThat("m 2", equalToIgnoringWhiteSpace(" m 2 "));

    // all other spaces are collapsed to a single space
    assertThat("m 2", equalToIgnoringWhiteSpace("m     2"));

    // does not match because the single space in the expected string is not collapsed any further
    assertThat("m2", not(equalToIgnoringWhiteSpace("m 2")));
}

所以,这就解释了为什么您会看到您在问题中描述的行为。

这是:

你们中的任何人都知道是否真的存在实际上忽略空格的匹配器吗?

您可以编写自己的匹配器。这是一个例子:

public class IgnoresAllWhitespacesMatcher extends BaseMatcher<String> {
    public String expected;

    public static IgnoresAllWhitespacesMatcher ignoresAllWhitespaces(String expected) {
        return new IgnoresAllWhitespacesMatcher(expected);
    }

    private IgnoresAllWhitespacesMatcher(String expected) {
        this.expected = expected.replaceAll("\\s+", "");
    }

    @Override
    public boolean matches(Object actual) {
        return expected.equals(actual);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(String.format("the given String should match '%s' without whitespaces", expected));
    }
}

使用此匹配器通过以下测试:

@Test
public void testUsingCustomIgnoringAllWhitespaceMatcher() {
    // leading and trailing spaces are ignored
    assertThat("m2", ignoresAllWhitespaces(" m 2 "));

    // intermediate spaces are ignored
    assertThat("m2", ignoresAllWhitespaces("m     2"));
}

【讨论】:

  • 我们不应该去掉实际字符串中的空格吗?所以“m 2”将匹配“m 2”
猜你喜欢
  • 2021-12-27
  • 2016-07-09
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2017-07-05
  • 2015-12-27
相关资源
最近更新 更多