Hamcrest isEqualIgnoringWhitespace 不忽略空格
Hamcrest isEqualIgnoringWhitespace does not Ignore whitespace
因此,由于我们需要将一些 HTML 解析为 XML 并验证 HTML 中的所有内容都在 XML 文件中,因此我们在 Unittests 中使用 Hamcrest 进行验证.由于我们不能在 XML 文件中获得更多或更少的信息,因此我们有一个不使用 contains
而使用 equalTo
的匹配器很重要。问题是我们解析但必须提取某些元素,因为它们在外部管理的数据模型中是不允许的。我们发现这样做会在某些情况下添加额外的空格(与 Jsoup 有关)。
因此,由于空格与实际内容无关,我们决定暂时忽略它们(因为这纯粹是 PoC),但我们确实希望验证我们的概念。为此,我想出了一个解决方案,它去除了每个空格 (String.replaceAll("\s","")
),同时也去除了换行符和制表符。然后将所有文本连接到一个 String 对象中,这使得阅读起来很糟糕,而且在调试时也不是一个很好的做法。所以我选择使用 Hamcrests IsEqualIgnoringWhitespace。测试时我发现它根本没有像名字所暗示的那样做任何事情。在代码中,没有删除空格、制表符或换行符,而是检查当前字符是否为空格,如果是,则之前的字符是否也包含空格。如果是这种情况,它将删除一个空格。所以从根本上讲,它只是将空格标准化为在两个单词之间只包含其中一个。
这里是class中使用的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();
}
所以本质上它根本不会忽略空格。那为什么要这样命名呢?
为了给出一些我们想要相互匹配的输入示例,这里是一些有空格但不应该有空格的文本(文本是荷兰语,但这并不重要):
m2
vs. m 2
(HTML 原文:m<sup>2</sup>
)
Tabel 3.1
vs. Tabel 3 .1
(HTML 原文:Tabel <a href="link to table">3</a>.1
)
因此,由于这些文本永远不会被普通的 equalTo
匹配器匹配,equalToIgnoringWhitespaces
实际上应该根据名称匹配它,但它没有。
你们有谁知道是否真的有一个匹配器可以忽略空格?
根据 Javadocs IsEqualIgnoringWhitespace
:
Creates a matcher of String that matches when the examined string is equal to the specified expectedString, when whitespace differences are (mostly) ignored.
这在 Matchers
Javadocs 中有更详细的解释:
Creates a matcher of String that matches when the examined string is equal to the specified expectedString, when whitespace differences are (mostly) ignored. To be exact, the following whitespace rules are applied:
- all leading and trailing whitespace of both the expectedString and the examined string are ignored
- any remaining whitespace, appearing within either string, is collapsed to a single space before comparison
以下测试验证了此行为:
@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")));
}
所以,这就解释了为什么您会看到您在问题中描述的行为。
回复:
Does anyone of you know if there actually is a matcher that actually ignores whitespaces?
您可以编写自己的匹配器。这是一个例子:
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"));
}
因此,由于我们需要将一些 HTML 解析为 XML 并验证 HTML 中的所有内容都在 XML 文件中,因此我们在 Unittests 中使用 Hamcrest 进行验证.由于我们不能在 XML 文件中获得更多或更少的信息,因此我们有一个不使用 contains
而使用 equalTo
的匹配器很重要。问题是我们解析但必须提取某些元素,因为它们在外部管理的数据模型中是不允许的。我们发现这样做会在某些情况下添加额外的空格(与 Jsoup 有关)。
因此,由于空格与实际内容无关,我们决定暂时忽略它们(因为这纯粹是 PoC),但我们确实希望验证我们的概念。为此,我想出了一个解决方案,它去除了每个空格 (String.replaceAll("\s","")
),同时也去除了换行符和制表符。然后将所有文本连接到一个 String 对象中,这使得阅读起来很糟糕,而且在调试时也不是一个很好的做法。所以我选择使用 Hamcrests IsEqualIgnoringWhitespace。测试时我发现它根本没有像名字所暗示的那样做任何事情。在代码中,没有删除空格、制表符或换行符,而是检查当前字符是否为空格,如果是,则之前的字符是否也包含空格。如果是这种情况,它将删除一个空格。所以从根本上讲,它只是将空格标准化为在两个单词之间只包含其中一个。
这里是class中使用的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();
}
所以本质上它根本不会忽略空格。那为什么要这样命名呢?
为了给出一些我们想要相互匹配的输入示例,这里是一些有空格但不应该有空格的文本(文本是荷兰语,但这并不重要):
m2
vs. m 2
(HTML 原文:m<sup>2</sup>
)
Tabel 3.1
vs. Tabel 3 .1
(HTML 原文:Tabel <a href="link to table">3</a>.1
)
因此,由于这些文本永远不会被普通的 equalTo
匹配器匹配,equalToIgnoringWhitespaces
实际上应该根据名称匹配它,但它没有。
你们有谁知道是否真的有一个匹配器可以忽略空格?
根据 Javadocs IsEqualIgnoringWhitespace
:
Creates a matcher of String that matches when the examined string is equal to the specified expectedString, when whitespace differences are (mostly) ignored.
这在 Matchers
Javadocs 中有更详细的解释:
Creates a matcher of String that matches when the examined string is equal to the specified expectedString, when whitespace differences are (mostly) ignored. To be exact, the following whitespace rules are applied:
- all leading and trailing whitespace of both the expectedString and the examined string are ignored
- any remaining whitespace, appearing within either string, is collapsed to a single space before comparison
以下测试验证了此行为:
@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")));
}
所以,这就解释了为什么您会看到您在问题中描述的行为。
回复:
Does anyone of you know if there actually is a matcher that actually ignores whitespaces?
您可以编写自己的匹配器。这是一个例子:
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"));
}