Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log messages in android studio junit test

Tags:

Is there a way to print out Logcat (Log.i, Log.d) messages when running a JUnit (method) test in Android Studio?

I can see System.out.print message but no logcat printouts.

In the runconfiguration (GUI window of Android Studio) there are logcat options for tests under Android tests but not for JUnit tests.

Is this possible somehow? Thanks for any hints!

like image 817
daniel Avatar asked Feb 22 '16 19:02

daniel


People also ask

Should you test log messages?

Logging statements isn't to be overlooked. It's code, real code, that is meant for humans at a later time. The better that is, and if it has a test around it, the faster I can find it and the code associated with it. Maybe even fix it quickly and safely.

What is a log message in Android?

The tag of a system log message is a short string indicating the system component from which the message originates (for example, ActivityManager ). A user-defined tag can be any string that you find helpful, such as the name of the current class (the recommended tag).

How do you log test unit?

ALL: in unit tests you can change the log level of the logger, to verify that when a certain log level is set, certain messages will no longer be logged. For example, if the log level were to be set to WARN, then the FruitLogger should no longer log the message body.

How do you write JUnit test cases for Android?

You write your local unit test class as a JUnit 4 test class. To do so, create a class that contains one or more test methods, usually in module-name/src/test/ . A test method begins with the @Test annotation and contains the code to exercise and verify a single aspect of the component that you want to test.


1 Answers

Logcat output will not be seen in unit tests because Logcat is Android feature - JUnit tests can use only standard Java, therefore Android features won't work.

What you can do in unit tests is inject "test doubles" into tested components. But Log.x calls are static, so you can't override them (without resolving to e.g. PowerMock, which you should avoid at all costs).

Therefore, the first step will be to introduce a non-static class that will behave as a proxy for Log.x calls:

/**  * This class is a non-static logger  */ public class Logger {      public void e(String tag, String message) {         Log.e(tag, message);     }      public void w(String tag, String message) {         Log.w(tag, message);     }      public void v(String tag, String message) {         Log.v(tag, message);     }      public void d(String tag, String message) {         Log.d(tag, message);     } } 

Use this class in every place you have Log.x calls now.

Second step would be to write a test-double implementation of Logger that redirects to standard output:

public class UnitTestLogger extends Logger{      @Override     public void e(String tag, String message) {         System.out.println("E " + tag + ": " + message);     }      // similar for other methods } 

The last step is to inject UnitTestLogger instead of Logger in unit tests:

@RunWith(MockitoJUnitRunner.class) public class SomeClassTest {      private Logger mLogger = new UnitTestLogger();      private SomeClass SUT;      @Before     public void setup() throws Exception {         SUT = new SomeClass(/* other dependencies here */ mLogger);     }  } 

If you want to be rigorously strict about OOP concepts, you can extract common interface for Logger and UnitTestLogger.

That said, I never encountered a need to investigate Log.x calls in unit tests. I suspect that you don't need it either. You can run unit tests in debug mode and step over the code line-by-line in debugger, which is much faster than attempting to investigate logcat output...

General advice:

If the code you are testing contains Log.x static calls and your unit tests do not crash - you have a problem.

I'd guess that either all tests are being run with Robolectric, or you have this statement in build.gradle: unitTests.returnDefaultValues = true.

If you run all the tests with Robolectric, then it is just unefficient, but if all Android calls return default values, then you test suite is not reliable. I suggest you fix this issue before proceeding any further because it will bite you in the future one way or another.

like image 81
Vasiliy Avatar answered Sep 28 '22 10:09

Vasiliy