28

By default all Logger output, visible when an application is running, is mute when the application is tested.

How to force the debugs, infos etc. to be shown in the specs2 reports?

Rajish
  • 6,755
  • 4
  • 34
  • 51

5 Answers5

22

First off, you may like some background why logging is disabled in test mode. This was Guillame Bort's answer to a question in the play forum (see this thread):

The logger is disabled in test mode for now because it was causing an huge PermGen space leak when running tests. But we are working to run tests in a forked JVM so we will enable it again soon.

As a workaround, I created my own logger like this (Scala code):

import play.api.{Play, LoggerLike, Logger}
import org.slf4j.LoggerFactory
import org.slf4j.impl.SimpleLoggerFactory

object MyLogger extends LoggerLike {

  val factory = if (Play.isTest(Play.current)) {
    new SimpleLoggerFactory()
  } else {
    LoggerFactory.getILoggerFactory
  }

  val redirectDebugToInfo = factory.isInstanceOf[SimpleLoggerFactory]

  val logger = factory.getLogger("application")

  def apply(name: String): Logger = new Logger(factory.getLogger(name))

  def apply[T](clazz: Class[T]): Logger = new Logger(factory.getLogger(clazz.getCanonicalName))

  // this method is to make debug statements to show up in test mode
  override def debug(m: => String) = {
    if (redirectDebugToInfo) {
      info(m)
    } else {
      super.debug(m)
    }
  }
}

I don't know how this code behaves regarding the PermGen leak in general, but so far I didn't have that problem. To make it work you need to add this dependency:

"org.slf4j" % "slf4j-simple" % "1.6.4"
rintcius
  • 3,283
  • 2
  • 19
  • 16
  • How do you cope with the `SLF4J: Class path contains multiple SLF4J bindings.` warning? – Rajish Jul 25 '12 at 22:50
  • @Rajish I don't deal with it, since it's just a temporary workaround. For me the warning didn't give any issues. Does it give any issues to you? – rintcius Aug 20 '12 at 15:43
  • @rintcius Thanks for the workaround! I'm using java and as far as I know I can just mix scala code. I added this as a scala file to my java project but it doesn't seem to work. Looking at your code I should be able to log as usual Logger.debug("debug") thoughts? I did add the dependencies as well. – Hua-Ying Sep 15 '12 at 13:27
  • 1
    @Hua-Ying I don't think it would work in Java because MyLogger uses the Scala API (e.g. the debug method takes => String as a parameter as opposed to String in Java). You could try translating it to Java and talking to Play's Java API instead (ie. no play.api imports) – rintcius Sep 15 '12 at 15:59
  • 1
    I created a Java class to use MyLoggerS.scala (renamed from MyLogger.scala). https://gist.github.com/4062948 – angelokh Nov 13 '12 at 00:07
  • As of Play 2.3, there appears to be no `org.slf4j.impl.SimpleLoggerFactory` available, so this does not work. – Tony Day Aug 07 '14 at 12:30
  • @TonyDay did you add the slf4j-simple dependency (see last line of my answer)? – rintcius Aug 09 '14 at 10:12
  • @rintcius No I didn't, and now I feel silly. Will give it a go! Sorry about that :-) – Tony Day Aug 09 '14 at 22:02
9

If you're using FakeApplication, you can pass some configuration info:

  FakeApplication(additionalConfiguration = Map(
    "logger.application" -> "DEBUG"
  ))

That limits LOGGER output to debug and higher output.

I was surprised to observe that the setting is "sticky". If an early test uses FakeApplication, a later test that does not use FakeApplication will still use the same logging level.

giampaolo
  • 6,906
  • 5
  • 45
  • 73
bwbecker
  • 1,031
  • 9
  • 21
6

I created a logger.xml file under conf such as this:

<configuration>
    <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder><pattern>%coloredLevel %logger{15} - %message%n%xException{5}</pattern></encoder>
    </appender>

    <logger name="play" level="ERROR" />
    <logger name="application" level="INFO" />

    <root level="ERROR">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Then I start my play environment with the following command:

play -Dlogger.file=conf/logger.xml

Voila! Logging data in test. It does lead to memory leaks, but is invaluable during development.

John Kelvie
  • 858
  • 1
  • 7
  • 16
5

If you're using sbt to run tests (which play does by default), you can set javaOptions in the Test task to control the logging configuration used.

Eg, in project/Build.scala:

javaOptions in Test      += "-Dlogger.file=conf/test-logger.xml"

More about the syntax of the test-logger.xml file here:

http://logback.qos.ch/manual/configuration.html

jazmit
  • 5,170
  • 1
  • 29
  • 36
  • 2
    This no longer appears to work from 2.3.2. Using the code above will not compile in a default project. Managed to get `testOptions in Test += Tests.Argument("-Dlogger.file=conf/test-logger.xml")` to configure logging, but no logging comes out of unit tests at all. – Tony Day Aug 07 '14 at 12:01
  • I edited the answer to remove play.Project which is removed in 2.3.x, but the remaining still works - we are currently using it in our project. What do you have in your test-logger.xml? – jazmit Aug 10 '14 at 17:11
  • This works now that you have removed the `play.Project`. thanks for the update @jamesinchina – Tony Day Aug 11 '14 at 10:10
  • Works and I am on SBT 1.5.3 so it will be `Test / javaOptions += "-Dlogger.file=conf/test-logger.xml"` – Manabu Tokunaga Jul 11 '21 at 13:33
3

If you look at Play Logger source, you will see that logging is disabled in Test mode.

If you really want logging, you can create logging configuration file for testing and pass it to Play as system property "logger.file".

Example logging configuration (test-logger.xml file in project root):

<configuration>
  <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
  <logger name="application" level="INFO">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
        <pattern>%coloredLevel %logger{15} - %message%n%xException{5}</pattern>
      </encoder>
    </appender>
  </logger>
</configuration>

Running tests:

JAVA_OPTS="-Dlogger.file=test-logger.xml" play test
Luka Zakrajšek
  • 1,079
  • 12
  • 12