Как определить, работает ли приложение Android в UI-тестировании с помощью Espresso
Я пишу несколько тестов эспрессо для Android. Я запускаю следующую проблему:
Для правильной работы определенного тестового примера мне нужно отключить некоторые функции в приложении. Поэтому в моем приложении мне нужно определить, выполняю ли я тест Espresso, чтобы отключить его. Тем не менее, я не хочу использовать BuildConfig.DEBUG
, потому что я не хочу, чтобы эти функции были отключены в сборке отладки. Кроме того, я хотел бы избежать создания нового buildConfig, чтобы избежать слишком большого количества вариантов сборки, которые нужно создать (у нас уже есть много вариантов).
Я искал способ определить buildConfigField для тестирования, но я не нашел ссылок на Google.
Ответы
Ответ 1
В сочетании с ответом 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 каждый раз, когда вам нужно проверить значение, и он запускает проверку только при первом вызове этой функции.
Ответ 2
Объединение Commonsware comment + 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();
}
Ответ 3
Основываясь на ответах выше следующего кода Котлина, это эквивалентно:
val isRunningTest : Boolean by lazy {
try {
Class.forName("android.support.test.espresso.Espresso")
true
} catch (e: ClassNotFoundException) {
false
}
}
Затем вы можете проверить значение свойства:
if (isRunningTest) {
// Espresso only code
}
Ответ 4
Как насчет флага в классе 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);
}
Ответ 5
Я предпочитаю не использовать отражение, которое медленно работает на android. У большинства из нас есть кинжал2, настроенный для инъекции зависимости. У меня есть тестовый компонент, настроенный для тестирования. Ниже приведен краткий способ получения режима приложения (тестирование или нормальный):
создать перечисление:
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();
}
Ответ 6
Я создам два файла, например ниже
src/main/.../Injection.java
ЦСИ/androidTest/.../Injection.java
И в Injection.java я буду использовать другую реализацию, или просто статическую переменную int it.
Поскольку androidTest - это источник, а не часть типа сборки, я думаю, что вы хотите сделать, это сложно.
Ответ 7
Для этого вы можете использовать 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
}
Ответ 8
Если вы используете 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
}