Igor Akkerman
12/31/2019, 12:21 AMdata class Member(val name: String, val interest: String, val favoriteNumber: Int)
val members = listOf(Member("Me", "Kotlin", Random.nextInt()), Member("MyDog", "food", Random.nextInt()))
expect(members)
.containsExactly(
{ feature { f(it::name) }.toBe("Me") ; feature { f(it::interest) }.toBe("Kotlin")},
{ feature { f(it::name) }.toBe("MyDog") ; feature { f(it::interest) }.toBe("food")}
)
robstoll
01/06/2020, 6:42 AMfun Expect<Member>.hasNameAndInterest(name: String, interest: String) =
this.feature({ f(it::name) }, { toBe(name) })
.feature({ f(it::interest) }) { toBe(interest) }
then it can be rewritten to:
expect(members).containsExactly(
{ hasNameAndInterest("Me", "Kotlin") },
{ hasNameAndInterest("MyDog", "food") }
)
toBe
was only an example and you want to perform other assertions on the properties, e.g. startsWith("Kot")
then you could provide a shortcut for the properties:
val Expect<Member>.name
get() = name(this).getExpectOfFeature()
// allows to define an assertion group for the feature
fun Expect<Member>.name(assertionCreator: Expect<String>.() -> Unit) =
name(this).addToInitial(assertionCreator)
private fun name(expect: Expect<Member>) = ExpectImpl.feature.property(expect, Member::name)
Whether this boilerplate is worth it depends on how many times you use the property IMO. Then you could use it as follows:
expect(members).containsExactly(
{ name.toBe("Me") },
{ name { startsWith("Ro"); endsWith("t") } }
)
Igor Akkerman
01/06/2020, 11:45 AMch.tutteli.atrium.reporting.AtriumError: expect: [Member(name=Me, interest=Kotlin, favoriteNumber=1771517067), Member(name=MyDog, interest=food, favoriteNumber=-1574926733)] (java.util.Arrays.ArrayList <1682681674>)
◆ contains only, in order:
✔️ ▶️ entry 0: Member(name=Me, interest=Kotlin, favoriteNumber=1771517067) (atriumtest.AtriumTest.Member <613298587>)
◾ an entry which:
» ▶️ name: "Me" <1446983876>
◾ to be: "Me" <1446983876>
» ▶️ interest: "Kotlin" <1042790962>
◾ to be: "Kotlin" <1042790962>
✘ ▶️ entry 1: Member(name=MyDog, interest=food, favoriteNumber=-1574926733) (atriumtest.AtriumTest.Member <2130192211>)
◾ an entry which:
» ▶️ name: "Me" <1446983876>
◾ to be: "MyDog" <990897274>
» ▶️ interest: "Kotlin" <1042790962>
◾ to be: "foodX" <539690370>
✔️ ▶️ size: 2 (kotlin.Int <593415583>)
◾ to be: 2 (kotlin.Int <593415583>)robstoll
01/06/2020, 11:47 AMfeature { f(it::name) }
?I noticed a tiny irregularity
Igor Akkerman
01/06/2020, 11:49 AMrobstoll
01/06/2020, 11:49 AMIgor Akkerman
01/06/2020, 11:50 AMfeature { f(it::name) }
robstoll
01/06/2020, 11:50 AMan entry which:
>> name:
- to be: "My Dog"
Igor Akkerman
01/06/2020, 11:52 AMrobstoll
01/06/2020, 11:52 AMfeature
it is mainly that complicated because Kotlin has unfortunately many bugs in the area of type inference and method overloading. See the list here https://github.com/robstoll/atrium#kotlin-bugs, would be nice if you can upvote some, so jetbrains invests a bit more time in this areain order only
, it would not make sense for in any order
.Igor Akkerman
01/06/2020, 11:54 AMrobstoll
01/06/2020, 11:55 AMIgor Akkerman
01/06/2020, 11:55 AMrobstoll
01/06/2020, 12:00 PMfeature(Member::name)
in case you find that simplerIgor Akkerman
01/06/2020, 12:02 PMfeature(Member::name)
is good enough, really. No idea if something like containsExactly({Member::name toBe "Me"; Member::interest toBe "Kotlin"})
would be technically possible