问题描述
我最近开始使用 Android Studio 3.1.2 和 SDK 19 (Android 4.4) 编写我真正的第一个 Android 项目.
I recently started coding my really first android project using Android Studio 3.1.2 and SDK 19 (Android 4.4).
当我遇到测试时,我想自动化我的 UI 测试,我计划用 Appium 的 Java 客户端编写(服务器将在外部设置).为了获得包含所有驱动程序的 java-Client,我在 build.gradle(app)
中添加了一个依赖项:
When I came across testing I want to automate my UI-tests, which I plan to write with the java client of Appium (the server will be set up externally). In order to get the java-Client including all the drivers I added a dependency into the build.gradle(app)
:
implementation 'io.appium:java-client:6.1.0'
添加依赖项后同步 Gradle 不会导致任何可识别的问题.现在,如果我尝试运行我的一个(非 UI)测试,我会在构建过程中得到一个 DexArchiveBuilderException
,抛出一堵文本墙,以某种方式暗示, 的几个资源io.appium:java-client:6.1.0
需要来自较新 Android SDK 的 API:
Synching Gradle after adding the dependency didn't cause any recognizable problems. Now if I try to run one of my (non-UI) tests, I get a DexArchiveBuilderException
already during the build process, throwing a wall of text, that somehow hints, that several resources of io.appium:java-client:6.1.0
require APIs from newer Android SDKs:
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): java.lang.Object org.openqa.selenium.firefox.XpiDriverService$ThrowingSupplier.get()","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Invoke-customs are only supported starting with Android O (--min-api 26)","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Invoke-customs are only supported starting with Android O (--min-api 26)","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Invoke-customs are only supported starting with Android O (--min-api 26)","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): org.springframework.core.env.Environment org.springframework.context.ConfigurableApplicationContext.getEnvironment()","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): java.util.concurrent.ScheduledFuture org.springframework.scheduling.TaskScheduler.schedule(java.lang.Runnable, java.time.Instant)","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): void org.springframework.context.ApplicationEventPublisher.publishEvent(org.springframework.context.ApplicationEvent)","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): boolean org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor.requiresDestruction(java.lang.Object)","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): boolean org.springframework.beans.factory.FactoryBean.isSingleton()","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"error","text":"Default interface methods are only supported starting with Android N (--min-api 24): boolean org.springframework.beans.factory.SmartFactoryBean.isEagerInit()","sources":[{}],"tool":"D8"}
在实际异常之下:
com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process /Users/ini/.gradle/caches/modules-2/files-2.1/org.seleniumhq.selenium/selenium-firefox-driver/3.12.0/b44da882625fdc1e8e99035b3d1bb488d17802e6/selenium-firefox-driver-3.12.0.jar
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:146)
at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.transform(DexArchiveBuilderTransform.java:308)
at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:221)
at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:217)
at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:212)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:46)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:60)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:626)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:581)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:745)
我几乎没有测试自动化方面的经验,所以官方的 Appium 文档并没有真正向我解释,是否可以让客户端在 SDK 19 上运行,如果是这种情况,如何做到这一点.你们中有人知道如何做到这一点吗?还是我只是鲁莽,在集成过程中忘记了必要的步骤?感谢转发.
I hardly have any experience in test automation, so the official Appium documentation doesn't really explain to me, if it's possible to make the client run on SDK 19 and if this is the case, how to do that. Does anyone of you guys know how to do this? Or am I just foolhardy and forgot a required step during the integration? Thanks in forward.
推荐答案
如果您想使用 Appium Java 客户端实现自动化,最好将其测试项目与 Android 项目分开,并在 Appium 测试中使用您构建的应用 APK.
If you want to automate with Appium Java client, it's best to keep it's test project separate from the Android project and use your built app APK in the Appium test.
如果您想将测试与 Android 项目保持在一起,最好使用 Espresso,因为它是 Android SDK 的一部分.
If you want to keep your test together with the Android project, it's best to use Espresso as it's a part of the Android SDK.
这篇关于在Android Studio项目中实现Appium Java客户端太笨了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!