From dac885bc6e8bccd5f770bc7b8f89961e04048b48 Mon Sep 17 00:00:00 2001 From: Edward Hou <36526373+wordhou@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:53:05 -0700 Subject: [PATCH] More consise reporting for contains.atLeast(1) (#934) --- README.md | 18 +++------ .../creators/impl/ContainsAssertionCreator.kt | 40 +++++++++++++++++-- .../impl/ContainsObjectsAssertionCreator.kt | 39 ++++++++++++++++-- .../CharSequenceContainsAssertionCreator.kt | 2 + .../impl/InAnyOrderEntriesAssertionCreator.kt | 2 + .../impl/InAnyOrderValuesAssertionCreator.kt | 27 +++++-------- ...equenceToContainAtLeastExpectationsSpec.kt | 8 ++-- ...ceToContainNotToContainExpectationsSpec.kt | 8 ++-- ...rSequenceToContainRegexExpectationsSpec.kt | 3 +- .../CharSequenceToContainSpecBase.kt | 1 + .../IterableToContainEntriesSpecBase.kt | 1 + ...AnyOrderAtLeast1EntriesExpectationsSpec.kt | 18 +++------ ...nAnyOrderAtLeast1ValuesExpectationsSpec.kt | 9 ++--- ...InAnyOrderAtLeastValuesExpectationsSpec.kt | 9 ++--- .../integration/IterableToContainSpecBase.kt | 1 + ...bleToHaveElementsAndAnyExpectationsSpec.kt | 12 ++---- settings.gradle.kts | 21 ++++++++-- .../DescriptionCharSequenceAssertion.kt | 2 + .../DescriptionIterableAssertion.kt | 4 +- .../DescriptionCharSequenceAssertion.kt | 2 + .../DescriptionIterableAssertion.kt | 4 +- 21 files changed, 148 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 9e74a75b4..5c025294c 100644 --- a/README.md +++ b/README.md @@ -999,8 +999,7 @@ expect(listOf(1, 2, 2, 4)).toContain(2, 3) expected that subject: [1, 2, 2, 4] (java.util.Arrays.ArrayList <1234789>) ◆ contains, in any order: ⚬ an element which equals: 3 (kotlin.Int <1234789>) - ⚬ ▶ number of such entries: 0 - ◾ is at least: 1 + » but no such element was found ``` @@ -1039,13 +1038,11 @@ expected that subject: [1, 2, 2, 4] (java.util.Arrays.ArrayList <1234789> ◆ contains, in any order: ⚬ an element which: » is less than: 0 (kotlin.Int <1234789>) - ⚬ ▶ number of such entries: 0 - ◾ is at least: 1 + » but no such element was found ⚬ an element which: » is greater than: 2 (kotlin.Int <1234789>) » is less than: 4 (kotlin.Int <1234789>) - ⚬ ▶ number of such entries: 0 - ◾ is at least: 1 + » but no such element was found ``` @@ -1085,8 +1082,7 @@ expected that subject: [1, 2, 3, 4] (java.util.Arrays.ArrayList <1234789> ◆ contains, in any order: ⚬ an element which: » is less than: 0 (kotlin.Int <1234789>) - ⚬ ▶ number of such entries: 0 - ◾ is at least: 1 + » but no such element was found ```
@@ -1739,8 +1735,7 @@ expected that subject: "calling myNullableFun with ..." <1234789> ◆ ▶ myNullableFun(-2147483648): null » contains: ⚬ value: "min" <1234789> - ⚬ ▶ number of matches: - ◾ is at least: 1 + » but no match was found ◆ ▶ myNullableFun(2147483647): "2147483647" <1234789> ◾ equals: "max" <1234789> ``` @@ -1888,8 +1883,7 @@ expected that subject: () -> kotlin.Nothing (readme.examples.MostExamples ◾ is instance of type: String (kotlin.String) -- Class: java.lang.String ◾ contains: ⚬ value: "no no no" <1234789> - ⚬ ▶ number of matches: - ◾ is at least: 1 + » but no match was found ℹ Properties of the unexpected IllegalArgumentException » message: "no no no..." <1234789> » stacktrace: diff --git a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/basic/contains/creators/impl/ContainsAssertionCreator.kt b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/basic/contains/creators/impl/ContainsAssertionCreator.kt index 6a510c80a..4d3a871aa 100644 --- a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/basic/contains/creators/impl/ContainsAssertionCreator.kt +++ b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/basic/contains/creators/impl/ContainsAssertionCreator.kt @@ -2,11 +2,14 @@ package ch.tutteli.atrium.logic.creating.basic.contains.creators.impl import ch.tutteli.atrium.assertions.AssertionGroup import ch.tutteli.atrium.assertions.builders.assertionBuilder +import ch.tutteli.atrium.assertions.builders.withExplanatoryAssertion import ch.tutteli.atrium.creating.AssertionContainer import ch.tutteli.atrium.logic.creating.basic.contains.Contains import ch.tutteli.atrium.logic.assertions.impl.LazyThreadUnsafeAssertionGroup +import ch.tutteli.atrium.logic.creating.basic.contains.checkers.AtLeastChecker import ch.tutteli.atrium.reporting.Text import ch.tutteli.atrium.reporting.translating.Translatable +import ch.tutteli.atrium.reporting.translating.TranslatableWithArgs /** * Represents the base class for [Contains.Creator]s, providing a template to fulfill its job. @@ -31,6 +34,17 @@ abstract class ContainsAssertionCreator, searchCriteria: List @@ -83,9 +97,27 @@ abstract class ContainsAssertionCreator AssertionGroup ): AssertionGroup { - val count = search(multiConsumableContainer, searchCriterion) - val featureAssertion = featureFactory(count, descriptionNumberOfOccurrences) + val assertions = mutableListOf() + if (searchBehaviour is NotSearchBehaviour) { + val mismatches = mismatchesForNotSearchBehaviour(multiConsumableContainer, searchCriterion) + if (mismatches.isNotEmpty()) assertions.add(createExplanatoryGroupForMismatches(mismatches)) + } else { + val count = search(multiConsumableContainer, searchCriterion) + val featureAssertion = featureFactory(count, descriptionNumberOfOccurrences) + assertions.add(featureAssertion) + } - return assertionBuilder.list + return if (assertions.isEmpty()) { + assertionBuilder.invisibleGroup + .withAssertion( + assertionBuilder.createDescriptive(groupDescription, searchCriterion, trueProvider) + ).build() + } else assertionBuilder.list .withDescriptionAndRepresentation(groupDescription, searchCriterion) - .withAssertion(featureAssertion) + .withAssertions(assertions) .build() } @@ -67,4 +83,19 @@ abstract class ContainsObjectsAssertionCreator, searchCriterion: SC): Int + + /** + * Finds the mismatched indices and values when the [searchBehaviour] is `NotSearchBehaviour` in the subject of the + * given [multiConsumableContainer] and creates a list of assertions about the mismatched indexed values + * + * @param multiConsumableContainer The provider of the subject of this expectation in which we shall look for something + * not matching the given [searchCriterion]. + * @param searchCriterion The search criterion used to determine whether something matches or not. + * + * @return A list of [Assertion]s that describe the indexed values that did not match the [searchCriterion] + */ + protected open fun mismatchesForNotSearchBehaviour( + multiConsumableContainer: AssertionContainer, + searchCriterion: SC + ): List = emptyList() } diff --git a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/charsequence/contains/creators/impl/CharSequenceContainsAssertionCreator.kt b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/charsequence/contains/creators/impl/CharSequenceContainsAssertionCreator.kt index 246d66c61..e5209d91b 100644 --- a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/charsequence/contains/creators/impl/CharSequenceContainsAssertionCreator.kt +++ b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/charsequence/contains/creators/impl/CharSequenceContainsAssertionCreator.kt @@ -37,6 +37,8 @@ class CharSequenceContainsAssertionCreator): AssertionContainer = container.changeSubject.unreported { it.toString() }.toAssertionContainer() diff --git a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderEntriesAssertionCreator.kt b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderEntriesAssertionCreator.kt index be4eb47b5..87a4d3546 100644 --- a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderEntriesAssertionCreator.kt +++ b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderEntriesAssertionCreator.kt @@ -53,6 +53,8 @@ class InAnyOrderEntriesAssertionCreator( IterableLikeContains.Creator.() -> Unit)?> { override val descriptionContains: Translatable = DescriptionIterableAssertion.CONTAINS + override val descriptionNotFound: Translatable = DescriptionIterableAssertion.ELEMENT_NOT_FOUND + override val descriptionNumberOfElementsFound: Translatable = DescriptionIterableAssertion.NUMBER_OF_ELEMENTS_FOUND override fun makeSubjectMultipleTimesConsumable(container: AssertionContainer): AssertionContainer> = turnSubjectToList(container, converter) diff --git a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderValuesAssertionCreator.kt b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderValuesAssertionCreator.kt index 8699b68f4..865714ecb 100644 --- a/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderValuesAssertionCreator.kt +++ b/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/creating/iterable/contains/creators/impl/InAnyOrderValuesAssertionCreator.kt @@ -43,6 +43,8 @@ class InAnyOrderValuesAssertionCreator( override val descriptionContains: Translatable = DescriptionIterableAssertion.CONTAINS override val descriptionNumberOfOccurrences: Translatable = DescriptionIterableAssertion.NUMBER_OF_OCCURRENCES override val groupDescription: Translatable = DescriptionIterableAssertion.AN_ELEMENT_WHICH_EQUALS + override val descriptionNotFound: Translatable = DescriptionIterableAssertion.ELEMENT_NOT_FOUND + override val descriptionNumberOfElementsFound: Translatable = DescriptionIterableAssertion.NUMBER_OF_ELEMENTS_FOUND override fun makeSubjectMultipleTimesConsumable(container: AssertionContainer): AssertionContainer> = turnSubjectToList(container, converter) @@ -50,23 +52,16 @@ class InAnyOrderValuesAssertionCreator( override fun search(multiConsumableContainer: AssertionContainer>, searchCriterion: SC): Int = multiConsumableContainer.maybeSubject.fold({ -1 }) { subject -> subject.filter { it == searchCriterion }.size } - override fun searchAndCreateAssertion( + /** + * Override in any subclass that wants to report mismatched elements individually when the [searchBehaviour] + * is [NotSearchBehaviour] + */ + override fun mismatchesForNotSearchBehaviour( multiConsumableContainer: AssertionContainer>, - searchCriterion: SC, - featureFactory: (Int, Translatable) -> AssertionGroup - ): AssertionGroup { - return if (searchBehaviour is NotSearchBehaviour) { - val list = multiConsumableContainer.maybeSubject.getOrElse { emptyList() } - val mismatches = createIndexAssertions(list) { (_, element) -> element == searchCriterion } - val assertions = mutableListOf() - if (mismatches.isNotEmpty()) assertions.add(createExplanatoryGroupForMismatches(mismatches)) - assertionBuilder.list - .withDescriptionAndRepresentation(groupDescription, searchCriterion) - .withAssertions(assertions) - .build() - } else { - super.searchAndCreateAssertion(multiConsumableContainer, searchCriterion, featureFactory) - } + searchCriterion: SC + ): List { + val list = multiConsumableContainer.maybeSubject.getOrElse { emptyList() } + return createIndexAssertions(list) { (_, element) -> element == searchCriterion } } /** diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainAtLeastExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainAtLeastExpectationsSpec.kt index a968cf447..1cc286c94 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainAtLeastExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainAtLeastExpectationsSpec.kt @@ -142,7 +142,7 @@ abstract class CharSequenceToContainAtLeastExpectationsSpec( it("${toContainAtLeastPair.first("'h'", "once")} throws AssertionError") { expect { fluentHelloWorld.toContainAtLeastFun(1, 'h') - }.toThrow { messageToContain("$atLeast: 1", "$valueWithIndent: 'h'") } + }.toThrow { messageToContain(noMatchFoundDescr, "$valueWithIndent: 'h'") } } it("${toContainAtLeastIgnoringCasePair.first("'h'", "once")} does not throw") { fluentHelloWorld.toContainAtLeastIgnoringCaseFun(1, 'h') @@ -151,7 +151,7 @@ abstract class CharSequenceToContainAtLeastExpectationsSpec( it("${toContainAtLeastPair.first("'H', 'E'", "once")} throws AssertionError") { expect { fluentHelloWorld.toContainAtLeastFun(1, 'H', 'E') - }.toThrow { messageToContain(atLeast, 'E') } + }.toThrow { messageToContain(noMatchFoundDescr, 'E') } } it("${toContainAtLeastIgnoringCasePair.first("'H', 'E'", "once")} does not throw") { fluentHelloWorld.toContainAtLeastIgnoringCaseFun(1, 'H', 'E') @@ -162,7 +162,7 @@ abstract class CharSequenceToContainAtLeastExpectationsSpec( fluentHelloWorld.toContainAtLeastFun(1, 'E', 'H') }.toThrow { message { - toContain("$atLeast: 1", "$valueWithIndent: 'E'") + toContain(noMatchFoundDescr, "$valueWithIndent: 'E'") notToContain("$valueWithIndent: 'H'") } } @@ -181,7 +181,7 @@ abstract class CharSequenceToContainAtLeastExpectationsSpec( fluentHelloWorld.toContainAtLeastFun(1, 'H', 'E', 'w', 'r') }.toThrow { message { - toContain("$atLeast: 1", "$valueWithIndent: 'E'", "$valueWithIndent: 'w'") + toContain(noMatchFoundDescr, "$valueWithIndent: 'E'", "$valueWithIndent: 'w'") notToContain("$valueWithIndent: 'H'", "$valueWithIndent: 'r'") } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainNotToContainExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainNotToContainExpectationsSpec.kt index 16e9740ac..f27351675 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainNotToContainExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainNotToContainExpectationsSpec.kt @@ -42,8 +42,7 @@ abstract class CharSequenceToContainNotToContainExpectationsSpec( messageToContain( "$rootBulletPoint$toContainDescr: $separator" + "$valueWithIndent: \"Hello\"", - "$numberOfOccurrences: 0", - "$atLeast: 1" + noMatchFoundDescr ) } } @@ -103,9 +102,8 @@ abstract class CharSequenceToContainNotToContainExpectationsSpec( fluent.toContainFun("hello", "robert") }.toThrow { message { - this.toContain.exactly(2).values( - "$numberOfOccurrences: 0", - "$atLeast: 1" + this.toContain.exactly(2).value( + noMatchFoundDescr ) this.toContain.exactly(1).values( "$rootBulletPoint$toContainDescr: $separator", diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainRegexExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainRegexExpectationsSpec.kt index 99e0d0fbb..e8f135200 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainRegexExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainRegexExpectationsSpec.kt @@ -134,8 +134,7 @@ abstract class CharSequenceToContainRegexExpectationsSpec( toContain( "$rootBulletPoint$toContainDescr: $separator" + "$regexWithIndent: ${roberto.toLowerCase()}", - "$numberOfOccurrences: 0", - "$atLeast: 1" + noMatchFoundDescr ) } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainSpecBase.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainSpecBase.kt index fb6e357d0..4eaf18879 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainSpecBase.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/CharSequenceToContainSpecBase.kt @@ -20,6 +20,7 @@ abstract class CharSequenceToContainSpecBase(spec: Root.() -> Unit) : Spek(spec) val numberOfOccurrences = DescriptionCharSequenceAssertion.NUMBER_OF_OCCURRENCES.getDefault() val value = DescriptionCharSequenceAssertion.VALUE.getDefault() val stringMatchingRegex = DescriptionCharSequenceAssertion.STRING_MATCHING_REGEX.getDefault() + val noMatchFoundDescr = DescriptionCharSequenceAssertion.NOT_FOUND.getDefault() val atLeast = DescriptionCharSequenceAssertion.AT_LEAST.getDefault() val atMost = DescriptionCharSequenceAssertion.AT_MOST.getDefault() diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainEntriesSpecBase.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainEntriesSpecBase.kt index caea66122..98aa69c00 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainEntriesSpecBase.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainEntriesSpecBase.kt @@ -27,6 +27,7 @@ abstract class IterableToContainEntriesSpecBase( val indexDescr = String.format(DescriptionIterableAssertion.INDEX.getDefault(), index) return "$indexDescr: ${value.toString()}" } + val noSuchEntryDescr = DescriptionIterableAssertion.ELEMENT_NOT_FOUND.getDefault() fun index(index: Int) = String.format(DescriptionIterableAssertion.INDEX.getDefault(), index) diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec.kt index cb0ff313e..b5671c500 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec.kt @@ -62,8 +62,7 @@ abstract class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhich: $separator", "$toBeLessThanDescr: 1.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } @@ -75,8 +74,7 @@ abstract class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec( message { toContain.exactly(2).values( "$anElementWhich: $separator", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) toContain.exactly(1).values( "$rootBulletPoint$toContainInAnyOrder: $separator", @@ -100,8 +98,7 @@ abstract class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec( "$anElementWhich: $separator", "$toBeGreaterThanDescr: 1.0", "$toBeLessThanDescr: 2.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } @@ -161,8 +158,7 @@ abstract class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhich: $separator", "$toBeDescr: 2.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } @@ -177,8 +173,7 @@ abstract class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec( message { toContain.exactly(2).values( "$anElementWhich: $separator", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) toContain.exactly(1).values( "$rootBulletPoint$toContainInAnyOrder: $separator", @@ -200,8 +195,7 @@ abstract class IterableToContainInAnyOrderAtLeast1EntriesExpectationsSpec( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhich: $separator", "$isDescr: null", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec.kt index 7d8453bfb..e4f0b9cf8 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec.kt @@ -41,8 +41,7 @@ abstract class IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec( messageToContain( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhichIs: 1.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchValueDescr ) } } @@ -73,8 +72,7 @@ abstract class IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec( messageToContain( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhichIs: 9.5", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchValueDescr ) } } @@ -84,8 +82,7 @@ abstract class IterableToContainInAnyOrderAtLeast1ValuesExpectationsSpec( }.toThrow { message { toContain.exactly(2).values( - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchValueDescr ) toContain.exactly(1).values( "$rootBulletPoint$toContainInAnyOrder: $separator", diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeastValuesExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeastValuesExpectationsSpec.kt index c02d6cbbf..dd110c7dd 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeastValuesExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainInAnyOrderAtLeastValuesExpectationsSpec.kt @@ -90,14 +90,14 @@ abstract class IterableToContainInAnyOrderAtLeastValuesExpectationsSpec( it("${toContainAtLeastPair.first("1.1", "once")} throws AssertionError") { expect { expect(oneToSeven()).toContainAtLeastFun(1, 1.1) - }.toThrow { messageToContain("$atLeastDescr: 1", "$anElementWhichIs: 1.1") } + }.toThrow { messageToContain(noSuchValueDescr, "$anElementWhichIs: 1.1") } } it("${toContainAtLeastPair.first("1.0, 2.3", "once")} throws AssertionError mentioning only 2.3") { expect { expect(oneToSeven()).toContainAtLeastFun(1, 1.0, 2.3) }.toThrow { message { - toContain("$atLeastDescr: 1", "$anElementWhichIs: 2.3") + toContain(noSuchValueDescr, "$anElementWhichIs: 2.3") notToContain("$anElementWhichIs: 1.0") } } @@ -107,7 +107,7 @@ abstract class IterableToContainInAnyOrderAtLeastValuesExpectationsSpec( expect(oneToSeven()).toContainAtLeastFun(1, 2.3, 1.0) }.toThrow { message { - toContain("$atLeastDescr: 1", "$anElementWhichIs: 2.3") + toContain(noSuchValueDescr, "$anElementWhichIs: 2.3") notToContain("$anElementWhichIs: 1.0") } } @@ -118,8 +118,7 @@ abstract class IterableToContainInAnyOrderAtLeastValuesExpectationsSpec( }.toThrow { message { toContain.exactly(2).values( - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchValueDescr ) toContain.exactly(1).values( "$rootBulletPoint$toContainInAnyOrder: $separator", diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainSpecBase.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainSpecBase.kt index 3b2c9a8c6..96d2433eb 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainSpecBase.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToContainSpecBase.kt @@ -47,6 +47,7 @@ abstract class IterableToContainSpecBase(spec: Root.() -> Unit) : Spek(spec) { val hasDescriptionBasic = DescriptionBasic.HAS.getDefault() val nextElement = DescriptionIterableAssertion.NEXT_ELEMENT.getDefault() val notToContainDescr = DescriptionIterableAssertion.CONTAINS_NOT.getDefault() + val noSuchValueDescr = DescriptionIterableAssertion.ELEMENT_NOT_FOUND.getDefault() val sizeDescr = DescriptionCollectionAssertion.SIZE.getDefault() val atLeastDescr = DescriptionIterableAssertion.AT_LEAST.getDefault() diff --git a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToHaveElementsAndAnyExpectationsSpec.kt b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToHaveElementsAndAnyExpectationsSpec.kt index b5d9f58c4..98c7f0cea 100644 --- a/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToHaveElementsAndAnyExpectationsSpec.kt +++ b/misc/specs/atrium-specs-common/src/main/kotlin/ch/tutteli/atrium/specs/integration/IterableToHaveElementsAndAnyExpectationsSpec.kt @@ -46,8 +46,7 @@ abstract class IterableToHaveElementsAndAnyExpectationsSpec( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhich: $separator", "$toBeLessThanDescr: 1.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } @@ -65,8 +64,7 @@ abstract class IterableToHaveElementsAndAnyExpectationsSpec( "$anElementWhich: $separator", "$isGreaterThanDescr: 1.0", "$toBeLessThanDescr: 2.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } @@ -105,8 +103,7 @@ abstract class IterableToHaveElementsAndAnyExpectationsSpec( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhich: $separator", "$toBeDescr: 2.0", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } @@ -124,8 +121,7 @@ abstract class IterableToHaveElementsAndAnyExpectationsSpec( "$rootBulletPoint$toContainInAnyOrder: $separator", "$anElementWhich: $separator", "$isDescr: null", - "$numberOfOccurrences: 0", - "$atLeastDescr: 1" + noSuchEntryDescr ) } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 4033075a6..f4b1bf70b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -35,7 +35,12 @@ buildscript { "IterableContains.*Spec.*points to containsNot", // we improved reporting for notToContain with 0.17.0 "IterableContainsNot(Entries|Values)AssertionsSpec.*`containsNot( nullable)?`.*throws AssertionError", - "IterableNoneAssertionsSpec.*`(none|containsNot)( nullable)?`.*throws AssertionError" + "IterableNoneAssertionsSpec.*`(none|containsNot)( nullable)?`.*throws AssertionError", + // changed reporting for contains.atLeast(1) with 0.17.0 + or( + "(CharSequence|Iterable)Contains.*Spec", + "IterableAnyAssertionsSpec" + ) + ".*`.*(any|contains).*`.*(throws.*AssertionError|failing cases)" ) + ".*)", // we don't use asci bullet points in reporting since 0.17.0 // but have own tests to assure that changing bullet points work @@ -98,7 +103,12 @@ buildscript { "IterableContains.*Spec.*points to containsNot", // we improved reporting for notToContain with 0.17.0 "IterableContainsNot(Entries|Values)AssertionsSpec.*`containsNot.*`.*throws AssertionError", - "IterableNoneAssertionsSpec.*`(none|containsNot).*`.*throws AssertionError" + "IterableNoneAssertionsSpec.*`(none|containsNot).*`.*throws AssertionError", + // changed reporting for contains.atLeast(1) with 0.17.0 + or( + "(CharSequence|Iterable)Contains.*Spec", + "IterableAnyAssertionsSpec" + ) + ".*`.*(any|contains).*`.*(throws.*AssertionError|failing cases)" ) + ".*)", // we don't use asci bullet points in reporting since 0.17.0 // but have own tests to assure that changing bullet points work @@ -162,7 +172,12 @@ buildscript { "IterableExpectationsSpec.*`(containsNoDuplicates|contains noDuplicates)`", // we improved reporting for notToContain with 0.17.0 "IterableContainsNot(Entries|Values)ExpectationsSpec.*`containsNot.*`.*throws AssertionError", - "IterableNoneExpectationsSpec.*`(none|containsNot).*`.*throws AssertionError" + "IterableNoneExpectationsSpec.*`(none|containsNot).*`.*throws AssertionError", + // changed reporting for contains.atLeast(1) with 0.17.0 + or( + "(CharSequence|Iterable)Contains.*Spec", + "IterableAnyExpectationsSpec" + ) + ".*`.*(any|contains).*`.*(throws.*AssertionError|failing cases)" ) + ".*)").let { commonPatterns -> Pair( // bc diff --git a/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt b/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt index 2254c9bef..1f5a7b474 100644 --- a/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt +++ b/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt @@ -19,6 +19,8 @@ enum class DescriptionCharSequenceAssertion(override val value: String) : String IGNORING_CASE("%s, Gross-/Kleinschreibung ignorierend"), MATCHES("stimmt vollständig überein mit"), MISMATCHES("stimmt nicht vollständig überein mit"), + NOT_FOUND("aber es wurde kein Treffer gefunden"), + NUMBER_OF_MATCHES_FOUND("und %s Treffer wurden gefunden"), NUMBER_OF_OCCURRENCES("Anzahl Treffer"), STARTS_WITH("beginnt mit"), STARTS_NOT_WITH("beginnt nicht mit"), diff --git a/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt b/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt index 1ebe94abf..e9241c7af 100644 --- a/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt +++ b/translations/de_CH/atrium-translations-de_CH-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt @@ -46,7 +46,9 @@ enum class DescriptionIterableAssertion(override val value: String) : StringBase NEXT_ELEMENT("ein nächstes Element"), NO_ELEMENTS("❗❗ kann nicht eruiert werden, leeres Iterable"), DUPLICATE_ELEMENTS("doppelte Elemente"), - DUPLICATED_BY("(dupliziert von Index: %s") + DUPLICATED_BY("(dupliziert von Index: %s"), + ELEMENT_NOT_FOUND("aber es konnte kein solches Element gefunden werden"), + NUMBER_OF_ELEMENTS_FOUND("und % Elemente wurden gefunden") } internal const val COULD_NOT_EVALUATE_DEFINED_ASSERTIONS = diff --git a/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt b/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt index e92df97ac..b61c7e178 100644 --- a/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt +++ b/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionCharSequenceAssertion.kt @@ -19,6 +19,8 @@ enum class DescriptionCharSequenceAssertion(override val value: String) : String IGNORING_CASE("%s, ignoring case"), MATCHES("matches entirely"), MISMATCHES("does not match entirely"), + NOT_FOUND("but no match was found"), + NUMBER_OF_MATCHES_FOUND("and %s matches were found"), NUMBER_OF_OCCURRENCES("number of matches"), STARTS_WITH("starts with"), STARTS_NOT_WITH("does not start with"), diff --git a/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt b/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt index 5592252e2..0008ff740 100644 --- a/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt +++ b/translations/en_GB/atrium-translations-en_GB-common/src/main/kotlin/ch/tutteli/atrium/translations/DescriptionIterableAssertion.kt @@ -46,7 +46,9 @@ enum class DescriptionIterableAssertion(override val value: String) : StringBase NEXT_ELEMENT("a next element"), NO_ELEMENTS("❗❗ cannot be determined, empty Iterable"), DUPLICATE_ELEMENTS("duplicate elements"), - DUPLICATED_BY("duplicated by index: %s") + DUPLICATED_BY("duplicated by index: %s"), + ELEMENT_NOT_FOUND("but no such element was found"), + NUMBER_OF_ELEMENTS_FOUND("and %s such elements were found") } internal const val COULD_NOT_EVALUATE_DEFINED_ASSERTIONS = "Could not evaluate the defined assertion(s)"