Skip to content

Commit

Permalink
Contains in order more details (#29) (#3871)
Browse files Browse the repository at this point in the history
add more details on what exactly could not be matched, such as `" could
not match element 6 at index 2"` in the following example:

```
            shouldThrow<AssertionError> {
               col should containsInOrder(1, 2, 6)
            }
            }.message shouldBe "[1, 1, 2, 2, 3, 3] did not contain the elements [1, 2, 6] in order, could not match element 6 at index 2"

Co-authored-by: Emil Kantis <emil.kantis@protonmail.com>
  • Loading branch information
AlexCue987 and Kantis committed Feb 15, 2024
1 parent deb8d2a commit be59b5a
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ fun <T> containsInOrder(subsequence: List<T>): Matcher<Collection<T>?> = neverNu
if (actualIterator.next() == subsequence[subsequenceIndex]) subsequenceIndex += 1
}

val mismatchDescription = if(subsequenceIndex == subsequence.size) "" else
", could not match element ${subsequence.elementAt(subsequenceIndex).print().value} at index $subsequenceIndex"

MatcherResult(
subsequenceIndex == subsequence.size,
{ "${actual.print().value} did not contain the elements ${subsequence.print().value} in order" },
{ "${actual.print().value} did not contain the elements ${subsequence.print().value} in order$mismatchDescription" },
{ "${actual.print().value} should not contain the elements ${subsequence.print().value} in order" }
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,12 @@ fun <T> containsInOrder(subsequence: Sequence<T>): Matcher<Sequence<T>?> = never
if (actualIterator.next() == subsequenceAsList.elementAt(subsequenceIndex)) subsequenceIndex += 1
}

val mismatchDescription = if(subsequenceIndex == subsequenceAsList.size) "" else
", could not match element ${subsequenceAsList.elementAt(subsequenceIndex)} at index $subsequenceIndex"

MatcherResult(
subsequenceIndex == subsequenceAsList.size,
{ "[$actual] did not contain the elements [$subsequenceAsList] in order" },
{ "[$actual] did not contain the elements [$subsequenceAsList] in order$mismatchDescription" },
{ "[$actual] should not contain the elements [$subsequenceAsList] in order" }
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.sksamuel.kotest.matchers.collections

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.assertions.throwables.shouldThrowAny
import io.kotest.core.spec.style.WordSpec
import io.kotest.matchers.collections.containsInOrder
import io.kotest.matchers.collections.shouldContainInOrder
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.throwable.shouldHaveMessage

class InOrderTest : WordSpec() {
Expand All @@ -18,24 +20,29 @@ class InOrderTest : WordSpec() {

shouldThrow<AssertionError> {
col should containsInOrder(1, 2, 6)
}
}.message shouldBe "[1, 1, 2, 2, 3, 3] did not contain the elements [1, 2, 6] in order, could not match element 6 at index 2"

shouldThrow<AssertionError> {
col should containsInOrder(4)
}
}.message shouldBe "[1, 1, 2, 2, 3, 3] did not contain the elements [4] in order, could not match element 4 at index 0"

shouldThrow<AssertionError> {
col should containsInOrder(2, 1, 3)
}
}
"reject empty expected list" {
shouldThrowAny {
listOf(5, 3, 1, 2, 4, 2) should containsInOrder(listOf<Int>())
}.message shouldBe "expected values must not be empty"
}
"work with unsorted collections" {
val actual = listOf(5, 3, 1, 2, 4, 2)
actual should containsInOrder(3, 2, 2)
}
"print errors unambiguously" {
shouldThrow<AssertionError> {
listOf<Number>(1L, 2L) should containsInOrder(listOf<Number>(1, 2))
}.shouldHaveMessage("""[1L, 2L] did not contain the elements [1, 2] in order""")
}.shouldHaveMessage("""[1L, 2L] did not contain the elements [1, 2] in order, could not match element 1 at index 0""")
}
"support iterables with vararg" {
val actual = listOf(1, 2, 3, 4, 5).asIterable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import io.kotest.matchers.sequences.shouldNotContainNull
import io.kotest.matchers.sequences.shouldNotContainOnlyNulls
import io.kotest.matchers.sequences.shouldNotHaveCount
import io.kotest.matchers.sequences.shouldNotHaveElementAt
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain

class SequenceMatchersTest : WordSpec() {

Expand Down Expand Up @@ -788,6 +790,12 @@ class SequenceMatchersTest : WordSpec() {
sampleData.countup.shouldContainInOrder((5..15).asSequence())
}

"describe first unmatched element" {
shouldThrowAny {
sequenceOf(1, 2, 3).shouldContainInOrder(sequenceOf(2, 3, 4, 5))
}.message shouldContain "did not contain the elements [[2, 3, 4, 5]] in order, could not match element 4 at index 2"
}

fail("for overlapping sequence (variadic)") {
sampleData.countup.shouldContainInOrder(*(5..15).toList().toTypedArray())
}
Expand Down

0 comments on commit be59b5a

Please sign in to comment.