Search code examples
groovyconsoleassert

Why Groovy's power assert prints failure messages twice?


$ groovy -e 'assert 1 == 2'
Caught: Assertion failed: 

assert 1 == 2
         |
         false

Assertion failed: 

assert 1 == 2
         |
         false

        at script_from_command_line.run(script_from_command_line:1)

Why is this happening? How can disable/configure this?

Receiving the output twice is mildly irritating when I'm working on a simple script and want to write some asserts at the end of it and execute/test the script in Vim with !groovy %


Solution

  • Rather late but, for what it's worth... as well as for posterity :)

    Notice the Caught: prefix on the first occurrence of the message. When a script throws an exception (that's not caught), by default groovy prints (to stderr) this prefix, the exception's toString() and its stack trace and then it exits.

    Thus, I would say that the first occurrence of the message represents the "default" behaviour / error handling for uncaught exceptions while the second is due to a "special" handling of PowerAssertionErrors / assert keyword in Groovy, i.e. simply printing the error's toString().

    Using a method like the ok() below verifies this "theory" as well as giving a possible solution to the double message issue:

    def ok(assertion) {
        try {
            assert assertion
        } catch(AssertionError assertionError) {
            System.err.println(assertionError)
        }
    }
    

    As far as I've seen, this is still the behaviour in Groovy 2.5.0.

    EDIT

    Unfortunately, by using the ok() method above like ok 1 == 2, you lose the most significant information about the failing assertion as the output becomes something along the lines:

    Assertion failed:
    
    assert assertion
           |
           false
    

    A better solution (or rather workaround) would be to wrap the assertion within a closure and pass it to the ok() method:

    def ok(Closure<?> assertionExp) {
        try {
            assertionExp?.call()
        } catch(AssertionError assertionError) {
            System.err.println(assertionError)
        }
    }
    

    Using ok() becomes:

    ok { assert 1 == 2 }
    

    Yielding the output:

    Assertion failed:
    
    assert 1 == 2
             |
             false