Lets say I have an `List<Int>` and I want to...
# strikt
r
Lets say I have an
List<Int>
and I want to check that the first value from the list is less than the second. How can I express this in Strikt?
Copy code
expectThat(listOf(5, 6)) {
  // this[1] is a builder, so can't do this:
  this[0].isLessThan(this[1])
}
Note because of the way the unit test is structured, I don't actually have access to the original list, only the assertion builder. So I can't just do
this[0].isLessThan(originalList[1])
.
c
Copy code
expectThat(listOf(5, 6)) {
    get {get(0)<get(1)}.isTrue()
}
šŸ‘ 1
r
Thanks!
r
Another approach would be with a custom assertion. e.g.
Copy code
expectThat(listOf(5, 6))
      .assert("first element < second") {
        if (it[0] < it[1]) pass(it)
        else fail(it)
      }
You could express it more simply with:
Copy code
expectThat(listOf(5, 6))
      .assertThat("first element < second") {
        it[0] < it[1]
      }
And if this is something you want to use in multiple places extract it as a re-usable custom assertion:
Copy code
fun Assertion.Builder<List<Int>>.firstElementIsLessThanSecond() =
    assert("first element < second") {
      if (it[0] < it[1]) pass(it)
      else fail(it)
    }
Generalizing that into a
Assertion.Builder<List<Comparable<*>>>.isOrdered
assertion would be even better
r
Great. Yeah my real use case is slightly more complex than checking if the list is ordered -- I actually need to find specific elements in the List, and then compare their attributes. However, all that is useful insight.
r
My concern with the
get { this[0] < this[1] }.isTrue()
form is that I think the error message wouldn’t be very helpful if it failed
r
Yeah it isn't
c
thats much better, I didnt know about assertThat. using get like that is my last resort hack.
but shouldnt the error message be something like expect ā€œget(0)>get(1) to be true but was falseā€?
r
This form seems to work well for my use case:
Copy code
expectThat(input) {
  filter { interestingElements }
    .hasSize(2)
    .map { extractIntAttribute }
    .assertThat("first element < second) {
      it.toList().let { it[0] < it[1] }
    }
}
Though with that setup, a generalized
isOrdered
would indeed work well instead of that last
assertThat
.
r
I was sure I had written an assertion like that but seems like not. Would probably be something worth adding to the core lib
with a
Assertion.Builder<List<*>>.isOrderedAccordingTo(Comparator)
overload
r
@christophsturm Yeah the error message with the
get
form isn't too bad, its just not quite as clear as it doesn't show the actual values:
Copy code
ā–¼ toList().let { it[0] < it[1] }:
        āœ— is true
          found false
vs
Copy code
ā–¼ [0, 0]:
      āœ— first element < second
r
It should also be possible to get the actual values into that custom assertion message
šŸ‘€ 1
Early morning here otherwise I’m sure I’d be able to tell you exactly how šŸ˜‰
r
Probably with
assert
and
fail
like this? https://strikt.io/wiki/custom-assertions/
"Describing the "actual" value"
r
yeah, I’m just not sure how to present that in this case since what you’re interested in is 2 values
Just occurred to me that another way to do it would be
Copy code
expectThat(myList.slice(0..1)) isEqualTo myList.slice(0..1).sorted()
r
Makes sense though doesn't work for my case because I have a Strikt assertion wrapper around another library's testing SDK (Apache Beam). I couldn't do that without making my wrapper more complicated.
Copy code
fun <T: Any> PAssert.IterableAssert<T>.expectThat(block: Assertion.Builder<Iterable<T>>.() -> Unit): PAssert.IterableAssert<T> {
  satisfies {
    expectThat(it, block)
    null
  }
  return this
}