Есть ли простой пример использования slf4j в модульных тестах? - PullRequest
15 голосов
/ 29 сентября 2010

Я использую JUnit4 и Hibernate3 в своем проекте.Hibernate зависит от Slf4j, и поэтому мой проект также включает эту библиотеку.Теперь я хотел бы использовать Slf4j в модульных тестах для записи дополнительной информации о тестировании.Не могли бы вы привести краткий пример того, как должен выглядеть мой модульный тест, чтобы регистрировать только одну строку текста?Предпочтительно без дублирования кода в нескольких тестах.

Ответы [ 7 ]

12 голосов
/ 29 сентября 2010

Почему вы хотите регистрировать вещи в своем модульном тесте?Модульные тесты должны проходить / не проходить и должны использовать тестовую среду для указания этого.Вы не хотите читать вывод, чтобы увидеть, пройден ли тест или нет.И если это не удается, лучше всего запустить его в IDE / отладчике.

11 голосов
/ 30 сентября 2010

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

package com.example.mydao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// other imports not shown...

public class TestMyDAO extends TestCase {

    private static final Logger logger = 
        LoggerFactory.getLogger(TestMyDAO.class);


    public void testA() {
        logger.debug("Logging from testA() method");
    }

    public void testB() {
        logger.debug("Logging from testB() method");
    }

    public void testThatIAmWorkingOn() {
        logger.info("Logging from my new test method at INFO level");
    }

}

Я использую log4j в качестве фактического поставщика журналирования, поэтому мой файл конфигурации log4j.xml выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
    <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p  [%c{1}] %m %n" />
        </layout>
    </appender>

    <logger name="com.example.mydao" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate" additivity="false">
        <level value="WARN" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate.connection.DriverManagerConnectionProvider" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate.connection.C3P0ConnectionProvider" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange" additivity="false">
        <level value="WARN" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.resourcepool.BasicResourcePool" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.c3p0.C3P0Registry" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <root>
        <priority value ="WARN" />
        <appender-ref ref="consoleAppender"/>
    </root>

</log4j:configuration>

Это дает мне вывод информационного уровня из моего класса JUnit, а также некоторые полезные вещи из среды выполнения Hibernate и других библиотек, используемых с Hibernate.Настройте по своему вкусу.

Наконец, мне нужно убедиться, что все следующие библиотеки находятся в моем classpath при выполнении тестов JUnit:

  • slf4j-api-1.6.0.jar
  • slf4j-log4j12-1.6.0.jar
  • log4j-1.2.16.jar
  • log4j.xml (мой файл конфигурации, показанный выше)
  • Некоторая версия JUnit времени выполнения JAR
  • Все файлы JAR обычно присутствуют при запуске приложения в рабочей среде

Это то, что я делаю при использовании log4j.Если вы используете другую реализацию ведения журнала, то отрегулируйте соответственно.Неважно, используете ли вы другую версию slf4j, если «API» и JAR-файлы реализации имеют одинаковую версию (у меня оба 1.6.0).

5 голосов
/ 26 января 2016

Другим решением является переключение реализации ведения журнала на простую реализацию только для тестов.

Так в вашем pom.xml

    <!-- Depend on slf4j API -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>

    <!-- Use SimpleLogger as the slf4j implementation in test -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.12</version>
        <scope>test</scope>
    </dependency>

    <!-- Use log4j as the slf4j implementation during runtime (not test) -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
        <scope>runtime</scope>
    </dependency>

SimpleLogger просто записывает все в stderr по умолчанию и не требует никаких файлов конфигурации

2 голосов
/ 29 сентября 2010

Мы используем log4j в качестве нашего выходного регистратора;

private static Logger log = LoggerFactory.getLogger(MyClassHere.class);

slf4j должен без проблем найти и использовать log4j, если вы настроите его правильно.Чтобы упростить жизнь, я бы использовал этот шаблон Eclipse, так как вы будете писать этот код неплохо:

private static Logger log = LoggerFactory.getLogger(${enclosing_type}.class);
${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}

для тестов, я бы порекомендовал вам не подниматься выше уровня INFO и держать большинство вещей дляDEBUG.Если вы действительно хотите разумно отлавливать множество ошибок, то я бы порекомендовал взглянуть на PositronLogger, который является приложением файла журнала, который будет молча обрабатывать все вплоть до TRACE, но выводит его в файл, только если он фиксирует ERROR;вроде путешествий во времени:)

http://github.com/andreaja/PositronLogger

0 голосов
/ 03 января 2018

Добавление журналов при написании новых тестов полезно. В то же время, когда тесты выполняются в конвейере CI или CD, вы хотите, чтобы протоколирование было отключено (или, по крайней мере, менее подробно). Иногда сбои являются временными, особенно при сквозном запуске, поэтому полезно иметь соответствующий вывод в консольном журнале заданий CI. Эта статья описывает это очень хорошо - https://gualtierotesta.wordpress.com/2015/11/01/tutorial-logging-during-tests/

0 голосов
/ 26 января 2016

При использовании log4j 1 в качестве базовой реализации slf4j

log4j ничего не регистрирует по умолчанию, кроме вас,

  • имеет log4j.properties файл в пути к классам
  • набор -Dlog4j.configuration=file:///path/to/log4j.properties. Если вы используете maven, это можно сделать в вашей конфигурации maven-surefire-plugin.
  • настроить конфигурацию log4j программно, например, методом @BeforeClass

    @BeforeClass
    public static void beforeClass() {
        BasicConfigurator.resetConfiguration();
        BasicConfigurator.configure();
    }
    

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

0 голосов
/ 29 сентября 2010

Мне кажется, это неприятный запах.

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

Модульное тестирование должно быть автоматизировано, вмешательство человека необходимо только в том случае, если ваши инструменты сборки сообщают вам, что определенный тест не пройден, и причину сбоя следует указывать с использованием всех этих методов проверки (например, assertEquals)

...