IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Test - Espresso 延迟匹配的实现 -> 正文阅读

[移动开发]Android Test - Espresso 延迟匹配的实现

Espresso 会检测主线程何时处于空闲状态,以便可以在适当的时间运行测试命令,从而提高测试的可靠性。

先上示例代码:来自官网

    @Test
    fun greeterSaysHello() {
        onView(withId(R.id.name_field)).perform(typeText("Steve"))
        onView(withId(R.id.greet_button)).perform(click())
        onView(withText("Hello Steve!")).check(matches(isDisplayed()))
    }
    

很简单的代码。
场景:如果按钮?greet_button?的点击事件触发后,“Hello Steve!” 文本将在访问接口后才会显示,这个时间是不确定性的,所以给它添加?Thread.sleep()?也就不可行了。

空闲资源:

Espresso的空闲资源表示结果会影响界面测试中后续操作的异步操作。通过向 Espresso 注册空闲资源,您可以在测试应用时更可靠地验证这些异步操作。

?? 这里我们虽然可以使用Espresso空闲资源来处理(使用 IdlingRegistry 类),但是 应用的生产代码中存在空闲资源逻辑,这是不推荐的。

处理方案:

根据如下匹配方法:?ViewAssertions.matches()?

/**
   * Returns a generic {@link ViewAssertion} that asserts that a view exists in the view hierarchy
   * and is matched by the given view matcher.
   */
  public static ViewAssertion matches(final Matcher<? super View> viewMatcher) {
    return new MatchesViewAssertion(checkNotNull(viewMatcher));
  }

重写 MatchesViewAssertion() :

/**
 * 如果需要等待视图匹配,在等待期间抛出此错误
 * @property message
 */
class WaitingNotMatchViewException(override val message: String) : RuntimeException()


// 简便易使用
fun waitMatches(viewMatcher: Matcher<View>): ViewAssertion {
    return WaitMatchesViewAssertion(checkNotNull(viewMatcher))
}


@VisibleForTesting
class WaitMatchesViewAssertion(private val viewMatcher: Matcher<View>) : ViewAssertion {

    private val TAG = WaitMatchesViewAssertion::class.java.simpleName

    override fun check(view: View?, noViewException: NoMatchingViewException?) {
        val description = StringDescription()
        description.appendText("'")
        viewMatcher.describeTo(description)
        if (noViewException != null) {
            description.appendText(
                String.format(
                    Locale.ROOT,
                    "' check could not be performed because view '%s' was not found.\n",
                    noViewException.viewMatcherDescription
                )
            )
            Log.e(TAG, description.toString())
            throw noViewException
        } else {
            // 添加 try-catch
            try {
                description.appendText("' doesn't match the selected view.")
                ViewMatchers.assertThat(description.toString(), view, viewMatcher)
            }catch (e: AssertionFailedError){
                // 抛出异常 WaitingNotMatchViewException
                throw WaitingNotMatchViewException("doesn't match the selected view.")
            }
        }
    }

    override fun toString(): String {
        return String.format(Locale.ROOT, "MatchesViewAssertion{viewMatcher=%s}", viewMatcher)
    }
}

封装:

/**
 * 页面上只有一个视图与表达式匹配的情况。
 * 等待匹配元素直到超时。如果找不到匹配的元素,这不会抛出异常,它只是等待。
 *
 * @param elementToCheck 要检查的元素
 * @param viewMatcher 匹配项
 * @param secondsToWait 等待的最大秒数
 */
fun waitForElementWithMatcher(
    elementToCheck: ViewInteraction, // 要检查的元素
    viewMatcher: Matcher<View>, // 匹配项
    secondsToWait: Int = 30  // 超时时间
) {
    var i = 0
    var elementMatched = false
    while (i <= secondsToWait) {
        if (IntegrationUtil.waitElementToViewMatcher(elementToCheck, viewMatcher)) {
            elementMatched = true
            break
        }
        Thread.sleep(1000)  // 这里的时间可以自己设定
        i++
    }
    if (!elementMatched) {
        throw Exception("Expected to find the element on Screen .Waited for $i seconds")
    }
}


/**
 * 检查元素匹配项。
 * 在您知道屏幕上只有一个匹配元素的情况下使用它  
 *
 * @param elementToCheck 要检查的元素
 * @param viewMatcher  元素匹配项
 * @return returns 如果元素匹配,则返回 true
 */
fun waitElementToViewMatcher(
    elementToCheck: ViewInteraction,
    viewMatcher: Matcher<View>
): Boolean {
    try {
        val elementList = mutableListOf(elementToCheck.check(waitMatches(viewMatcher)))
        if (elementList.count() == 1)
            return true
    } catch (e: NoMatchingViewException) {
        return false
    } catch (e: WaitingNotMatchViewException) {
        return false
    } catch (e: Exception) {
        throw Exception(e.message)
    }
    return false
}


使用:

    @Test
    fun greeterSaysHello() {
        onView(withId(R.id.name_field)).perform(typeText("Steve"))
        onView(withId(R.id.greet_button)).perform(click())
        // onView(withText("Hello Steve!")).check(matches(isDisplayed()))
        waitForElementWithMatcher(onView(withText("Hello Steve!")), isDisplayed(), 30)
    }
    

最后,欢迎讨论。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:33:51  更:2022-05-12 16:34:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:21:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码