2015-02-16 21 views
10

Android için bazı Espresso testleri yazıyorum. Şu sorunla karşılaşıyorum: Belirli bir sınama durumunun düzgün çalışması için, uygulamadaki bazı özellikleri devre dışı bırakmam gerekir. Bu nedenle, uygulamamda, Espresso testini çalıştırıp çalıştırmadığımı tespit etmem gerekiyor, böylece onu devre dışı bırakabiliyorum. Ancak, bu özelliklerin bir hata ayıklama yapısında devre dışı bırakılmasını istemediğim için BuildConfig.DEBUG kullanmak istemiyorum. Ayrıca, oluşturulacak çok fazla yapı varyantından kaçınmak için yeni bir buildConfig oluşturmaktan kaçınmak isterim (zaten tanımlanmış birçok tat var).Android uygulamasının Espresso ile UI testi çalıştırıp çalıştırmadığını belirleme

Test için buildConfigField'ı tanımlamanın bir yolunu arıyordum, ancak Google'da herhangi bir başvuru bulamadım.

+4

Test kodunuzun VM'de olup olmadığını görmek için bir hacky çözümü 'Class.forName()' dır: http://wtanaka.com/node/8041 – CommonsWare

+0

Bu sorunu çözdünüz mü? – Marcus

+0

Evet. – Comtaler

cevap

23

:

boolean isDebug = true; 

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

Kontrol ayıklama modunda ise.

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(); 
} 

Bu değerini kontrol etmek gerekmez, yalnızca her zaman try-catch kontrol gerçekleştiriyor önler:

Ben testi çalıştıran olmasından bağımsız olarak kontrol etmek için bir AtomicBoolean değişken ve bir fonksiyon tanımlanmış: İşte benim çözüm Bu işlevi ilk kez çağırdığınızda kontrolü çalıştırır.

+1

Çözümü göndereceğim AtomicBoolean sınıfı yerine yalnızca bir Boolean (boolean değil) nesnesi kullanmaktan ne haber? – Paul

3

Bunun için SharedPreferences'ı kullanabilirsiniz.

Seti ayıklama modu: CommonsWare cevabı ile birlikte

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); 
boolean isDebug = sharedPref.getBoolean("DEBUG_MODE", false); 

if(isDebug){ 
    //Activate debug features 
}else{ 
    //Disable debug features 
} 
19

Commonsware comment + Comtaler's çözümünü birleştirmek, Espresso çerçevesini kullanan herhangi bir test sınıfı için bunu yapmanın bir yoludur. Daha sonra özelliğinin değerini kontrol edebilirsiniz

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

: Aşağıdaki Kotlin kodunun üzerinde yanıtlara

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(); 
    } 
7

Bina eşdeğerdir

if (isRunningTest) { 
    // Espresso only code 
} 
0

i yansıma kullanmamayı tercih hangi android üzerinde yavaş. Çoğumuz bağımlılık enjeksiyonu için ayarlanmış hançer2 var. Test için kurulmuş bir test bileşenim var.

@Module 
public class AppModule { 

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

benim gibi bir test koşucu oluşturun:

public enum ApplicationMode { 
    NORMAL,TESTING; 
} 

ve normal AppModule:

bir enum oluşturmak: Burada uygulama modunu alabilirsiniz kısa yolu (test ya da normal) 'dir :

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); 
    } 
} 

böyle gradle içinde beyan etmek unutma:

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

böyle tam olarak görünüyor geçersiz kılma yöntemi ile AppModule bir alt sınıfını oluşturabilir ve sınıf tanımı üzerinde bir modül olarak işaretlemek etmeyin: MyTestApplication sınıfında şimdi

public class TestAppModule extends AppModule{ 

    public TestAppModule(Application application) { 
     super(application); 
    } 

    @Override 
    public ApplicationMode provideApplicationMode(){ 
     return ApplicationMode.TESTING; //notice we are testing here 
    } 
} 

sen bildirilen özel test atlet ilan aşağıdakiler var:

Şimdi
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(); 
    } 
} 

sadece kullanmak yerde böyle üretim kodunda enjekte etmek:

@Inject 
    ApplicationMode appMode; 

çalışan espresso testleriniz enum testini yaparken, üretim kodunda normal enum olacak.

ps gerekli değildir ama sen benim üretim hançer onun böyle grafiği oluşturur ve uygulama alt sınıfta beyan nasıl gerekiyorsa: Ben gibi iki dosya oluşturacağız

protected AppComponent initDagger(Application application) { 
     return DaggerAppComponent.builder() 
       .appModule(new AppModule(application)) 
       .build(); 
    } 
0

altına

src/ana /.../ Injection.java

src/androidTest /.../ Injection.java

Ve Injection.java'da farklı bir uygulama ya da sadece statik bir değişken kullanacağım.

AndroidTest kaynak kümesi olduğu için, yapı türünün bir parçası değil, yapmak istediğiniz şeyin zor olduğunu düşünüyorum.

İlgili konular