Могу ли я автоматически выполнить тестовые сценарии JUnit один раз с включенным ведением журнала и один раз с отключенным ведением журнала? - PullRequest
6 голосов
/ 03 июня 2009

Я нашел решение, см. Мой собственный ответ ниже. У кого-нибудь есть более элегантный?

Я хочу сделать это, чтобы увеличить охват кода и найти тонкие ошибки.

Предположим, что тестируется следующий класс:

public class Foo {
    private final Logger logger = LoggerFactory.getLogger(Foo.class);
    public void bar() {
        String param=[..];
        if(logger.isInfoEnabled()) logger.info("A message with parameter {}", param);

        if(logger.isDebugEnabled()) {
            // some complicated preparation for the debug message
            logger.debug([the debug message]);
        }
    }
}

и следующий тестовый класс:

public class FooTest {
    @Test
    public void bar() {
        Foo foo=new Foo();
        foo.bar();
    }
}

Инструмент покрытия кода, например, Cobertura правильно сообщит, что только некоторые из условных ветвей были проверены.

info и debug либо активируются, либо деактивируются для регистратора.

Помимо того, что вы плохо выглядите в своей оценке покрытия, это представляет реальный риск.

Что если есть какой-то побочный эффект, вызванный кодом внутри if (logger.isDebugEnabled ())? Что если ваш код работает только в том случае, если DEBUG включен, и с треском проваливается, если уровень журнала установлен на INFO? (Это на самом деле произошло в одном из наших проектов: p)

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

Есть ли способ сделать что-то подобное с JUnit? Я знаю, как глобально включить или отключить всю мою регистрацию в Logback, поэтому проблема заключается в следующем: как выполнить тесты дважды, один раз с включенным ведением журнала, один раз с отключенным ведением журнала.

p.s. Мне известен этот вопрос , но я не думаю, что это дубликат. Меня меньше беспокоят абсолютные значения покрытия, а тонкие, трудно обнаруживаемые ошибки, которые могут содержаться внутри if (logger.isDebugEnabled ()).

Ответы [ 5 ]

4 голосов
/ 03 июня 2009

Я решил эту проблему, реализовав базовый класс, который должны расширяться тестовыми классами, если такая функциональность желательна.

Статья Написание параметризованного теста JUnit содержало решение.

См. LoggingTestBase для базового класса ведения журнала и LoggingTestBaseExampleTest для простого примера его использования.

Каждый содержащийся тестовый метод выполняется три раза:

1. Он выполняется с использованием ведения журнала, как определено в logback-test.xml, как обычно. Это должно помочь при написании / отладке тестов.

2. Выполняется со всеми включенными журналами и записывается в файл. Этот файл удаляется после теста.

3. Выполняется с отключенной регистрацией.

Да, LoggingTestBase нужна документация;)

3 голосов
/ 03 июня 2009

Вы пробовали просто поддерживать два отдельных файла конфигурации журнала? Каждый из них будет регистрироваться на разных уровнях от корневого регистратора.

Все журналы отключены :

...
<root>
    <priority value="OFF"/>
    <appender-ref ref="LOCAL_CONSOLE"/>
</root>
...

Все журналы включены :

...
<root>
    <priority value="ALL"/>
    <appender-ref ref="LOCAL_CONSOLE"/>
</root>
...

Выполнение будет указывать различные конфигурации пути к классам через системный параметр:

-Dlog4j.configuration=path/to/logging-off.xml
-Dlog4j.configuration=path/to/logging-on.xml
2 голосов
/ 03 июня 2009

Я бы рекомендовал перейти с JUnit на TestNG. TestNG имеет много дополнительных функций по сравнению с JUnit. Он позволяет вам запускать тесты несколько раз с различной конфигурацией, и я думаю, это то, что вам нужно

1 голос
/ 03 июня 2009

eqbridges предложение о простом запуске тестов дважды в разных контекстах журналирования кажется самым простым. Вам не нужно забывать кодировать логику в каждом благословенном тесте, за одним большим преимуществом. Во-вторых, вы можете легко понять, какой уровень ведения журнала виноват.

При этом существует пара стратегий, если вам просто нужно было сделать это за один прогон теста.

Для 3.8 я бы поставил все в комплекты и сделал два комплекта, по одному для каждого уровня ведения журнала, который устанавливает уровень ведения журнала перед запуском тестов. Функционально это то же самое, что дважды запускать весь набор тестов с разными параметрами командной строки, за исключением того, что вы получаете его за один запуск.

В JUnit 4.x на ум приходит пара дополнительных опций:

Один из них - пользовательский бегун. Хотя я не могу думать обо всем, что вам нужно было бы сделать, чтобы сделать эту работу, но бегун, который фактически запускает тест дважды и комментирует тест с помощью @RunWith ваш пользовательский бегун, мог бы работать.

Другое - параметризованные тесты. Хотя на самом деле вам придется настроить каждый тест на получение параметров (для этого требуется конструктор, который принимает аргументы), а затем установить уровень журнала в соответствии с параметром.

РЕДАКТИРОВАТЬ: В ответ на ваш запрос с практическими рекомендациями по параметризованным тестам, здесь является Javadoc на бегун, чтобы начать, а здесь является более практичным руководство.

0 голосов
/ 04 июня 2009

Если вы чувствуете, что у вас слишком много журналирования, если вы все включаете, возможно, вы могли бы попытаться сократить количество журналирования. Это не очень полезно, если компьютер слишком много для того, чтобы зачитывать, не говоря уже о том, чтобы человек читал.

...