Skip to content

Commit

Permalink
ContainDuplicates should print them (#20) (#3846)
Browse files Browse the repository at this point in the history
`containDuplicates` should list duplicates that violate the assumption,
for instance:
```
           shouldThrowAny {
               listOf(1, 2, 3, 4, 2, 1) shouldNot containDuplicates()
            }.shouldHaveMessage("Collection should not contain duplicates, but has some: [1, 2]")
```
  • Loading branch information
AlexCue987 committed Jan 24, 2024
1 parent 77db319 commit f524b62
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.kotest.matchers.collections

import io.kotest.assertions.print.print
import io.kotest.matchers.Matcher
import io.kotest.matchers.MatcherResult
import io.kotest.matchers.should
Expand Down Expand Up @@ -35,10 +36,18 @@ fun <T> Collection<T>.shouldNotContainDuplicates(): Collection<T> {
}

fun <T> containDuplicates() = object : Matcher<Collection<T>> {
override fun test(value: Collection<T>) = MatcherResult(
value.toSet().size < value.size,
{ "Collection should contain duplicates" },
{
"Collection should not contain duplicates"
})
override fun test(value: Collection<T>): MatcherResult {
val duplicates = value.duplicates()
return MatcherResult(
duplicates.isNotEmpty(),
{ "Collection should contain duplicates" },
{
"Collection should not contain duplicates, but has some: ${duplicates.print().value}"
})
}
}

internal fun<T> Collection<T>.duplicates(): Collection<T> = this.groupingBy { it }
.eachCount().entries
.filter { it.value > 1 }
.map { it.key }
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.sksamuel.kotest.matchers.collections
import io.kotest.assertions.shouldFail
import io.kotest.assertions.throwables.shouldNotThrow
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.assertions.throwables.shouldThrowAny
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.WordSpec
import io.kotest.equals.Equality
Expand Down Expand Up @@ -230,6 +231,12 @@ class CollectionMatchersTest : WordSpec() {
listOf(1, 2, 3, 3).shouldContainDuplicates()
listOf(1, 2, 3, 4).shouldNotContainDuplicates()
}

"print duplicates in message" {
shouldThrowAny {
listOf(1, 2, 3, 4, 2, 1) shouldNot containDuplicates()
}.shouldHaveMessage("Collection should not contain duplicates, but has some: [1, 2]")
}
}

"singleElement" should {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sksamuel.kotest.matchers.collections

import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.collections.duplicates
import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder

class DuplicatesTest : StringSpec(){
init {
"return empty list" {
listOf(1, 2, 3, 4, null).duplicates().shouldBeEmpty()
}

"return not null duplicates" {
listOf(1, 2, 3, 4, 3, 2).duplicates() shouldContainExactlyInAnyOrder listOf(2, 3)
}

"return null duplicates" {
listOf(1, 2, 3, null, 4, 3, null, 2).duplicates() shouldContainExactlyInAnyOrder listOf(2, 3, null)
}
}
}

0 comments on commit f524b62

Please sign in to comment.