https://kotlinlang.org logo
#kotest
Title
# kotest
d

Davio

03/22/2024, 8:31 AM
Does anybody know if there is a typesafe version of
shouldBe
? It's all too easy to accidentally compare apples and oranges since
shouldBe
just accepts any type as its argument
1
c

CLOVIS

03/22/2024, 8:50 AM
There is none 😕
m

Mervyn McCreight

03/22/2024, 9:25 AM
What about shouldBeEqual?
k

Klitos Kyriacou

03/22/2024, 9:47 AM
shouldBeEqual is not typesafe either.
m

Mervyn McCreight

03/22/2024, 9:54 AM
Hm.
Copy code
infix fun <A : Any> A.shouldBeEqual(expected: A): A
Looks type safe to me though. Or am I missing something now?
k

Klitos Kyriacou

03/22/2024, 9:57 AM
The type parameter
A
will become the closest common superclass/interface between the two arguments. And all types have at least
Any
as a superclass.
1
d

Davio

03/22/2024, 10:08 AM
I guess we could force it by using
Copy code
"foo".shouldBeEqual<String>("foo")
But that doesn't look really appealing
c

CLOVIS

03/22/2024, 10:09 AM
This is why other assertion frameworks use two-parts assertions, for example with strikt:
Copy code
expectThat(foo) isEqualTo "bar"
the first function "captures" the type, so the compiler is not allowed to up-cast to Any to match the second argument.
1
d

Davio

03/22/2024, 10:14 AM
Ah I see, I still like Kotest's style better so I'll use it and accept this weird quirk
k

Klitos Kyriacou

03/22/2024, 10:20 AM
I quite like Strikt's
expectThat
and AssertK's
assertThat
because they clearly show the start of an assertion on any particular line. With Kotest, you need to scan with your eye to find a shouldXxx somewhere in the middle of a line, and only then do you know that it's an assertion.
c

CLOVIS

03/22/2024, 10:23 AM
It depends on the style. With Kotest, I tend to write many very, very short tests that only assert a very specific thing. When tests are 5 lines long, there's not really a doubt what the assertion is. With JUnit + strikt, I tend to write longer tests that assert multiple things, taking advantage of the combined expression message.
d

Davio

03/22/2024, 10:23 AM
It's a matter of taste I guess, for me Kotest's style feels more natural and less cluttered, but that's also because I usually follow a given-when-then top-down approach in my test methods, so I know the bottom part always only has assertions
1
e

Emil Kantis

03/22/2024, 11:35 AM
I started writing an inspection for
shouldBe
when comparing definitely incompatible types. Would that be an acceptable middle ground?
The problem with forcing type consistency is for cases where
shouldBe
actually treats different types as compatible, for instance comparing an array with a list
1
d

Davio

03/22/2024, 12:32 PM
An inspection would be acceptable, I don't think we can do much better
e

Emil Kantis

03/22/2024, 12:39 PM
Maybe the inspection could also be added as a detekt-rule, so it could be enforced in CI. Are you using detekt?
d

Davio

03/22/2024, 1:14 PM
Not at the moment
l

LeoColman

03/22/2024, 1:40 PM
I think we did have a discussion at some point of using Kotlin Contracts to ensure the type comparison, but the API wasn't ready for that yet. Maybe it is now?
I'm usually ok with comparing Apples to Oranges because usually the runtime will tell me "Hey dummy, you're comparing wrong". That is sometimes annoying to debug when
toString()
is the same for both classes, but usually I catch the type unsafety pretty quickly
I agree it's a 'quirk'.
shouldBe
kinda sacrifices type safety for being more dynamic
k

Klitos Kyriacou

03/22/2024, 1:52 PM
Type safety is not as important in test code as it is in production code though, is it?
d

Davio

03/22/2024, 1:57 PM
That's true, what I do like about
shouldBe
is that it's basically the most concise, yet still clear, version of
if(this != that) throw Something()
2 Views