Skip to content

Commit

Permalink
Fixes #493 : Add partial regex match assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
ptemplier authored and joel-costigliola committed Oct 19, 2015
1 parent e83cbf9 commit e113706
Show file tree
Hide file tree
Showing 8 changed files with 460 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/main/java/org/assertj/core/api/AbstractCharSequenceAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -794,4 +794,47 @@ public S isSubstringOf(CharSequence sequence) {
strings.assertIsSubstringOf(info, actual, sequence);
return myself;
}

/**
* Verifies that the actual {@code CharSequence} contains the given regular expression.
* <p>
* Example :
* <pre><code class='java'> // assertion will pass
* assertThat(&quot;Frodo&quot;).containsPattern(&quot;Fr.d&quot;);
*
* // assertion will fail
* assertThat(&quot;Frodo&quot;).containsPattern(&quot;Frodod&quot;);</code></pre>
*
* @param regex the regular expression to find in the actual {@code CharSequence}.
* @return {@code this} assertion object.
* @throws NullPointerException if the given pattern is {@code null}.
* @throws PatternSyntaxException if the regular expression's syntax is invalid.
* @throws AssertionError if the actual {@code CharSequence} is {@code null}.
* @throws AssertionError if the given regular expression cannot be found in the actual {@code CharSequence}.
*/
public S containsPattern(CharSequence regex) {
strings.assertContainsPattern(info, actual, regex);
return myself;
}

/**
* Verifies that the actual {@code CharSequence} contains the given regular expression pattern.
* <p>
* Example :
* <pre><code class='java'> // assertion will pass
* assertThat(&quot;Frodo&quot;).containsPattern(Pattern.compile(&quot;Fr.d&quot;));
*
* // assertion will fail
* assertThat(&quot;Frodo&quot;).containsPattern(Pattern.compile(&quot;Frodod&quot;));</code></pre>
*
* @param pattern the regular expression to find in the actual {@code CharSequence}.
* @return {@code this} assertion object.
* @throws NullPointerException if the given pattern is {@code null}.
* @throws AssertionError if the actual {@code CharSequence} is {@code null}.
* @throws AssertionError if the given regular expression cannot be found in the actual {@code CharSequence}.
*/
public S containsPattern(Pattern pattern) {
strings.assertContainsPattern(info, actual, pattern);
return myself;
}
}
35 changes: 35 additions & 0 deletions src/main/java/org/assertj/core/error/ShouldContainPattern.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.core.error;

/**
* Creates an error message indicating that an assertion that verifies that a {@code CharSequence} contains a pattern failed.
*
* @author Pierre Templier
*/
public class ShouldContainPattern extends BasicErrorMessageFactory {

/**
* Creates a new <code>{@link ShouldContainPattern}</code>.
* @param actual the actual value in the failed assertion.
* @param pattern a regular expression pattern.
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldContainPattern(CharSequence actual, CharSequence pattern) {
return new ShouldContainPattern(actual, pattern);
}

private ShouldContainPattern(CharSequence actual, CharSequence pattern) {
super("%nExpecting:%n %s%nto contain pattern:%n %s", actual, pattern);
}
}
38 changes: 38 additions & 0 deletions src/main/java/org/assertj/core/internal/Strings.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static org.assertj.core.error.ShouldContainCharSequenceOnlyOnce.shouldContainOnlyOnce;
import static org.assertj.core.error.ShouldContainCharSequenceSequence.shouldContainSequence;
import static org.assertj.core.error.ShouldContainOnlyDigits.shouldContainOnlyDigits;
import static org.assertj.core.error.ShouldContainPattern.shouldContainPattern;
import static org.assertj.core.error.ShouldEndWith.shouldEndWith;
import static org.assertj.core.error.ShouldMatchPattern.shouldMatch;
import static org.assertj.core.error.ShouldNotBeEmpty.shouldNotBeEmpty;
Expand All @@ -52,6 +53,7 @@
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

Expand Down Expand Up @@ -627,4 +629,40 @@ public void assertIsSubstringOf(AssertionInfo info, CharSequence actual, CharSeq
throw failures.failure(info, shouldBeSubstring(actual, sequence, comparisonStrategy));
}

/**
* Verifies that the given {@code CharSequence} contains the given regular expression.
*
* @param info contains information about the assertion.
* @param actual the given {@code CharSequence}.
* @param regex the regular expression to find in the actual {@code CharSequence}.
* @throws NullPointerException if the given pattern is {@code null}.
* @throws PatternSyntaxException if the regular expression's syntax is invalid.
* @throws AssertionError if the given {@code CharSequence} is {@code null}.
* @throws AssertionError if the actual {@code CharSequence} does not contain the given regular expression.
*/
public void assertContainsPattern(AssertionInfo info, CharSequence actual, CharSequence regex) {
checkRegexIsNotNull(regex);
assertNotNull(info, actual);
Pattern pattern = Pattern.compile(regex.toString());
Matcher matcher = pattern.matcher(actual);
if (!matcher.find()) throw failures.failure(info, shouldContainPattern(actual, pattern.pattern()));
}

/**
* Verifies that the given {@code CharSequence} contains the given regular expression.
*
* @param info contains information about the assertion.
* @param actual the given {@code CharSequence}.
* @param pattern the regular expression to find in the actual {@code CharSequence}.
* @throws NullPointerException if the given pattern is {@code null}.
* @throws AssertionError if the given {@code CharSequence} is {@code null}.
* @throws AssertionError if the given {@code CharSequence} does not contain the given regular expression.
*/
public void assertContainsPattern(AssertionInfo info, CharSequence actual, Pattern pattern) {
checkIsNotNull(pattern);
assertNotNull(info, actual);
Matcher matcher = pattern.matcher(actual);
if (!matcher.find()) throw failures.failure(info, shouldContainPattern(actual, pattern.pattern()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.core.api.charsequence;

import static org.assertj.core.test.TestData.matchAnything;
import static org.mockito.Mockito.verify;

import java.util.regex.Pattern;

import org.assertj.core.api.CharSequenceAssert;
import org.assertj.core.api.CharSequenceAssertBaseTest;
import org.junit.BeforeClass;

/**
* Tests for <code>{@link CharSequenceAssert#containsPattern(Pattern)}</code>.
*
* @author Pierre Templier
*/
public class CharSequenceAssert_containsPattern_Pattern_Test extends CharSequenceAssertBaseTest {

private static Pattern pattern;

@BeforeClass
public static void setUpOnce() {
pattern = matchAnything();
}

@Override
protected CharSequenceAssert invoke_api_method() {
return assertions.containsPattern(pattern);
}

@Override
protected void verify_internal_effects() {
verify(strings).assertContainsPattern(getInfo(assertions), getActual(assertions), pattern);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.core.api.charsequence;

import static org.assertj.core.test.TestData.matchAnything;
import static org.mockito.Mockito.verify;

import org.assertj.core.api.CharSequenceAssert;
import org.assertj.core.api.CharSequenceAssertBaseTest;
import org.junit.BeforeClass;

/**
* Tests for <code>{@link CharSequenceAssert#containsPattern(CharSequence)}</code>.
*
* @author Pierre Templier
*/
public class CharSequenceAssert_containsPattern_String_Test extends CharSequenceAssertBaseTest {

private static CharSequence regex;

@BeforeClass
public static void setUpOnce() {
regex = matchAnything().pattern();
}

@Override
protected CharSequenceAssert invoke_api_method() {
return assertions.containsPattern(regex);
}

@Override
protected void verify_internal_effects() {
verify(strings).assertContainsPattern(getInfo(assertions), getActual(assertions), regex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.core.error;

import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.error.ShouldContainPattern.shouldContainPattern;

import org.assertj.core.description.TextDescription;
import org.assertj.core.presentation.StandardRepresentation;
import org.junit.Before;
import org.junit.Test;


public class ShouldContainPattern_create_Test {

private ErrorMessageFactory factory;

@Before
public void setUp() {
factory = shouldContainPattern("Frodo", ".*Orc.*");
}

@Test
public void should_create_error_message() {
String message = factory.create(new TextDescription("Test"), new StandardRepresentation());
assertThat(message).isEqualTo(format("[Test] %nExpecting:%n \"Frodo\"%nto contain pattern:%n \".*Orc.*\""));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.core.internal.strings;

import static org.assertj.core.error.ShouldContainPattern.shouldContainPattern;
import static org.assertj.core.test.ErrorMessages.regexPatternIsNull;
import static org.assertj.core.test.TestData.matchAnything;
import static org.assertj.core.test.TestData.someInfo;
import static org.assertj.core.test.TestFailures.failBecauseExpectedAssertionErrorWasNotThrown;
import static org.assertj.core.util.FailureMessages.actualIsNull;
import static org.mockito.Mockito.verify;

import java.util.regex.PatternSyntaxException;

import org.assertj.core.api.AssertionInfo;
import org.assertj.core.internal.Strings;
import org.assertj.core.internal.StringsBaseTest;
import org.junit.Test;

/**
* Tests for <code>{@link Strings#assertMatches(AssertionInfo, CharSequence, CharSequence)}</code>.
*
* @author Pierre Templier
*/
public class Strings_assertContainsPattern_CharSequence_Test extends StringsBaseTest {

private static final String CONTAINED_PATTERN = "dark";
private String actual = "Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate… leads to suffering.";

@Test
public void should_throw_error_if_regular_expression_is_null() {
thrown.expectNullPointerException(regexPatternIsNull());
String regex = null;
strings.assertContainsPattern(someInfo(), actual, regex);
}

@Test
public void should_throw_error_if_syntax_of_regular_expression_is_invalid() {
thrown.expect(PatternSyntaxException.class);
strings.assertContainsPattern(someInfo(), actual, "*...");
}

@Test
public void should_fail_if_actual_is_null() {
thrown.expectAssertionError(actualIsNull());
strings.assertContainsPattern(someInfo(), null, matchAnything().pattern());
}

@Test
public void should_fail_if_actual_does_not_contain_regular_expression() {
AssertionInfo info = someInfo();
try {
strings.assertContainsPattern(info, actual, "Luke");
} catch (AssertionError e) {
verify(failures).failure(info, shouldContainPattern(actual, "Luke"));
return;
}
failBecauseExpectedAssertionErrorWasNotThrown();
}

@Test
public void should_pass_if_actual_contains_pattern() {
strings.assertContainsPattern(someInfo(), actual, CONTAINED_PATTERN);
}

@Test
public void should_throw_error_if_regular_expression_is_null_whatever_custom_comparison_strategy_is() {
thrown.expectNullPointerException(regexPatternIsNull());
String regex = null;
stringsWithCaseInsensitiveComparisonStrategy.assertContainsPattern(someInfo(), actual, regex);
}

@Test
public void should_throw_error_if_syntax_of_regular_expression_is_invalid_whatever_custom_comparison_strategy_is() {
thrown.expect(PatternSyntaxException.class);
stringsWithCaseInsensitiveComparisonStrategy.assertContainsPattern(someInfo(), actual, "*...");
}

@Test
public void should_fail_if_actual_is_null_whatever_custom_comparison_strategy_is() {
thrown.expectAssertionError(actualIsNull());
stringsWithCaseInsensitiveComparisonStrategy.assertContainsPattern(someInfo(), null, matchAnything().pattern());
}

@Test
public void should_fail_if_actual_does_not_contain_regular_expression_whatever_custom_comparison_strategy_is() {
AssertionInfo info = someInfo();
try {
stringsWithCaseInsensitiveComparisonStrategy.assertContainsPattern(info, actual, "Luke");
} catch (AssertionError e) {
verify(failures).failure(info, shouldContainPattern(actual, "Luke"));
return;
}
failBecauseExpectedAssertionErrorWasNotThrown();
}

@Test
public void should_pass_if_actual_contains_pattern_whatever_custom_comparison_strategy_is() {
stringsWithCaseInsensitiveComparisonStrategy.assertContainsPattern(someInfo(), actual, CONTAINED_PATTERN);
}
}

0 comments on commit e113706

Please sign in to comment.