From 8986a916a6c4f8e7e04a193217ccce670c42697e Mon Sep 17 00:00:00 2001 From: Gili Tzabari Date: Mon, 13 Jan 2025 11:53:46 -0500 Subject: [PATCH] When returning multiple failures, eliminate any duplicate messages. --- README.md | 12 +++---- docs/changelog.md | 4 +++ docs/features.md | 6 ++-- docs/supported_libraries.md | 8 ++--- .../java/ValidationFailures.java | 31 +++++++++---------- .../internal/validator/AbstractValidator.java | 14 +++++++++ pom.xml | 6 ++-- .../test/java/ComparableTest.java | 3 +- 8 files changed, 50 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index fe5aeb46..5967af51 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # checklist Requirements API -[![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.java/10.7/) +[![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.java/10.8/) [![Changelog](https://img.shields.io/badge/changelog-A345D5.svg)](docs/changelog.md) [![javascript, typescript](https://img.shields.io/badge/other%20languages-javascript,%20typescript-457FD5.svg)](../../../requirements.js) @@ -22,7 +22,7 @@ To get started, add this Maven dependency: com.github.cowwoc.requirements java - 10.7 + 10.8 ``` @@ -152,14 +152,14 @@ This library offers the following features: Designed for discovery using your favorite IDE's auto-complete feature. The main entry points are: -* [requireThat(value, name)](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html#requireThat(T,java.lang.String)) +* [requireThat(value, name)](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html#requireThat(T,java.lang.String)) for method preconditions. - * [that(value, name)](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html#that(T,java.lang.String)) + * [that(value, name)](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html#that(T,java.lang.String)) for [class invariants, method postconditions and private methods](docs/features.md#assertion-support). - * [checkIf(value, name)](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html#checkIf(T,java.lang.String)) + * [checkIf(value, name)](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html#checkIf(T,java.lang.String)) for multiple failures and customized error handling. -See the [API documentation](https://cowwoc.github.io/requirements.java/10.7/) for more details. +See the [API documentation](https://cowwoc.github.io/requirements.java/10.8/) for more details. ## Best practices diff --git a/docs/changelog.md b/docs/changelog.md index 77fef923..eea92d76 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,10 @@ Minor updates involving cosmetic changes have been omitted from this list. See https://github.com/cowwoc/requirements.java/commits/main for a full list. +## Version 10.8 - 2025/01/13 + +* When returning multiple failures, eliminate any duplicate messages. + ## Version 10.7 - 2025/01/03 * Bugfix: If the string representation of the expected and actual values was equal, the class names were not diff --git a/docs/features.md b/docs/features.md index 2722f01b..54f718aa 100644 --- a/docs/features.md +++ b/docs/features.md @@ -130,7 +130,7 @@ String province = "Florida"; List provinces = Arrays.asList("Ontario", "Quebec", "Nova Scotia", "New Brunswick", "Manitoba", "British Columbia", "Prince Edward Island", "Saskatchewan", "Alberta", "Newfoundland and Labrador"); -List failures = checkIf(name, "name").length().isBetween(10, 30).elseGetFailures(); +List failures = new ArrayList<>(checkIf(name, "name").length().isBetween(10, 30).elseGetFailures()); failures.addAll(checkIf(provinces, "provinces").contains(province).elseGetFailures()); for (ValidationFailure failure: failures) @@ -174,7 +174,7 @@ requireThat(nameToAge, "nameToAge"). ## String diff When -a [String comparison](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/type/component/ObjectValidatorComponent#isEqualTo(java.lang.Object)) +a [String comparison](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/type/component/ObjectValidatorComponent#isEqualTo(java.lang.Object)) fails, the library outputs a diff of the values being compared. Depending on the terminal capability, you will see a [textual](textual_diff.md) or a [colored](colored_diff.md) diff. @@ -188,7 +188,7 @@ terminal. The use of colors is disabled by default if stdin or stdout are redirected, even if ANSI colors are supported. To enable colors, -invoke [GlobalConfiguration.terminalEncoding(TerminalEncoding)](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/GlobalConfiguration.html#terminalEncoding(com.github.cowwoc.requirements10.java.TerminalEncoding)). +invoke [GlobalConfiguration.terminalEncoding(TerminalEncoding)](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/GlobalConfiguration.html#terminalEncoding(com.github.cowwoc.requirements10.java.TerminalEncoding)). ## Returning the value after validation diff --git a/docs/supported_libraries.md b/docs/supported_libraries.md index 688170da..49f2e81a 100644 --- a/docs/supported_libraries.md +++ b/docs/supported_libraries.md @@ -1,11 +1,11 @@ Each module uses a separate class pair for validation. For example, -[DefaultJavaValidators](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html) +[DefaultJavaValidators](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/DefaultJavaValidators.html) and -[JavaValidators](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/JavaValidators.html) +[JavaValidators](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/java/JavaValidators.html) validate the core Java API. Similarly, -[DefaultGuavaValidators](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/guava/DefaultGuavaValidators.html) +[DefaultGuavaValidators](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/guava/DefaultGuavaValidators.html) and -[GuavaValidators](https://cowwoc.github.io/requirements.java/10.7/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/guava/GuavaValidators.html) +[GuavaValidators](https://cowwoc.github.io/requirements.java/10.8/com.github.cowwoc.requirements.java/com/github/cowwoc/requirements10/guava/GuavaValidators.html) validate the Guava API. The following table lists validators for third-party libraries: diff --git a/java/src/main/java/com/github/cowwoc/requirements10/java/ValidationFailures.java b/java/src/main/java/com/github/cowwoc/requirements10/java/ValidationFailures.java index afc4a28c..733309df 100644 --- a/java/src/main/java/com/github/cowwoc/requirements10/java/ValidationFailures.java +++ b/java/src/main/java/com/github/cowwoc/requirements10/java/ValidationFailures.java @@ -69,14 +69,7 @@ public boolean throwOnFailure() { if (failures.isEmpty()) return true; - Throwable throwable; - if (failures.size() == 1) - { - ValidationFailure failure = failures.getFirst(); - throwable = failure.getException(); - } - else - throwable = new MultipleFailuresException(failures); + Throwable throwable = getThrowable(); if (cleanStackTrace) Exceptions.removeLibraryFromStackTrace(throwable); switch (throwable) @@ -87,6 +80,19 @@ public boolean throwOnFailure() } } + /** + * @return the failure exception + */ + private Throwable getThrowable() + { + if (failures.size() == 1) + { + ValidationFailure failure = failures.getFirst(); + return failure.getException(); + } + return new MultipleFailuresException(failures); + } + /** * Returns the validation failure messages. * @@ -115,14 +121,7 @@ public Throwable getException() { if (failures.isEmpty()) return null; - Throwable throwable; - if (failures.size() == 1) - { - ValidationFailure failure = failures.getFirst(); - throwable = failure.getException(); - } - else - throwable = new MultipleFailuresException(failures); + Throwable throwable = getThrowable(); if (cleanStackTrace) Exceptions.removeLibraryFromStackTrace(throwable); return throwable; diff --git a/java/src/main/java/com/github/cowwoc/requirements10/java/internal/validator/AbstractValidator.java b/java/src/main/java/com/github/cowwoc/requirements10/java/internal/validator/AbstractValidator.java index 96838e8c..6b2b19aa 100644 --- a/java/src/main/java/com/github/cowwoc/requirements10/java/internal/validator/AbstractValidator.java +++ b/java/src/main/java/com/github/cowwoc/requirements10/java/internal/validator/AbstractValidator.java @@ -158,6 +158,13 @@ public void addFailure(String message, Throwable cause, ExceptionBuilder excepti { ValidationFailureImpl failure = new ValidationFailureImpl(configuration, message, cause, exceptionBuilder, Set.of()); + for (ValidationFailure existingFailure : failures) + if (existingFailure.getMessage().equals(failure.getMessage())) + { + // Skip duplicate failure messages + return; + } + failures.add(failure); if (configuration.throwOnFailure()) { @@ -186,6 +193,13 @@ public void addFailure(String message, Throwable cause, { ValidationFailureImpl failure = new ValidationFailureImpl(configuration, message, cause, exceptionBuilder, Set.of(checkedException)); + for (ValidationFailure existingFailure : failures) + if (existingFailure.getMessage().equals(failure.getMessage())) + { + // Skip duplicate failure messages + return; + } + failures.add(failure); if (configuration.throwOnFailure()) { diff --git a/pom.xml b/pom.xml index bd23af56..e1c0355a 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ ch.qos.logback logback-classic - 1.5.15 + 1.5.16 com.github.javaparser @@ -147,7 +147,7 @@ org.twdata.maven mojo-executor - 2.4.1-m2 + 2.4.1 org.testng @@ -157,7 +157,7 @@ org.assertj assertj-core - 3.27.1 + 3.27.2 diff --git a/test/src/test/java/com/github/cowwoc/requirements10/test/java/ComparableTest.java b/test/src/test/java/com/github/cowwoc/requirements10/test/java/ComparableTest.java index 440a5997..27b6024a 100644 --- a/test/src/test/java/com/github/cowwoc/requirements10/test/java/ComparableTest.java +++ b/test/src/test/java/com/github/cowwoc/requirements10/test/java/ComparableTest.java @@ -715,9 +715,8 @@ public void multipleFailuresNullIsComparableTo() TestValidators validators = TestValidators.of(scope); Integer actual = null; + // Ensure that expectedMessages does not contain the same failure message twice List expectedMessages = List.of(""" - "actual" must be equal to 5. - actual: null""", """ "actual" must be equal to 5. actual: null"""); try (ConfigurationUpdater configurationUpdater = validators.updateConfiguration())