Skip to content

Commit

Permalink
print disambiguation message if display is the same
Browse files Browse the repository at this point in the history
if the types are different, add them to the error message, otherwise
just print out that they don't compare equal

Fixes #449
  • Loading branch information
evant committed Nov 29, 2023
1 parent d5f522e commit b8989e2
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
47 changes: 37 additions & 10 deletions assertk/src/commonMain/kotlin/assertk/assertions/support/support.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ internal fun display(value: Any?): String {
prefix = "{",
postfix = "}",
transform = { (k, v) -> "${display(k)}=${display(v)}" })

is BooleanArray -> value.joinToString(prefix = "[", postfix = "]", transform = ::display)
is CharArray -> value.joinToString(prefix = "[", postfix = "]", transform = ::display)
is IntArray -> value.joinToString(prefix = "[", postfix = "]", transform = ::display)
Expand All @@ -54,7 +55,31 @@ fun <T> Assert<T>.fail(expected: Any?, actual: Any?) {
if (expected == null || actual == null || expected == actual) {
expected(message = ":${show(expected)} but was:${show(actual)}", expected = expected, actual = actual)
} else {
val extractor = DiffExtractor(display(expected), display(actual))
val displayExpected = display(expected)
val displayActual = display(actual)

if (displayExpected == displayActual) {
// display() representations are the same, if the types are different, report them
val expectedType = expected::class
val actualType = actual::class

if (expectedType != actualType) {
expected(
message = ":<$displayActual> with type:${show(expectedType)} but was type:${show(actualType)} with the same string representation",
expected = expected,
actual = actual
)
} else {
// otherwise just note that they appear the same
expected(
message = ":<${displayActual}> with type:${show(expectedType)} did not compare equal to the same type with the same string representation",
expected = expected,
actual = actual,
)
}
}

val extractor = DiffExtractor(displayExpected, displayActual)
val prefix = extractor.compactPrefix()
val suffix = extractor.compactSuffix()
val expectedDiff = extractor.expectedDiff().renderSpecialWhitespace()
Expand All @@ -77,9 +102,17 @@ fun <T> Assert<T>.fail(expected: Any?, actual: Any?) {
fun <T> Assert<T>.expected(message: String, expected: Any? = NONE, actual: Any? = NONE): Nothing {
val maybeSpace = if (message.startsWith(":")) "" else " "
val maybeInstance = if (context.originatingSubject != null) " (${context.displayOriginatingSubject()})" else ""
fail(
message = "expected${formatName(name)}$maybeSpace$message$maybeInstance",
expected = expected,
actual = actual,
cause = extractCause(),
)
}

// Attempt to extract a helpful Throwable to use as a cause if the current value
// or originating subject are a Throwable or failure Result.
// Attempt to extract a helpful Throwable to use as a cause if the current value
// or originating subject are a Throwable or failure Result.
private fun <T> Assert<T>.extractCause(): Throwable? {
var cause: Throwable? = null
if (this is ValueAssert<*>) {
cause = when (value) {
Expand All @@ -95,13 +128,7 @@ fun <T> Assert<T>.expected(message: String, expected: Any? = NONE, actual: Any?
}
}
}

fail(
message = "expected${formatName(name)}$maybeSpace$message$maybeInstance",
expected = expected,
actual = actual,
cause = cause,
)
return cause
}

/**
Expand Down
21 changes: 21 additions & 0 deletions assertk/src/commonTest/kotlin/test/assertk/assertions/AnyTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ class AnyTest {
}
}

@Test fun isEqualTo_will_report_different_types_with_the_same_display_representation() {
val error = assertFailsWith<AssertionError> {
assertThat(Actual("test")).isEqualTo(Expected("test"))
}
assertEquals("expected:<test> with type:<${Expected::class}> but was type:<${Actual::class}> with the same string representation", error.message)
}

@Test fun isEqualTo_will_report_that_same_types_with_the_same_display_representation_do_not_compare_equal() {
val error = assertFailsWith<AssertionError> {
assertThat(Actual("test")).isEqualTo(Actual("test"))
}
assertEquals("expected:<test> with type:<${Actual::class}> did not compare equal to the same type with the same string representation", error.message)
}

@Test fun isNotEqualTo_non_equal_objects_passes() {
val nonEqual = BasicObject("not test")
assertThat(subject).isNotEqualTo(nonEqual)
Expand Down Expand Up @@ -491,5 +505,12 @@ class AnyTest {
}

class DifferentObject : TestObject()

class Expected(val value: String) {
override fun toString() = value
}
class Actual(val value: String) {
override fun toString() = value
}
}
}

0 comments on commit b8989e2

Please sign in to comment.