Skip to content

Commit

Permalink
add general coding rule ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE
Browse files Browse the repository at this point in the history
Signed-off-by: Manfred Hanke <[email protected]>
  • Loading branch information
hankem committed Oct 3, 2022
1 parent 6878f49 commit d0ee71a
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -480,4 +480,22 @@ public void check(JavaClass implementationClass, ConditionEvents events) {
}
};
}

/**
* A rule that checks that all {@link AssertionError AssertionErrors} (e.g. from the {@code assert} keyword) have a detail message.
* <p>
* Example:
* <pre>{@code
* assert x > 0; // violation
* throw new AssertionError(); // violation
*
* assert x > 0 : "x is not positive"; // no violation
* throw new AssertionError("x is not positive"); // no violation
* }</pre>
</p>
*/
@PublicAPI(usage = ACCESS)
public static final ArchRule ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE =
noClasses().should().callConstructor(AssertionError.class /* without detailMessage */)
.because("assertions should have a detail message");
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import com.tngtech.archunit.library.testclasses.packages.incorrect.wrongsubdir.defaultsuffix.subdir.ImplementationClassWithWrongTestClassPackageTest;
import org.junit.Test;

import static com.tngtech.archunit.library.GeneralCodingRules.ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE;
import static com.tngtech.archunit.library.GeneralCodingRules.testClassesShouldResideInTheSamePackageAsImplementation;
import static com.tngtech.archunit.testutil.Assertions.assertThatRule;
import static java.util.regex.Pattern.quote;

public class GeneralCodingRulesTest {

Expand Down Expand Up @@ -80,4 +82,37 @@ public void should_not_pass_when_none_of_multiple_matching_test_classes_resides_
);
}

@Test
public void ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE_should_fail_on_assert_without_detail_message() {
class InvalidAssertions {
void f(int x) {
assert x > 0;
}

void f() {
throw new AssertionError();
}
}
assertThatRule(ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE)
.checking(new ClassFileImporter().importClasses(InvalidAssertions.class))
.hasViolations(2)
.hasViolationMatching(quote("Method <" + InvalidAssertions.class.getName() + ".f(int)> calls constructor <java.lang.AssertionError.<init>()> in ") + ".*")
.hasViolationMatching(quote("Method <" + InvalidAssertions.class.getName() + ".f()> calls constructor <java.lang.AssertionError.<init>()> in ") + ".*");
}

@Test
public void ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE_should_accept_assert_with_detail_message() {
class ValidAssertions {
void f(int x) {
assert x > 0 : "argument should be postive";
}

void f() {
throw new AssertionError("f() should not be called");
}
}
assertThatRule(ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE)
.checking(new ClassFileImporter().importClasses(ValidAssertions.class))
.hasNoViolation();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,16 @@ private Optional<AssertionError> checkRule(ArchRule rule, JavaClasses classes) {
}

public ArchRuleCheckAssertion hasViolationMatching(String regex) {
for (String detail : evaluationResult.getFailureReport().getDetails()) {
if (detail.matches(regex)) {
return this;
}
}
throw new AssertionError(String.format("No violation matches '%s'", regex));
assertThat(evaluationResult.getFailureReport().getDetails())
.as("violation details (should match '%s')", regex)
.anyMatch(detail -> detail.matches(regex));
return this;
}

public ArchRuleCheckAssertion hasNoViolationMatching(String regex) {
for (String detail : evaluationResult.getFailureReport().getDetails()) {
if (detail.matches(regex)) {
throw new AssertionError(String.format("Violation matches '%s'", regex));
}
}
assertThat(evaluationResult.getFailureReport().getDetails())
.as("violation details (should not match '%s')", regex)
.noneMatch(detail -> detail.matches(regex));
return this;
}

Expand Down

0 comments on commit d0ee71a

Please sign in to comment.