【发布时间】:2012-01-20 06:24:48
【问题描述】:
Ruby 的 Test::Unit 有一个很好的 assert_matches 方法,可以在单元测试中使用它来断言正则表达式匹配字符串。
在 JUnit 中有这样的东西吗?目前,我这样做:
assertEquals(true, actual.matches(expectedRegex));
【问题讨论】:
Ruby 的 Test::Unit 有一个很好的 assert_matches 方法,可以在单元测试中使用它来断言正则表达式匹配字符串。
在 JUnit 中有这样的东西吗?目前,我这样做:
assertEquals(true, actual.matches(expectedRegex));
【问题讨论】:
JUnit 5 的更新,没有任何额外的库。
现在您可以按照https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/Assertions.html#assertLinesMatch-java.util.List-java.util.List- 中的说明使用assertLinesMatch
创建断言是为了匹配多行文本,因此即使您尝试仅匹配一行,您也需要提供List。例如:
assertLinesMatch(List.of("Expected at the beginning.*"), List.of(contentUnderTest));
断言算法将尝试精确匹配,然后,如果失败,将使用String.match 将预期值解释为正则表达式。
重要提示:如果您的 contentUnderTest 包含多行,则正则表达式中的 .* 将不起作用(. 不匹配默认为换行符),因此您可能需要添加嵌入标志(https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#DOTALL):
// Flag ?s means match new lines
assertLinesMatch(List.of("(?s)Expected at the beginning.*"), List.of(contentWithMultipleLines));
【讨论】:
如果您使用assertThat() 和Hamcrest matcher 来测试正则表达式匹配,那么如果断言失败,您将收到一条很好的消息,指示预期的模式和实际文本。断言也会更流畅地阅读,例如
assertThat("FooBarBaz", matchesPattern("^Foo"));
使用 Hamcrest 2,您可以在 MatchesPattern.matchesPattern 找到 matchesPattern 方法。
【讨论】:
Matchers.matchesPattern(String):github.com/hamcrest/JavaHamcrest/blob/master/hamcrest-library/…
Hamcrest中有对应的matcher:org.hamcrest.Matchers.matchesPattern(String regex)。
As development of Hamcrest stalled你不能使用最新的可用 v1.3:
testCompile("org.hamcrest:hamcrest-library:1.3")
相反,您需要使用新的开发系列(但仍然是dated by Jan 2015):
testCompile("org.hamcrest:java-hamcrest:2.0.0.0")
甚至更好:
configurations {
testCompile.exclude group: "org.hamcrest", module: "hamcrest-core"
testCompile.exclude group: "org.hamcrest", module: "hamcrest-library"
}
dependencies {
testCompile("org.hamcrest:hamcrest-junit:2.0.0.0")
}
测试中:
Assert.assertThat("123456", Matchers.matchesPattern("^[0-9]+$"));
【讨论】:
使用 assertj 的另一种选择。这种方法很好,因为它允许您直接传递模式对象。
import static org.assertj.core.api.Assertions.assertThat;
assertThat("my\nmultiline\nstring").matches(Pattern.compile("(?s)my.*string", Pattern.MULTILINE));
【讨论】:
你可以使用 Hamcrest 和 jcabi-matchers:
import static com.jcabi.matchers.RegexMatchers.matchesPattern;
import static org.junit.Assert.assertThat;
assertThat("test", matchesPattern("[a-z]+"));
更多详情在这里:Regular Expression Hamcrest Matchers。
您将需要在类路径中使用这两个依赖项:
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-matchers</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
【讨论】:
您可以使用 Hamcrest,但您必须编写自己的匹配器:
public class RegexMatcher extends TypeSafeMatcher<String> {
private final String regex;
public RegexMatcher(final String regex) {
this.regex = regex;
}
@Override
public void describeTo(final Description description) {
description.appendText("matches regex=`" + regex + "`");
}
@Override
public boolean matchesSafely(final String string) {
return string.matches(regex);
}
public static RegexMatcher matchesRegex(final String regex) {
return new RegexMatcher(regex);
}
}
用法
import org.junit.Assert;
Assert.assertThat("test", RegexMatcher.matchesRegex(".*est");
【讨论】:
据我所知,没有其他选择。刚刚检查了assert javadoc 以确保。 不过,只是一点点变化:
assertTrue(actual.matches(expectedRegex));
编辑:自从 pholser 的回答以来,我一直在使用 Hamcrest 匹配器,也请检查一下!
【讨论】:
assertTrue() 肯定更好。我责怪 Eclipse 的自动完成功能,因为我对此一无所知。 ;)
assertTrue 无法像 assertEquals 或 assertThat 那样为您提供详细信息
assertTrue("Expected string matching '" +expectedRegex+ "'. Got: "+actual, actual.matches(expectedRegex));。不过它不如 Hamcrest 好。
is(true) 进行比较,那么assertThat 不会提供比assertTrue 更多的细节。要获得正确的错误消息,您需要一个不同的匹配器(或者您按照@MikeFHay 的建议手动构建消息)。
因为我也在寻找这个功能,所以我在 GitHub 上启动了一个名为 regex-tester 的项目。它是一个有助于在 Java 中轻松测试正则表达式的库(目前仅适用于 JUnit)。
这个库现在非常有限,但它确实有一个像这样工作的 Hamcrest 匹配器
assertThat("test", doesMatchRegex("tes.+"));
assertThat("test", doesNotMatchRegex("tex.+"));
更多关于如何使用 regex-tester 的信息是here。
【讨论】:
它不是 JUnit,但这是 fest-assert 的另一种方式:
assertThat(myTestedValue).as("your value is so so bad").matches(expectedRegex);
【讨论】: