Com*_*ler 21 android ui-testing android-espresso
我正在为Android编写一些Espresso测试.我正在运行以下问题:
为了使某个测试用例正常运行,我需要在应用程序中禁用某些功能.因此,在我的应用程序中,我需要检测我是否正在运行Espresso测试,以便我可以禁用它.但是,我不想使用BuildConfig.DEBUG,因为我不希望在调试版本中禁用这些功能.此外,我想避免创建一个新的buildConfig,以避免创建太多的构建变体(我们已经定义了很多风格).
我一直在寻找一种方法来定义buildConfigField以进行测试,但我在Google上找不到任何引用.
Com*_*ler 30
结合CommonsWare的答案.这是我的解决方案:
我定义了一个AtomicBoolean变量和一个函数来检查它是否正在运行测试:
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 ();
}
这样可以避免每次需要检查值时执行try-catch检查,并且只在第一次调用此函数时才运行检查.
Rya*_*yan 28
结合Commonsware评论+ Comtaler的解决方案,这是使用Espresso框架为任何测试类做到这一点的方法.
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();
    }
小智 13
基于上面的答案,以下Kotlin代码是等效的:
val isRunningTest : Boolean by lazy {
    try {
        Class.forName("android.support.test.espresso.Espresso")
        true
    } catch (e: ClassNotFoundException) {
        false
    }
}
然后,您可以检查属性的值:
if (isRunningTest) {
  // Espresso only code
}
BuildConfig课堂上的旗帜怎么样?
android {
    defaultConfig {
        // No automatic import :(
        buildConfigField "java.util.concurrent.atomic.AtomicBoolean", "IS_TESTING", "new java.util.concurrent.atomic.AtomicBoolean(false)"
    }
}
将此添加到测试类中的某个位置。
static {
    BuildConfig.IS_TESTING.set(true);
}
我不想使用在 android 上运行缓慢的反射。我们大多数人都为依赖注入设置了 dagger2。我有一个用于测试的测试组件。以下是获取应用程序模式(测试或正常)的简要方法:
创建一个枚举:
public enum ApplicationMode {
    NORMAL,TESTING;
}
和一个普通的 AppModule:
@Module
public class AppModule {
    @Provides
    public ApplicationMode provideApplicationMode(){
        return ApplicationMode.NORMAL;
    }
}
创建一个像我这样的测试运行器:
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);
    }
}
不要忘记像这样在gradle中声明它:
defaultConfig {
testInstrumentationRunner "com.mobile.pomelo.base.PomeloTestRunner"
}
现在使用 override 方法创建 AppModule 的子类,该方法看起来完全像这样,并且不要将其标记为类定义上方的模块:
public class TestAppModule extends AppModule{
    public TestAppModule(Application application) {
        super(application);
    }
    @Override
    public ApplicationMode provideApplicationMode(){
        return ApplicationMode.TESTING; //notice we are testing here
    }
}
现在,在您在自定义测试运行程序中声明的 MyTestApplication 类中,声明了以下内容:
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();
    }
}
现在要使用它,只需将它注入到生产代码中,就像这样:
@Inject
    ApplicationMode appMode;
因此,当您运行 espresso 测试时,它将测试枚举,但在生产代码中它将是正常枚举。
ps 不是必需的,但如果您需要查看我的生产匕首如何构建图形并在应用程序子类中声明:
 protected AppComponent initDagger(Application application) {
        return DaggerAppComponent.builder()
                .appModule(new AppModule(application))
                .build();
    }
如果您将JitPack与 kotlin 一起使用。您需要更改Espresso 的包名称。
val isRunningTest : Boolean by lazy {
    try {
        Class.forName("androidx.test.espresso.Espresso")
        true
    } catch (e: ClassNotFoundException) {
        false
    }
}
用于检查
if (isRunningTest) {
  // Espresso only code
}
| 归档时间: | 
 | 
| 查看次数: | 8277 次 | 
| 最近记录: |