概述
title: android-Androidd单元测试-Espresso
categories: Android
tags: [android, espresso, 单元测试]
date: 2020-02-23 00:36:26
comments: false
android-Androidd单元测试-Espresso
前篇
- 官方
- Espresso 设置说明 - https://developer.android.com/training/testing/espresso/setup?hl=zh-cn
- 将用户转到其他应用 (有发邮件示例) - https://developer.android.com/training/basics/intents/sending
- Espresso 备忘单 (各种模拟操作) - https://developer.android.com/training/testing/espresso/cheat-sheet?hl=zh-cn
- AndroidX Test 的 JUnit4 规则 - https://developer.android.com/training/testing/junit-rules?hl=zh-cn
- 示例 - https://github.com/android/testing-samples
测试时间稍长, 只要是需要 build gradle 文件.
单元测试分两种,
- [Context 测试](#简单的 Context 测试) : 获取某个 activity 进行简单的测试, 不能测试有线程等待的操作, 不能测试 ui 相关操作.
- [Espresso 使用](#Espresso 使用) : 可以测试有线程等待的操作, 可以测试 ui 相关操作.
TODO:
- 跳转 activity, 不自动退出 app
- 输入 慢于其他操作
Context 测试
-
在 build.gradle 中加入
dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:core:1.1.1' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:rules:1.2.0' androidTestImplementation 'androidx.test.ext:junit:1.1.1' }
-
添加测试用例
@RunWith(AndroidJUnit4ClassRunner.class) public class ExampleInstrumentedTest { private final String TAG = "--- aut"; private Context mCtx = null; @Before public void initContext() { mCtx = getInstrumentation().getTargetContext(); } @Test public void test_getFile() { final String tempFile = "hello.txt"; try { Tools.writeFile(mCtx, tempFile, "wolegequ"); } catch (IOException e) { e.printStackTrace(); } File fa = Tools.getFile(mCtx, tempFile); Log.d(TAG, String.format("test_getFile: " + fa.exists())); } }
-
run 一下这个用例.
Espresso 使用
-
在 build.gradle 中加入
dependencies { androidTestImplementation 'androidx.test:core:1.1.1' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:rules:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.ext:junit:1.1.1' }
-
添加测试用例
@RunWith(AndroidJUnit4.class) @LargeTest public class EspressoTest { private static final String TAG = "--- EspressoTest"; @Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class); @Test public void Test_hello() { MainActivity mainActy = mActivityRule.getActivity(); EditText etName = mainActy.findViewById(R.id.editText); // 模拟 输入 onView(withId(R.id.editText)).perform(typeText("yangx world"), ViewActions.closeSoftKeyboard()); Log.d(TAG, "etName:" + etName.getText()); } }
-
run 一下这个用例. (输入测试框架自动输入)
获取 Activity 的两种方式
-
ActivityTestRule
@Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class); @Test public void Test_hello() { MainActivity mainActy = mActivityRule.getActivity(); } }
-
ActivityScenario
private MainActivity mActivity = null; @Before public void launchActivity() { ActivityScenario<MainActivity> actSro = ActivityScenario.launch(MainActivity.class); actSro.onActivity((activity) -> { mActivity = activity; }); } @Test public void Test_hello() { MainActivity mainActy = mActivity; }
挂起 Activity
单元测试都不是在 ui 线程执行, 所以 Thread.sleep 并不会阻塞 ui 线程, 只是阻塞了测试线程.
每次测试完用例, app 都会退到 后台. 可以使用测试线程睡眠的 骚操作, 阻止单元测试结束 进而防止 app 退到后台, 此时 ui 是可以操作的
@After
public void suspending() {
try {
Thread.sleep(3000 * 100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
模拟 按键点击
onView(isRoot()).perform(pressKey(KeyEvent.KEYCODE_BACK)); // 模拟 点击 返回键
UI 显示必须在 UI 线程
测试线程不能进行 ui 操作, ui 必须跑在 ui 线程中.
@Test
public void Test_tips() {
mActivity.runOnUiThread(() -> {
Tools.Tips01(mActivity, "", null);
});
}
备忘单
- Espresso 备忘单 (各种模拟操作) - https://developer.android.com/training/testing/espresso/cheat-sheet?hl=zh-cn
踩坑
androidjunit4 deprecated 废弃问题
参考: https://stackoverflow.com/questions/52776716/androidjunit4-class-is-deprecated-how-to-use-androidx-test-ext-junit-runners-an
- The gradle file should contain the following line:
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
- Change test class to
AndroidJUnit4ClassRunner
fromAndroidJUnit4
还有就是 instrumentationregistry.gettargetcontext() deprecated
问题
参考: https://mlog.club/article/3900739
报错: application installation failed
可以尝试一下几种方式
- 这有可能是模拟器(手机)上原来安装过同名app但是签名等不一样,在手机上删除该app即可。
- 点击Build->Clean Project,然后再次Build->Rebuild Project即可。
- 点击File->Setting->Build,Execution,Deployment->Instant Run,将
enable instant run...
的勾去掉。 - 开启模拟器 调试选项 中的 usb 调试 和 usb 安装
模拟键盘输入不正确
比如 EditText 控件输入 yangx world
onView(withId(R.id.editText)).perform(typeText("yangx world"), ViewActions.closeSoftKeyboard());
etName.getText());
获取到的值不对, 且显示上看到也错的.
解决办法: 参考: https://stackoverflow.com/questions/20436968/espresso-typetext-not-working
Looks like I figured out the issue. It had to do with hardware vs software keyboard.
-
For Emulators:
Go to Settings -> Language & Input -> switch the Default Input to Sample Soft Keyboard.
逍遥模拟器改成
-
For Phones:
Install a software keyboard from the Play store and switch to it. It appears that the native keyboards of some phones do not work.
最后
以上就是故意大碗为你收集整理的android-Androidd单元测试-Espresso的全部内容,希望文章能够帮你解决android-Androidd单元测试-Espresso所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复