assertk icon indicating copy to clipboard operation
assertk copied to clipboard

Naming a failure

Open JakeWharton opened this issue 1 year ago • 3 comments

Maybe I'm overlooking something, but I can't seem to name an assertFailure with any clarifying data.

I have a test function calling a helper with a bunch of example failing cases. When one does not fail, I just get an "Expected failure but was success" with no real useful information. On the JVM the trace can help me, but this failure is JS-specific which means I get a near-useless trace.

Something like:

@Test fun parses() {
  assertParseFailure("1")
  assertParseFailure("1.2")
  assertParseFailure("1.2.a")
  assertParseFailure("1.2.3.4")
  assertParseFailure("1.2.3-beta")
}
private fun assertParseFailure(version: String) {
  assertFailure { parse(version) }
    .isIntanceOf<ISE>()
    ...
}

I have two proposals:

First, just let me name an assertFailure and put it in the message. Easy!

Second, and a bit weirder, but what if there was an Assert-based failure-expecting version of prop/#521? If there was, I could do

assertThat(version)
  .havingFailure("parses", ::parse)
  .isInstanceOf<ISE>()
  ...

I haven't really thought through the implications of such a thing. And in general I'm not sure to what degree the outcome of #521 is solely for traversing "down" an instance vs. processing it with other types/functions.

Something to think about, though. Even if it's wrong for this specific situation (because proposal 1 seems obvious to do), maybe it's a thing that's still needed for actual instance-based property/function calls that we expect to throw?

JakeWharton avatar Apr 02 '24 02:04 JakeWharton

Yeah I'd expect assertFailure to have the same additional arguments as assertThat. Also, we still have the result assertions so

assertThat(runCatching { parse(version) }, name = version).isFailure()

should work as a work-around?

evant avatar Apr 02 '24 02:04 evant

Ran into this myself and am working around it by adding this to my code:

inline fun assertFailure(description: String? = "lambda", f: () -> Unit): Assert<Throwable> {
    @Suppress("TooGenericExceptionCaught") // Intentionally capturing all exceptions.
    try {
        f()
    } catch (t: Throwable) {
        return assertThat(t, "exception thrown from $description")
    }
    fail("expected failure but $description completed successfully")
}

dalewking avatar Apr 27 '24 05:04 dalewking

Going to try to add name to assertFailure today

JakeWharton avatar Nov 15 '24 12:11 JakeWharton