How to determine if Android Application is started with JUnit testing instrumentation?-ThrowExceptions

Exception or error:

I need to determine in runtime from code if the application is run under TestInstrumentation.

I could initialize the test environment with some env/system variable, but Eclipse ADK launch configuration would not allow me to do that.

Default Android system properties and environment do not to have any data about it. Moreover, they are identically same, whether the application is started regularly or under test.

This one could be a solution: Is it possible to find out if an Android application runs as part of an instrumentation test but since I do not test activities, all proposed methods there won’t work. The ActivityManager.isRunningInTestHarness() method uses this under the hood:

SystemProperties.getBoolean("ro.test_harness") 

which always returns false in my case. (To work with the hidden android.os.SystemProperties class I use reflection).

What else can I do to try to determine from inside the application if it’s under test?

How to solve:

I have found one hacky solution: out of the application one can try to load a class from the testing package. The appication classloader surprisingly can load classes by name from the testing project if it was run under test. In other case the class is not found.

private static boolean isTestMode() {
  boolean result;
  try {
    application.getClassLoader().loadClass("foo.bar.test.SomeTest");
    // alternatively (see the comment below):
    // Class.forName("foo.bar.test.SomeTest");
    result = true;
  } catch (final Exception e) {
result = false;
  }
  return result;
}

I admit this is not elegant but it works. Will be grateful for the proper solution.

###

The isTestMode() solution did not work for me on Android Studio 1.2.1.1. Almighty Krzysztof from our company tweaked your method by using:

Class.forName("foo.bar.test.SomeTest");

instead of getClassLoader(). Thanks for Krzysztof!

###

We created a solution to pass parameters to the MainActivity and use it inside the onCreate method, enabling you to define how the Activity will be created.

In MainActivity class, we created some constants, which could also be an enum. We created a static attribute too.

public class MainActivity {
    public static final int APPLICATION_MODE = 5;
    public static final int UNIT_TEST_MODE = 10;
    public static final int OTHER_MODE = 15;

    public static int activityMode = APPLICATION_MODE;
    (...)

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        switch (activityMode) {
            case OTHER_MODE:
                (...)
                break;

            case UNIT_TEST_MODE:
                Log.d(TAG, "Is in Test Mode!");
                break;

            case APPLICATION_MODE:
                (...)
                break;
        }
        (...)
    }
    (...)
}

We made MainActivityTest class abstract, created a setApplicationMode and called this method inside the setUp() method, before calling the super.setUp() method.

public abstract class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

    protected void setUp() throws Exception {
        setApplicationMode();  // <=====
        super.setUp();
        getActivity();
        (...)
    }

    (...)
    public void setApplicationMode() {
        MainActivity.activityMode = MainActivity.UNIT_TEST_MODE;
    }
}

All other test classes inherit from MainActivityTest, if we want it to have another behaviour, we can simply override the setApplicationMode method.

public class OtherMainActivityTest extends MainActivityTest {
    (...)
    @Override
    public void setApplicationMode() {
        MainActivity.activityMode = MainActivity.OTHER_MODE;
    }
}

The user nathan-almeida is the friend that is co-author of this solution.

Leave a Reply

Your email address will not be published. Required fields are marked *