Почему в Groovy power assert дважды печатает сообщения об ошибках?

$ 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)

Почему это происходит? Как это отключить/настроить?

Получение вывода дважды немного раздражает, когда я работаю над простым скриптом и хочу написать несколько утверждений в конце и выполнить/протестировать скрипт в Vim с помощью !groovy %


person Kohányi Róbert    schedule 27.05.2016    source источник
comment
Он печатает его дважды при запуске из Vim? Или это только когда вы выполняете его с -e?   -  person tim_yates    schedule 27.05.2016
comment
@tim_yates Из Vim, из командной строки, когда я использую -e или если я запускаю скрипт напрямую.   -  person Kohányi Róbert    schedule 27.05.2016


Ответы (1)


Довольно поздно, но, чего бы это ни стоило... как и для потомков :)

Обратите внимание на префикс Caught: в первом появлении сообщения. Когда сценарий выдает исключение (которое не было перехвачено), по умолчанию groovy печатает (в stderr) этот префикс, toString() исключения и его трассировку стека, а затем завершает работу.

Таким образом, я бы сказал, что первое появление сообщения представляет собой поведение/обработку ошибок по умолчанию для неперехваченных исключений, а второе связано с «особой» обработкой ключевого слова PowerAssertionErrors/assert в Groovy, т. е. простой печатью ошибки toString().

Использование метода, подобного приведенному ниже ok(), подтверждает эту «теорию», а также дает возможное решение проблемы двойного сообщения:

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

Насколько я видел, это все еще поведение Groovy 2.5.0.

ИЗМЕНИТЬ

К сожалению, используя описанный выше метод ok(), такой как ok 1 == 2, вы теряете наиболее важную информацию об ошибочном утверждении, поскольку вывод становится примерно таким:

Assertion failed:

assert assertion
       |
       false

Лучшим решением (или, скорее, обходным путем) было бы обернуть утверждение внутри замыкания и передать его методу ok():

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

Использование ok() становится:

ok { assert 1 == 2 }

Получение вывода:

Assertion failed:

assert 1 == 2
         |
         false
person Octavian Theodor    schedule 26.06.2018