Where is log output written to when using Robolectric + Roboguice?
Asked Answered
E

6

53

I'm using Robolectric to test Android. I'm running my tests via maven, e.g.

mvn -Dtest=LogTest test

If I have code that writes to the logs, such as

Log.d("TAG", "blah");

or using Roboguice's Ln

Ln.d("blah");

I don't see any output in maven's surefire logs (text files).

Ideally, I actually want simple log statements to go to the console. I can write to the console by using System.out.println("blah"), but of course I'd rather use the supported logging APIs.

So my question is, why am I not seeing log output at all, and how can I get the log messages written to the console?

Extravasate answered 19/4, 2012 at 0:11 Comment(4)
Does it work with info / error?Cabala
This is an old question, but I do want to ask Tyler to accept an answer. When you accept answers to your questions, people are more willing to answer your questions.Valladares
@Valladares I agree Christine. However, I no longer have the ability to check if answers posted here work. At the time, none of the answers helped me. I upvoted scompt.com's answer, but then realized it didn't solve the issue for me, as I noted in the comments. Is there a policy/guide for what I should all this time later?Extravasate
Jesus Monzon Legido's solution works fine, I use that. Also, it's the simplest solution given.Valladares
M
80

I am running robolectric-2.0-alpha-3.

What worked for me was to set in the setUp method of my test the stream to stdout

Something like:

@Before
public void setUp() throws Exception {
  ShadowLog.stream = System.out;
  //you other setup here
}

With this version of robolectric I had no success doing the same (ShadowLog.stream = System.out) in a custom TestRunner or in my TestLifeycleApplication.

Setting the system property System.setProperty("robolectric.logging","stdout"); was of no effect as well, but it might works in previous versions.

Mantling answered 4/5, 2013 at 16:9 Comment(3)
Great! I call this in a static method annotated with @BeforeClass to run this only once per test file.Dasya
Works on robolectric 3.0 as well.Pupiparous
Works on roboletric 4.5.1Neoptolemus
F
15

Im using robolectric 2.3. How works for me:

Into my @Before:

ShadowLog.stream = System.out;

Inside my test functions i can use (ShadowLog. have other options):

ShadowLog.v("tag", "message");

And inside my tested class I can put some messages at log with:

System.out.println("message");
Flynt answered 10/10, 2014 at 13:20 Comment(3)
I've tried it, but I see nothing. Where is the output written? Btw.: I use Robolectric 2.4, but I think logging will work in the same way.Heterotaxis
U can see the result in the logcat. Verify if u put the ShadowLog.stream = System.out; into ur setup.Flynt
Why not just use System.out? Why the necessity for ShadowLog.Uball
N
13

By default, logging output when using the RobolectricTestRunner disappears. You can configure where it goes by looking at the setupLogging() method of that class.

To summarize, you need to set the robolectric.logging system property to either stdout, stderr, or a file path where the log should be written. I do this in the constructor of a subclass of RobolectricTestRunner that I use for all tests so that logs always get written to stdout.

Neves answered 20/4, 2012 at 9:8 Comment(5)
It worked! Thanks! Good links too. Now... did you read about that somewhere, or did you just dig through the source? Also, are you familiar with Roboguice? I was wanting to use their "Ln" logging, but if I do, it doesn't get printed out to stdout, although it's strange because it seems like its default implementation is via android.util.Log, which should work because I can use Log directly. Thoughts?Extravasate
I only found it by slogging through the code. I don't think it's documented anywhere. As for Ln, make sure your app is debuggable, otherwise Ln automatically disables debug and verbose logging.Neves
Rats. Sorry to be dense. I realize this did not actually solve my problem. The code you pointed out makes sense, but it doesn't actually work. I thought it was working, but it was leftover code I had used to make it work, from: groups.google.com/group/robolectric/browse_thread/thread/…Extravasate
Does setupLogging() still exist? pivotal.github.io/robolectric/javadoc/com/xtremelabs/…Chimpanzee
Yes, it's still in RobolectricTestRunner, but the package has been changed.Neves
C
5

Add the following to your test setup before your test runs:

ShadowLog.stream = System.out;
Robolectric.bindShadowClass(ShadowLog.class);

https://groups.google.com/forum/?fromgroups=#!msg/robolectric/PK-9cQQQROw/svuQzM5h_vsJ

Chimpanzee answered 12/4, 2013 at 5:40 Comment(3)
I just test this with robolectric 2.x+. Robolectric.bindShadowClass(ShadowLog.class); is not longer needed.Scintillation
Yup. This works. As @Scintillation says, the second line isn't needed - robolectric 2.2.Ithaca
I get an error **Cannot resolve method 'bindShadowClass'Uball
B
2

When running tests with maven all you need is something like this :

                 <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.17</version>
                    <configuration>
                        <systemPropertyVariables>
                          <robolectric.logging>stdout</robolectric.logging>
                        </systemPropertyVariables>
                    </configuration>
                 </plugin>

When running the tests locally, e.g. in intellij, then all you need is an environmental variable: Just go (for intellij) to Run/Debug Configurations --> Defaults -->Junit --> VM options and add

-Drobolectric.logging=stdout
Buttonhook answered 11/12, 2014 at 0:18 Comment(0)
P
0

The solution that worked out best for me (or at all) was to initialize a replacement injected implementation (during testing only) of RoboGuice's Ln.Print class to do System.out printing instead of Android's Log printing, given I was actually using Robolectric to avoid having to depend on the Android subsystem to run my tests in the first place.

From Ln.java:

public class Ln  {
...

/**
 * print is initially set to Print(), then replaced by guice during
 * static injection pass.  This allows overriding where the log message is delivered to.
 */
@Inject protected static Print print = new Print();

So basically:

public class TestModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(Ln.Print.class).to(TestLogPrint.class);
    }

}

and:

public class TestLogPrint extends Print {

    public int println(int priority, String msg ) {

        System.out.println(
            String.format(
                "%s%s", 
                getScope(4), 
                msg
            )
        );

        return 0;
    }

    protected static String getScope(int skipDepth) {
        final StackTraceElement trace = Thread.currentThread().getStackTrace()[skipDepth];
        return String.format("%s | %s.%s | ", new Date(), trace.getFileName().replace(".java", ""), trace.getMethodName());
    }
}

That of course assuming the standard Robolectric init to hook the module up with RoboGuice:

@Before
public void setUp() throws Exception {

    Module roboGuiceModule = RoboGuice.newDefaultRoboModule(Robolectric.application);
    Module productionModule = Modules.override(roboGuiceModule).with(new CustomRoboModule());
    Module testModule = Modules.override(productionModule).with(new TestModule());

    RoboGuice.setBaseApplicationInjector(Robolectric.application, RoboGuice.DEFAULT_STAGE, testModule);
    RoboGuice.injectMembers(Robolectric.application, this);

}
Polonaise answered 21/1, 2013 at 19:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.