How to determine if an Android application works in UI testing with Espresso

I am writing several espresso tests for Android. I run the following problem:

For a specific test case to work correctly, I need to disable some functions in the application. So in my application, I need to determine if I am running the Espresso test to disable it. However, I do not want to use BuildConfig.DEBUG because I do not want these features to be disabled in the debug assembly. In addition, I would like to avoid creating a new buildConfig in order to avoid too many build options that need to be created (we already have many options).

I was looking for a way to define buildConfigField for testing, but I did not find any links to Google.

+17
android android-espresso ui-testing
Feb 16 '15 at 21:08
source share
8 answers

Combined with CommonsWare's answer. Here is my solution:

I defined the AtomicBoolean variable and the function to check if it works:

 private AtomicBoolean isRunningTest; public synchronized boolean isRunningTest () { if (null == isRunningTest) { boolean istest; try { Class.forName ("myApp.package.name.test.class.name"); istest = true; } catch (ClassNotFoundException e) { istest = false; } isRunningTest = new AtomicBoolean (istest); } return isRunningTest.get (); } 

This avoids the try-catch check every time you need to check the value, and it runs the check only the first time this function is called.

+30
Feb 24 '15 at 17:03
source share
— -

Combining Commonsware comment + Comtaler solution is here to do it for any test class using the Espresso environment.

 public static synchronized boolean isRunningTest () { if (null == isRunningTest) { boolean istest; try { Class.forName ("android.support.test.espresso.Espresso"); istest = true; } catch (ClassNotFoundException e) { istest = false; } isRunningTest = new AtomicBoolean (istest); } return isRunningTest.get(); } 
+24
Oct 28 '15 at 21:38
source share

Based on the answers above the following Kotlin code, this is equivalent:

 val isRunningTest : Boolean by lazy { try { Class.forName("android.support.test.espresso.Espresso") true } catch (e: ClassNotFoundException) { false } } 

Then you can check the value of the property:

 if (isRunningTest) { // Espresso only code } 
+12
Oct 24 '16 at 2:09
source share

What about the flag in the BuildConfig class?

 android { defaultConfig { // No automatic import :( buildConfigField "java.util.concurrent.atomic.AtomicBoolean", "IS_TESTING", "new java.util.concurrent.atomic.AtomicBoolean(false)" } } 

Add this somewhere in your test classes.

 static { BuildConfig.IS_TESTING.set(true); } 
+5
Jan 09 '19 at 7:45
source share

I prefer not to use reflection, which runs slowly on android. Most of us have a dagger2 configured for an injection of addiction. I have a test component configured for testing. Below is a brief way to get the application mode (testing or normal):

create enumeration:

 public enum ApplicationMode { NORMAL,TESTING; } 

and regular AppModule:

 @Module public class AppModule { @Provides public ApplicationMode provideApplicationMode(){ return ApplicationMode.NORMAL; } } 

create a test runner like me:

 public class PomeloTestRunner extends AndroidJUnitRunner { @Override public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return super.newApplication(cl, MyTestApplication.class.getName(), context); } } 

Remember to declare it in gradle as follows:

 defaultConfig { testInstrumentationRunner "com.mobile.pomelo.base.PomeloTestRunner" } 

Now create a subclass of AppModule with an override method that will look exactly the same and not mark it as a module above the class definition:

 public class TestAppModule extends AppModule{ public TestAppModule(Application application) { super(application); } @Override public ApplicationMode provideApplicationMode(){ return ApplicationMode.TESTING; //notice we are testing here } } 

now in your MyTestApplication class that you declared in your custom test runner, the following is declared:

 public class PomeloTestApplication extends PomeloApplication { @Singleton @Component(modules = {AppModule.class}) public interface TestAppComponent extends AppComponent { } @Override protected AppComponent initDagger(Application application) { return DaggerPomeloTestApplication_TestAppComponent.builder() .appModule(new TestAppModule(application)) //notice we pass in our Test appModule here that we subclassed which has a ApplicationMode set to testing .build(); } } 

Now, to use it, just enter it in production code wherever possible:

 @Inject ApplicationMode appMode; 

therefore, when your test tests of espresso will check the enumeration, but when in the production code it will be a normal enumeration.

ps is not needed, but if you need to see how my production dagger builds a graph in this way and is declared in a subclass of the application:

  protected AppComponent initDagger(Application application) { return DaggerAppComponent.builder() .appModule(new AppModule(application)) .build(); } 
+3
Nov 14 '17 at 12:33
source share

I will create two files, for example below

src / main /.../ Injection.java

SIC / androidTest /.../ Injection.java

And in Injection.java I will use a different implementation, or just a static variable int it.

Since androidTest is the source, not part of the build type, I think what you want to do is complicated.

+2
Feb 27 '18 at 6:00
source share

You can use SharedPreferences for this.

Set debug mode:

 boolean isDebug = true; SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPref.edit(); editor.putInt("DEBUG_MODE", isDebug); editor.commit(); 

Check debugging mode:

 SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); boolean isDebug = sharedPref.getBoolean("DEBUG_MODE", false); if(isDebug){ //Activate debug features }else{ //Disable debug features } 
+1
Feb 16 '15 at 21:20
source share

If you are using JitPack with kotlin. You need to change the name of the Espresso package.

 val isRunningTest : Boolean by lazy { try { Class.forName("androidx.test.espresso.Espresso") true } catch (e: ClassNotFoundException) { false } } 

For check

 if (isRunningTest) { // Espresso only code } 
0
Jul 02 '19 at 5:59
source share



All Articles