web-dev-qa-db-ja.com

AndroidアプリがEspressoでUIテストを実行しているかどうかを検出する方法

私はAndroid用のいくつかのEspressoテストを書いています。私は次の問題で実行しています:

特定のテストケースを正しく実行するには、アプリの一部の機能を無効にする必要があります。したがって、私のアプリでは、Espressoテストを実行しているかどうかを検出して、無効にできるようにする必要があります。ただし、デバッグビルドでこれらの機能を無効にしたくないので、BuildConfig.DEBUGを使用したくありません。また、作成するビルドバリアントが多すぎるのを避けるために、新しいbuildConfigを作成することは避けたいと思います(すでに多くのフレーバーが定義されています)。

テスト用にbuildConfigFieldを定義する方法を探していましたが、Googleで参照が見つかりませんでした。

22
Comtaler

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チェックを実行する必要がなくなり、この関数を最初に呼び出したときにのみチェックが実行されます。

30
Comtaler

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

上記の回答に基づいて、次のKotlinコードを作成することは同等です。

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

次に、プロパティの値を確認できます。

if (isRunningTest) {
  // Espresso only code
}
15
David Pacheco

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

私は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();
    }
5
j2emanue

以下のような2つのファイルを作成します

src/main /.../Injection.Java

src/androidTest /.../Injection.Java

そして、Injection.Javaでは、別の実装を使用するか、静的変数を使用します。

AndroidTestはビルドタイプの一部ではなくソースセットであるため、やりたいことは難しいと思います。

2
Nevin Chen

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
}
1
hemantsb

これには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
}
1
Marcus