Is there any reason why `asClue` doesn't print the...
# kotest
k
Is there any reason why
asClue
doesn't print the clue in this example?
Copy code
test("foo") {
  "some clue".asClue {
    emptyList<Unit>().single()
  }
}
stacktrace:
Copy code
List is empty.
java.util.NoSuchElementException: List is empty.
	at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:616)
l
I think it's because you don't have an assertion that fails but an exception.
Copy code
emptyList<Unit>().shouldNotBeEmpty()
should display the clue
k
that was my hunch... so because
single()
throws NPE or
IllegalArgumentException
and not the
AssertionFailedError
? Might explain why half of our test failures do not include clues - quite a lot of our testing infrastructure code and logic doesn't use kotest assertions because it doesn't need to and it's easier that way. Unfortunately that clue doesn't get printed in these cases.
We use
single { someCondition }
quite frequently instead of
shouldHaveSingleElement { }
in our tests.
single
returns the item and that's what we need in most of our tests. Whereas
shouldHaveSingleElement
returns the subjected list...
Perhaps I could wrap `asClue`/`withClue` into my own extension and wrap thrown exceptions into
AssertionFailedError
in meantime 🤔
o
It's a bit different and can be overcome. Answer in the issue above. However, I'd advise to stick with using only Assertion-type exceptions for test failures, as that's part of the informal protocol. Test frameworks usually differentiate between "this test failed" and "the testing machinery failed".
💯 1
k
However, I'd advise to stick with using only Assertion-type exceptions for test failures, as that's part of the informal protocol.
I think from our experience using assertion APIs only is limiting and creates very verbose code - often it's a lot easier to just call
single { someCondition }
like in this example instead of calling an extra
shouldHaveSingleElement
beforehand. Maybe I'm missing some special way on how to write this code differently?
Copy code
rows // List<RowModel>
  .single { it.title = "Row 1" }
  .onClick()
the best I can come up with is:
Copy code
rows // List<RowModel>
  .shouldHaveSingleElement { it.title == "Row 1" }
  .single { it.title = "Row 1" } // should never throw at this point but we just the matched row
  .onClick()
maybe I could reuse the predicate, but this is quite verbose, given the simplicity of the example. 🤔
e
Copy code
rows // List<RowModel>
  .forSingle { it.title == "Row 1" }
  .onClick()
should work,
forSingle
tests for the lambda and then (if a single match is found) returns the result
o
forSingle
expects a Kotest assertion inside its lambda, right? So it would be
Copy code
rows // List<RowModel>
  .forSingle { it.title shouldBe "Row 1" }
  .onClick()
e
True, thanks for the correction 🙂
👍 1