Wie man die Protokollierung der Arbeit in scala unit tests mit testng, slf4s, und logback
Ich bin neu in der Scala, und nicht, dass vertraut mit den aktuellen Entwicklungen in Java, also bin ich mit, was ich davon ausgehen, ist ein Grundsätzliches problem.
Ich Schreibe einige Scala-code und testen mit test-Geräte mit ScalaTest und TestNG. Den code unter test verwendet slf4s zur Erfüllung seiner Anmeldung, unterstützt von logback.
In meiner " zu bauen.sbt' - Datei habe ich die Abhängigkeiten für alle Bibliotheken, die ich brauche:
scalaVersion := "2.9.1"
//Add test dependencies on scalatest and testng
libraryDependencies ++= Seq("org.scalatest" %% "scalatest" % "1.6.1" % "test", "org.testng" % "testng" % "6.1.1" % "test")
//Use the slf4j logging facade for logging
libraryDependencies += "org.slf4j" % "slf4j-api" % "1.6.3"
//use the slf4j connectors to implement the JCL logging facade in terms of slf4j (which in turn is implemented in terms of logback)
//confused yet?
libraryDependencies += "org.slf4j" % "jcl-over-slf4j" % "1.6.3"
//use logback for the back-end slf4j logging impl.
libraryDependencies ++= Seq("ch.qos.logback" % "logback-core" % "0.9.30", "ch.qos.logback" % "logback-classic" % "0.9.30")
//use slf4s to expose the slf4j logging facade in scala
libraryDependencies += "com.weiglewilczek.slf4s" %% "slf4s" % "1.0.7"
//Add the dispatch HTTP client dependency
libraryDependencies ++= Seq(
"net.databinder" %% "dispatch-http" % "0.8.5"
)
//I can't figure out how to use the dispatch HTTP client library, so just use the apache one
libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.1.2"
Führe ich die Protokollierung wie folgt aus (code vereinfacht zur besseren Lesbarkeit):
class MyClass extends Logging {
def doSomething() {
logger.debug("Hello world")
}
}
wenn ich einen test durchführen, übungen mit diesem code (mit dem 'sbt-test" - Befehl) sehe ich nicht die debug-Meldung, aber ich sehe diese auf der Konsole ausgegeben:
SLF4J: The following loggers will not work because they were created
SLF4J: during the default configuration phase of the underlying logging system.
SLF4J: See also http://www.slf4j.org/codes.html#substituteLogger
SLF4J: MyClass
Habe ich eine logback.xml Datei src/test/resources, und ich weiß, dass die Protokollierung selbst funktioniert so wie ich das sehe Ausgabe, die vom Apache-HttpClient-Bibliothek verwendet JCL).
Bin ich etwas fehlt? Die Informationen, die ich bin Anmeldung ist hilfreich in der Auseinandersetzung mit dem Verhalten von meinem code mit tests, und außerdem scheint es, wie das funktionieren sollte. Ich habe natürlich gelesen, die Seite an http://www.slf4j.org/codes.html#substituteLogger aber ich sehe nicht, wie mein logger wird immer erstellt, bevor das logging-subsystem konfiguriert wurde.
UPDATE: Hier ist der Inhalt meiner logback.xml:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %line --- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
InformationsquelleAutor der Frage anelson | 2011-10-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, es ist, weil SBT führt die tests parallel und Initialisierungscode in Slf4j ist nicht thread-sicher (!).
Sehen http://jira.qos.ch/browse/SLF4J-167 ... es ist berichtet worden, vor mehr als 2 Jahren!
Als workaround kann ich initialisieren, Slf4j durch das laden der root-logger, bevor die tests ausgeführt werden. Zu tun, fügen Sie einfach diese an Ihren SBT-Einstellungen:
InformationsquelleAutor der Antwort Bruno Bieth
slf4s 1.0.7 hängt davon ab, slf4j 1.6.1 wie Sie sehen können [hier][1]. Versuchen Sie, diese version zu verwenden, anstatt 1.6.3 für Ihre anderen slf4j Abhängigkeiten.
InformationsquelleAutor der Antwort Heiko Seeberger
Ich hatte das gleiche Problem. Landete genau Instanziierung eines leeren logger in der definition der Klasse.
Wenn ich meine Methode, um Ihren code, dann wäre es,
Beachten Sie, dass ich bin sehr neu in scala so, ich weiß nicht, die volle Bedeutung von dem, was ich gerade gemacht haben.
InformationsquelleAutor der Antwort casey
Das problem ist, dass, während der erste thread initialisiert die zugrunde liegenden logging-Implementierung (Blockierung) ist für alle anderen gleichzeitigen threads, SubstituteLoggerFactory erstellt. Dieser Ersatz-logger-Fabrik gibt eine SubstituteLogger stattdessen wird die eigentliche logger-Implementierung. Dieses Problem wird nicht gelöst in SLF4J-167.
Ist es weniger wahrscheinlich, um dieses Problem in Java, da oft logger-Objekte werden erstellt, wie eine statische variable, so dass die LoggerFactory wird initialisiert, während das laden von Klassen. In Scala gibt es keine statischen modifier und Begleiter-Objekte sind initialisiert träge.
Außerdem, die meisten testing-frameworks in Scala ausführen von tests parallel.
Um dieses Problem zu umgehen, ändern Sie die test-Umgebung: als Bruno Bieth vorgeschlagen, können Sie eine Initialisierung des LoggerFactory, bevor die tests beginnen. Sie können tun, dass auch in den test-code, anstatt die build-Einstellungen. Sie können auch festlegen, dass die Tests nacheinander ausgeführt werden, aber dann verlieren Sie die Geschwindigkeit.
Alternativ können Sie sehnsüchtig initialisieren Logger initialisiert in einem companion-Objekt. Hässlich, aber in den meisten Fällen sichergestellt, dass Foo-Objekte gleichzeitig erstellt werden, werden nicht initialisiert, mit einem SubstituteLogger.
InformationsquelleAutor der Antwort Ohad Bruker