Comment obtenir la journalisation de travail en scala tests unitaires avec testng, slf4s, et logback
Je suis nouveau à la Scala, et pas très familiers avec les récents développements en Java, donc je vais avoir ce que je suppose est un problème de base.
Je suis en train d'écrire quelques Scala de code, et de le tester avec des appareils de test à l'aide de ScalaTest et TestNG. Le code de test utilise slf4s pour effectuer la journalisation, soutenu par logback.
Dans mon construire.sbt fichier j'ai des dépendances pour toutes les bibliothèques dont j'ai besoin:
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"
- Je effectuer la journalisation de cette façon (code simplifié pour des raisons de lisibilité):
class MyClass extends Logging {
def doSomething() {
logger.debug("Hello world")
}
}
quand je lance un test qui exerce ce code (à l'aide de la "sbt test de "commande") je ne vois pas le message de débogage, mais je vois cet imprimé sur la console:
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
J'ai un logback.xml fichier dans src/test/resources, et je sais de journalisation elle-même fonctionne comme je vois que la sortie de l'Apache HttpClient de la bibliothèque (qui utilise JCL).
Suis-je raté quelque chose? Les informations que je suis la journalisation est utile dans l'exploration du comportement de mon code avec des tests, et d'ailleurs il semble que cela devrait fonctionner. Bien sûr, j'ai lu la page à http://www.slf4j.org/codes.html#substituteLogger mais je ne vois pas comment mon enregistreur est arriver créé avant que le sous-système d'enregistrement a été configuré.
Mise à JOUR: Voici le contenu de mon 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>
- Pouvez-vous poster le contenu de votre logback.xml fichier?
- J'ai le même problème (logback de base+classique 0.9.30, 1.0.0; slf4j-api 1.6.2). Je pense que c'est indépendant de l'utilisation de slf4s. Et son exécution, chose. Dans certaines exécutions certaines classes ne obtenir configurés, en d'autres pistes, je vois une erreur pour eux.
Vous devez vous connecter pour publier un commentaire.
Je pense que c'est parce que SBT exécute les tests en parallèle et certaines de code d'initialisation dans Slf4j n'est pas thread-safe (!).
Voir http://jira.qos.ch/browse/SLF4J-167 ... il a été rapporté plus de 2 ans!
Comme une solution de contournement j'initialise Slf4j par le chargement de la racine de l'enregistreur avant l'exécution des tests. Pour le faire il suffit de l'ajouter à votre SBT paramètres:
slf4s 1.0.7 dépend de slf4j 1.6.1 comme vous pouvez le voir [ici][1]. Essayez d'utiliser cette version au lieu de 1.6.3 pour vos autres slf4j dépendances.
J'ai eu le même problème. Terminé juste de l'instanciation d'un vide enregistreur dans la définition de classe.
Si j'ai appliqué ma méthode de votre code, alors il serait,
Remarque que je suis très nouveau à la scala, donc je ne sais pas toutes les implications de ce que je viens de le faire.
Le problème est que, bien que le premier thread est en cours d'initialisation du sous-jacent de la journalisation de la mise en œuvre (de blocage), pour tous les autres threads simultanés, SubstituteLoggerFactory est créé. Ce substitut de l'enregistreur de l'usine renvoie une SubstituteLogger plutôt les enregistreur de mise en œuvre. Ce problème n'est pas résolu dans SLF4J-167.
Il est moins susceptible de répondre à cette question en Java, parce que souvent enregistreur objets sont créés comme une variable statique, de sorte que le LoggerFactory est en cours d'initialisation au cours de la classe de chargement. En Scala, il n'y a pas de modificateur static et compagnon objets sont initialisés paresseusement.
En outre, la plupart des infrastructures de test en Scala exécuter des tests en parallèle.
Pour contourner ce problème, vous pouvez modifier l'environnement de test: comme Bruno Bieth suggéré, vous pouvez initialiser le LoggerFactory avant que les tests de démarrage. Vous pouvez le faire aussi dans le code de test plutôt que les paramètres de construction. Vous pouvez également définir le test à exécuter séquentiellement, mais alors vous perdre de la vitesse.
Sinon, vous pouvez avec impatience initialiser un Enregistreur de initialisé dans un compagnon de l'objet. Laid, mais dans la plupart des cas, il assure que les Foo objets créés simultanément de ne pas être initialisée avec un SubstituteLogger.