web-dev-qa-db-ja.com

単体テストでのslf4jの使用の単純なパターンはありますか?

プロジェクトでJUnit4とHibernate3を使用しています。 HibernateはSlf4jに依存しているため、私のプロジェクトにはこのライブラリも含まれています。ここで、補足テスト情報をログに記録するために、単体テストでSlf4jを使用したいと思います。 1行のテキストだけをログに記録するために、ユニットテストがどのように表示されるかについての簡単な例を教えてください。できればコードの重複なし複数のテストで。

17
yegor256

また、DAOクラスのJUnitテストでslf4jを使用するのも好きです。これは、新しいテストを作成するとき、または古いテストを変更するときに役立ちます。私は通常、古いロギング出力をデバッグレベルのままにし、そのメソッドのコードでまだ積極的に作業している間に、新しいロギングステートメントを情報レベルで作成します。私のJUnitクラスの1つは次のようになります。

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で使用される他のライブラリからのいくつかの有用なものが得られます。自分の好みに合わせて調整してください。

最後に、JUnitテストを実行するときに、次のすべてのライブラリがクラスパスにあることを確認する必要があります。

  • slf4j-api-1.6.0.jar
  • slf4j-log4j12-1.6.0.jar
  • log4j-1.2.16.jar
  • log4j.xml(上記の私の構成ファイル)
  • JUnitランタイムJARの一部のバージョン
  • アプリケーションを本番環境で実行するときに通常存在するすべてのJAR

これは、log4jを使用するときに私が行うことです。別のロギング実装を使用する場合は、それに応じて調整してください。 「API」と実装JARが同じバージョンである限り、異なるバージョンのslf4jを使用しているかどうかは関係ありません(私のものは両方とも1.6.0です)。

11
Jim Tough

なぜユニットテストにログを記録したいのですか?単体テストは合格/不合格であり、テストフレームワークを使用してそれを示す必要があります。テストが成功したか失敗したかを確認するために出力を読み通したくはありません。失敗した場合は、IDE /デバッガーで実行するのが最善の方法です。

14
dty

もう1つの解決策は、ログの実装をテスト専用の単純な実装に切り替えることです。

だからあなたの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に記録するだけで、構成ファイルは必要ありません。

5
Ed Griffin

出力ロガーとして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レベルを超えないようにし、ほとんどのものをデバッグすることをお勧めします。本当に多くのエラーをインテリジェントにトラップしたい場合は、ログファイルアペンダーであるPositronLoggerを調べることをお勧めします。これは、TRACEまでのすべてをサイレントに取得しますが、エラーをキャプチャした場合にのみファイルにダンプします。タイムトラベルのようなものです:)

http://github.com/andreaja/PositronLogger

2
BjornS

Xmlファイルを設定する必要はなく、System.out.printlnを使用したくありませんでした。ほとんどの場合、これは単体テストに必要でした。

テストロガーを設定できます。

<!-- 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>

ロガーを作成する前に、このプロパティを設定します:(ref: http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html TRACE以外で利用可能な他のプロパティ)

static {
    System.setProperty("org.slf4j.simpleLogger.defaultLogLevel","TRACE");
}

ロガーを作成します。

private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);


private void doSomeLogs(){
    LOGGER.trace("trace it"); 
}
0
user1917821

基になるslf4j実装としてlog4j 1を使用する場合

log4jは、次の場合を除いて、デフォルトでは何もログに記録しません。

  • log4j.propertiesクラスパス上のファイル
  • セットする -Dlog4j.configuration=file:///path/to/log4j.properties。 Mavenを使用している場合、これはmaven-surefire-plugin構成で実行できます。
  • たとえば@BeforeClassメソッドでlog4j構成をプログラムでセットアップします

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

    これは問題なく機能しますが、すべてユニットテストを実行する必要があります。これは面倒です。したがって、何かをすばやく機能させるために一時的に必要な場合を除いて、お勧めしません。

0
Ed Griffin

新しいテストの作成中にロギングを追加すると便利です。同時に、テストがCIまたはCDパイプラインで実行されている場合は、ロギングを無効にする(または少なくとも冗長性を低くする)必要があります。特にエンドツーエンドの実行では、障害が一時的なものである場合があるため、CIジョブのコンソールログに関連する出力があると便利です。この記事はそれを非常によく説明しています- https://gualtierotesta.wordpress.com/2015/11/01/tutorial-logging-during-tests/

0
MrHari