0

私のテスト自動化プロジェクトで、ロギングに問題があります。FileAppender で log4j2 ロガーを使用しています。私がそれを使用している方法は次のとおりです。

Logger logger = (Logger) LogManager.getLogger(loggerName);
Appender appender = FileAppender.newBuilder()
            .withAppend(false)
            .withBufferedIo(true)
            .withFileName(DIR_NAME + File.separator + loggerName + ".log")
            .withIgnoreExceptions(false)
            .withImmediateFlush(true)
            .withLocking(false)
            .withLayout(PatternLayout.newBuilder().withPattern("%d{HH:mm:ss.SSS}  [%-5level] %msg%n").withCharset(Charset.forName("UTF-8")).build())
            .withName(loggerName)
            .build();

    appender.start();
    logger.addAppender(appender);

単一のテストを実行しているときに機能します。すべてのデータがコンソールに表示され、ファイルが作成され、テスト ログがファイルに書き込まれます。テストが並行して実行されている場合、つまり異なるスレッドで問題が発生します。

この場合、2 つの異なるロガーとファイル アペンダーが作成されます。両方のファイル アペンダからのログ ファイルも作成され、両方のテストからのログがコンソールに表示されます。すべて問題ないように見えますが、これらのログ ファイルのいずれかが空になるたびに発生します。空のログは、後で開始されたテストに属します。

キャッシュに問題があると思われます。最初のファイルアペンダーは書き込み用のすべてのキャッシュを保持するため、2 番目のファイルアペンダーは書き込みできません。私は正しいですか?これに対する解決策は何ですか?

ありがとうございました。

4

1 に答える 1

0

プログラムによる構成を使用せずに、目的を達成できるはずです。log4j2 をプログラムで構成しない理由はたくさんありますが、私の意見では、そうすると、パブリック API の一部ではないlog4j2 の側面にコードが依存するようになるというのが最善の理由です。これは、log4j2 の実装が変更された場合、コードも変更する必要があることを意味します。これにより、長期的にはより多くの仕事が生まれます。

そのため、XML 構成ファイルを使用して log4j2 をセットアップし、テストごとに個別のログを生成する方法のデモを提供します。あなたの質問では指定されていないので、あなたの目標はTest注釈付きの各メソッドのログを作成することであり、これらの各メソッドは並行して実行されると想定しています。

まず、ここに私の TestNG クラスがあります:

package testpkg;

import java.lang.reflect.Method;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class NewTest {
    private static final Logger log = LogManager.getLogger();

    @BeforeMethod
    public void setThreadName(Method method){
        ThreadContext.put("threadName", method.getName());
    }

    @Test
    public void test1() {
        log.info("This is the first test!");
        log.warn("Something may be wrong, better take a look.");
    }

    @Test
    public void test2() {
        log.info("Here's the second test!");
        log.error("There's a problem, better fix it");
    }
}

ここでわかるように、2 つのTestメソッドとBeforeMethod呼び出されsetThreadNameた . setThreadNameメソッドは、明らかに、各メソッドの前に実行されますTest。実行しようとしているメソッドの名前を使用して、名前付きのキーthreadNameを log4j2 に配置ThreadContextします。これは、log4j2 構成ファイルのログ ファイル名の一部として使用されます。

log4j2.xml ファイルは次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Routing name="MyRoutingAppender">
            <Routes pattern="$${ctx:threadName}">
                <Route>
                    <File
                        fileName="logs/${ctx:threadName}.log"
                        name="appender-${ctx:threadName}"
                        append="false">
                        <PatternLayout>
                            <Pattern>[%date{ISO8601}][%-5level][%t] %m%n</Pattern>
                        </PatternLayout>
                    </File>
                </Route>
            </Routes>
        </Routing>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="[%date{ISO8601}][%-5level][%t] %m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="testpkg" level="TRACE" additivity="false">
            <AppenderRef ref="STDOUT" />
            <AppenderRef ref="MyRoutingAppender" />
        </Logger>
        <Root level="WARN">
            <AppenderRef ref="STDOUT" />
        </Root>
    </Loggers>
</Configuration>

ご覧のとおり、キーにRoutingAppender基づいて実行時にアペンダーを動的に生成するためにを使用するように構成ファイルを設定しました。これは の属性でも使用されます。ThreadContextthreadNamethreadNamefileNameFileAppender

これが私のtestNG設定ファイルです:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="My suite" parallel="methods" thread-count="5" verbose="1">
  <test name="testpkg" >
    <classes>
       <class name="testpkg.NewTest" />
    </classes>
  </test>
</suite>

ここでわかるようTestに、クラス内の各メソッドが並行して実行されるように設定しました。

これを実行すると、次のコンソール出力が得られます。

[RemoteTestNG] detected TestNG version 6.14.3
[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-2] Here's the second test!
[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-1] This is the first test!
[2018-05-04T21:54:54,709][WARN ][TestNG-test=testpkg-1] Something may be wrong, better take a look.
[2018-05-04T21:54:54,709][ERROR][TestNG-test=testpkg-2] There's a problem, better fix it

===============================================
My suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

2 つのメソッドの出力がインターリーブされていることがはっきりとわかるので、メソッドが実際に並行して実行されていることがわかります。

テスト クラスを実行すると、予想どおり 2 つのログ ファイルも作成されます。それらは、test1.log および test2.log という名前です。

それらの内容は次のとおりです。

test1.log:

[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-1] This is the first test!
[2018-05-04T21:54:54,709][WARN ][TestNG-test=testpkg-1] Something may be wrong, better take a look.

test2.log:

[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-2] Here's the second test!
[2018-05-04T21:54:54,709][ERROR][TestNG-test=testpkg-2] There's a problem, better fix it

ここで、予想どおり、最初の方法のログは test1.log に、2 番目の方法のログは test2.log に移動したことがわかります。

楽しみ!

于 2018-05-05T03:06:04.427 に答える