Как установить статус выхода в скрипте Groovy - PullRequest
16 голосов
/ 16 февраля 2012

У нас есть Groovy Script, который завершается с status из 0, когда все работает, и non-0 status для различных типов состояний отказа.Например, если сценарий принимает пользователя и адрес электронной почты в качестве аргументов, он завершится с status из 1 для недопустимого пользователя и status из 2 для недопустимого формата адреса электронной почты.Мы используем System.exit(statusCode) для этого.Это прекрасно работает, но затрудняет написание сценария для сценария.

В тесте мы создаем GroovyShell, создаем наш Binding и вызываем shell.run(script,args).Для тестов, которые утверждают условия сбоя, System.exit() заставляет JVM (и тест) завершиться.

Существуют ли альтернативы использованию System.exit() для выхода из скрипта Groovy?Я экспериментировал с выдачей необработанных исключений, но это загромождает вывод и всегда создает код состояния 1.

В наших тестовых примерах я также экспериментировал с использованием System.metaClass.static.invokeMethod для изменения поведения System.exit(), чтобы не выходJVM, но это похоже на уродливый хак.

Ответы [ 2 ]

10 голосов
/ 17 февраля 2012

imho System.metaClass.static.invokeMethod выглядит хорошо. Это тест, и взлом здесь хорошо.

Также вы можете создать вокруг него свою собственную обертку, например:

class ExitUtils {

    static boolean enabled = true

    static exit(int code) {
        if (!ExitUtils.enabled) {
            return  //TODO set some flag?
        }
        System.exit(code)
    }

}

и отключите его для тестов.

5 голосов
/ 18 февраля 2012

Вот техника, которую мы в конечном итоге использовали.

Мы не можем просто игнорировать вызов System.exit(), так как скрипт продолжит работать. Вместо этого мы хотим вызвать исключение с желаемым кодом состояния. Мы бросаем (custom) ProgramExitException, когда в наших тестах вызывается System.exit()

class ProgramExitException extends RuntimeException {

    int statusCode

    public ProgramExitException(int statusCode) {
        super("Exited with " + statusCode)
        this.statusCode = statusCode
    }
}

тогда мы перехватываем System.exit(), чтобы вызвать это исключение

/**
 * Make System.exit throw ProgramExitException to fake exiting the VM
 */
System.metaClass.static.invokeMethod = { String name, args ->
    if (name == 'exit')
        throw new ProgramExitException(args[0])
    def validMethod =  System.metaClass.getStaticMetaMethod(name, args)
    if (validMethod != null) {
        validMethod.invoke(delegate, args)
    }
    else {
        return  System.metaClass.invokeMissingMethod(delegate, name, args)
    }
}

и, наконец, GroovyShell перехватывает ProgramExitException и возвращает код состояния из метода run.

/**
 * Catch ProgramExitException exceptions to mimic exit status codes
 * without exiting the VM
 */
GroovyShell.metaClass.invokeMethod = { String name, args ->
    def validMethod = GroovyShell.metaClass.getMetaMethod(name, args)
    if (validMethod != null) {
        try {
            validMethod.invoke(delegate, args)
        } catch (ProgramExitException e) {
            return e.statusCode
        }
    }
    else {
        return GroovyShell.metaClass.invokeMissingMethod(delegate, name, args)
    }
 }

Наши тесты могут выглядеть просто, нам не нужно ничего менять в скриптах, и мы получаем поведение, которое ожидаем от запуска в командной строке.

assertEquals 'Unexpected status code', 0, shell.run(script,[arg1, arg2])
assertEquals 'Unexpected status code', 10, shell.run(script,[badarg1, badarg2])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...