作为新的 Android 应用程序的一部分,我们正在建立一个完整的持续集成(使用 Jenkins,但没关系)。
到目前为止,我们已经自动化了 JUnit 和 UI 测试,并且我们正在考虑在每次构建之后添加 Monkey 测试,作为额外的质量步骤。
然而,到目前为止,我们对 Monkey 的反馈相当负面。我们创建了一个全新的空 Android 应用程序(当您在 Android Studio 中创建一个空项目时的基本 Hello World 应用程序),即便如此,Monkey 测试也会经常崩溃(在模拟器上运行),因为这似乎与我们的应用程序。
我试过的命令:
adb shell monkey -v -v -s -2972043913753481246 -p my.app.package 50000
但它一路崩溃(大约步骤 6000)。
我认为这可能是由于模拟器被过度请求,所以我添加了一些限制让模拟器呼吸:
adb shell monkey -v -v -s -2972043913753481246 --throttle 150 -p my.app.package 50000
但是,它仍然崩溃(进一步,在步骤 8000 附近)。
我认为它可能需要更多的呼吸,所以我设置了 1 秒的节流以确保(即使是人类也可以更快地行动)
adb shell monkey -v -v -s -2972043913753481246 --throttle 1000 -p my.app.package 50000
而且,它仍然崩溃(大约 48 000 步)。
添加--ignore-native-crashes
并没有改变任何东西。
所以我的全部观点是:猴子真的有意义吗?它似乎不相关(如果 Android Studio 本身提供的一个空的 Hello World 应用程序是根本原因,那么我不想看到现实世界的应用程序会发生什么)。
有人找到一种方法让 Monkey 测试稳定且相关吗?您使用什么配置(事件数、限制、附加标志)?
我在 150 毫秒限制时遇到的崩溃之一:
// 崩溃:com.android.launcher (pid 1838) // 短消息:java.lang.IllegalArgumentException // 长消息:java.lang.IllegalArgumentException:宽度和高度必须 > 0 // 构建标签:generic_x86/sdk_google_phone_x86/ generic_x86:5.1/LKY45/1737576:eng/test-keys // Build Changelist: 1737576 // Build Time: 1423932217000 // java.lang.IllegalArgumentException: width and height must be > 0 // at android.graphics.Bitmap.createBitmap (Bitmap.java:810) // 在 android.graphics.Bitmap.createBitmap(Bitmap.java:789) // 在 android.graphics.Bitmap.createBitmap(Bitmap.java:756) // 在 com.android.launcher2。 Cling.dispatchDraw(Cling.java:201) // 在 android.view.View.updateDisplayListIfDirty(View.java:14162) // 在 android.view.View.getDisplayList(View.java:14189) // 在 android.view .ViewGroup。recreateChildDisplayList(ViewGroup.java:3389) // 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) // 在 android.view.View.updateDisplayListIfDirty(View.java:14127) // 在 android.view.View .buildLayer(View.java:13979) // 在 com.android.launcher2.AppsCustomizeTabHost.enableAndBuildHardwareLayer(AppsCustomizeTabHost.java:359) // 在 com.android.launcher2.AppsCustomizeTabHost.onLauncherTransitionStart(AppsCustomizeTabHost.java:403) // 在com.android.launcher2.Launcher.dispatchOnLauncherTransitionStart(Launcher.java:2538) // 在 com.android.launcher2.Launcher.hideAppsCustomizeHelper(Launcher.java:2852) // 在 com.android.launcher2.Launcher.showWorkspace(Launcher. java:2900) // 在 com.android.launcher2.Launcher.showWorkspace(Launcher.java:2893) // 在 com.android.launcher2.Launcher。startSearch(Launcher.java:1642) // 在 com.android.launcher2.Launcher.onSearchRequested(Launcher.java:1766) // 在 com.android.launcher2.Launcher.onKeyDown(Launcher.java:891) // 在 android .view.KeyEvent.dispatch(KeyEvent.java:2619) // 在 android.app.Activity.dispatchKeyEvent(Activity.java:2707) // 在 com.android.launcher2.Launcher.dispatchKeyEvent(Launcher.java:1973) / / at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2276) // at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4020) // at android.view. ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3982) // 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544) // 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597) // 在 android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563) // 在 android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3680) // 在 android.view.ViewRootImpl $InputStage.apply(ViewRootImpl.java:3571) // 在 android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3737) // 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544) / / at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597) // at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563) // at android.view.ViewRootImpl$InputStage.apply( ViewRootImpl.java:3571) // 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544) // 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597) // 在 android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563) // 在 android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3713) // 在 android.view.ViewRootImpl$ImeInputStage .onFinishedInputEvent(ViewRootImpl.java:3874) // 在 android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2208) // 在 android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1849) / / at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1840) // at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2185) // at android.view.InputEventSender.dispatchInputEventFinished( InputEventSender.java:141) // 在 android.os.MessageQueue.nativePollOnce(Native Method) // 在 android.os.MessageQueue.next(MessageQueue.java:143) // 在 android.os.Looper.loop(Looper.java:122) // 在 android.app.ActivityThread。 main(ActivityThread.java:5257) // 在 java.lang.reflect.Method.invoke(Native Method) // 在 java.lang.reflect.Method.invoke(Method.java:372) // 在 com.android。 internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) // 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) //android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) // 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) //android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) // 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) //
我担心在 1000 毫秒的节流中发生的崩溃是巨大的(数万行)发布在 SO 上的方式。