私はAndroid用のいくつかのEspressoテストを書いています。私は次の問題で実行しています:
特定のテストケースを正しく実行するには、アプリの一部の機能を無効にする必要があります。したがって、私のアプリでは、Espressoテストを実行しているかどうかを検出して、無効にできるようにする必要があります。ただし、デバッグビルドでこれらの機能を無効にしたくないので、BuildConfig.DEBUG
を使用したくありません。また、作成するビルドバリアントが多すぎるのを避けるために、新しいbuildConfigを作成することは避けたいと思います(すでに多くのフレーバーが定義されています)。
テスト用にbuildConfigFieldを定義する方法を探していましたが、Googleで参照が見つかりませんでした。
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チェックを実行する必要がなくなり、この関数を最初に呼び出したときにのみチェックが実行されます。
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();
}
上記の回答に基づいて、次の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"
}
次に、このように正確に見えるオーバーライドメソッドを使用して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;
したがって、実行中のエスプレッソテストでは列挙型をテストしますが、本番コードでは通常の列挙型になります。
psは必要ありませんが、私のプロダクションダガーがどのようにグラフを作成し、アプリケーションサブクラスで宣言するかを確認する必要がある場合:
protected AppComponent initDagger(Application application) {
return DaggerAppComponent.builder()
.appModule(new AppModule(application))
.build();
}
以下のような2つのファイルを作成します
src/main /.../Injection.Java
src/androidTest /.../Injection.Java
そして、Injection.Javaでは、別の実装を使用するか、静的変数を使用します。
AndroidTestはビルドタイプの一部ではなくソースセットであるため、やりたいことは難しいと思います。
KotlinでJitPackを使用している場合。 Espresso'sパッケージ名を変更する必要があります。
val isRunningTest : Boolean by lazy {
try {
Class.forName("androidx.test.espresso.Espresso")
true
} catch (e: ClassNotFoundException) {
false
}
}
確認用
if (isRunningTest) {
// Espresso only code
}
これにはSharedPreferencesを使用できます。
デバッグモードを設定します。
boolean isDebug = true;
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("DEBUG_MODE", isDebug);
editor.commit();
デバッグモードかどうかを確認します。
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
boolean isDebug = sharedPref.getBoolean("DEBUG_MODE", false);
if(isDebug){
//Activate debug features
}else{
//Disable debug features
}