查看: 91668|回复: 63015
打印 上一主题 下一主题

Espresso浅析和使用

[复制链接]
龙盛娱乐
跳转到指定楼层
楼主
发表于 2019-04-19 10:08:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

韩非马上召集柳如叶和李大刚以及海子他们商议战斗部署,听得四个半师团外加一个鬼子坦克联队过来,韩非手下的这些猛将也感到咂舌:“他娘的小鬼子这次是要跟我们拼命来了啊?四个半师团,十多万鬼子,徐州附近几乎没有什么可以坚守的地方,大多都是一望无际的平地,挖壕沟抵御鬼子那就是找死!”

墨月城平台网址

曾帆黑色的瞳孔忽的一暗,现在他真恨不得将当年的实情告诉她,他根本一点都不喜欢夏艳,和夏艳在一起不过是为了给她和陈中华造成错觉,让陈中华对他少点防备。
雪飞鸿想过了,换成别人,甚至像幻影婆婆这样的超级强,都无法练出先天真气,都无法吸收玉石能量,所以,自己还真是世间独一无二的存在……

两名亲兵将他扶起,递给他干毛巾和姜茶,季广琛默默地用毛巾将脸上的雨水擦干了,却对姜茶摇了摇头,表示他不需要。

 

欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~


Espresso是一个Google官方提供的Android应用UI自动化测试框架。Google希望,当Android的开发者利用Espresso写完测试用例后,能一边看着测试用例自动执行,一边享受一杯香醇Espresso(浓咖啡)。
Espress有3个特点:

  • 第一个收录在Android Testing Supporting Library底下的测试框架
  • 模拟用户的操作
  • 自动等待,直到UI线程Idle,才会执行测试代码

接下来,将从配置、写用例、运行一步步介绍Espresso的使用。

0. 项目配置

0.1 修改App的build.gradle

  • 在defaultConfig内增加,testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner”,用来运行脚本
  • 增加packagingOptions,避免编译时候License的冲突
  • 在dependencies中增加相关的引用(androidTestCompile只有在编译测试用例时候才会运行,普通编译不会)
    下面是build.gradle中涉及到Espresso配置的内容
android {
    defaultConfig {
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
       }
    }
    packagingOptions {
        exclude "LICENSE.txt"
    }
}
dependencies {
    // Espresso 相关的引用
    compile "com.android.support:support-annotations:22.1.1"
    androidTestCompile "com.android.support:support-annotations:22.1.1"
    androidTestCompile("com.android.support.test.espresso:espresso-core:2.1"){
        exclude group: "javax.inject"
    }
    androidTestCompile "com.android.support.test.espresso:espresso-intents:2.1"
    androidTestCompile "com.android.support.test.espresso:espresso-contrib:2.1"
    androidTestCompile "com.android.support.test:runner:0.2"
}

0.2 添加TestRunner

点击顶栏菜单Run->Edit Configurations,出现如下的窗口后,点击左上角的”+”,选择”Android Tests”;

修改新Configuration的名字,选中App Module,输入Runner,选择”Show chooer dialog”,点击”OK”完成

1. 写测试用例

1.1 三步曲

写UI自动化测试用例,归结起来就是3步:

定位View控件
操作View控件
校验View控件的状态
对应Espresso,就是以下3个方法的调用:

onView(ViewMatcher)
  .perform(ViewAction)
  .check(ViewAssertion);

其中,onView是用来定位View控件的,perform是操作控件的,check是校验View控件的状态。他们各自都需要再传入对应的参数分别如下:

ViewMatcher,有withId、withText、withClassName等等方法来定位View控件
ViewAction,有click()、longClick()、pressBack()、swipeLeft()等等方法来操作View控件
ViewAssertion,有isEnabled()、isLeftOf()、isChecked()等等方法来校验View控件状态
这里有ViewMatcherViewActionViewAssertion的Cheat Sheet。

1.2 完整测试用例代码

这是一个非常简单的测试用例,通过R.id.button定位控件,对它调用了一下click,最后校验控件是不是enabled状态。这里面有一些注解,@Rule修饰的是被测试的Activity@Test修饰的方法是测试用例。

@RunWith(AndroidJUnit4.class)public class MainActivityTest {    @Rule
    public ActivityTestRule mActivityRule = new ActivityTestRule(MainActivity.class);    @Test
    public void testTextViewDisplay() {
        onView(withId(R.id.button))
            .perform(click())
            .check(matches(isEnabled()));
    }
}

1.3 注意

Getting Started With Espresso 2.0这个视频中提到了2个写测试用例时的注意项:

避免Activity的层级跳转,测试用例尽量只在单个Activity内完成。Activity层级跳转越多,越容易出错
强烈不推荐,直接获取View的对象,调用View的方法来模拟用户操作。应该统一使用Espresso提供的方法
测试用例,特别是UI自动化测试用例,应该尽量保持逻辑简单,覆盖关键路径就足矣。因为UI变动是很频繁的,越复杂,维护成本就越高,投入产出比就会自然降低了。

2. 运行用例

  1. 在运行菜单中选择步骤0.2中设置的TestRunner,点击执行
  2. 测试用例模拟用户操作自动运行
  3. 测试用例执行完成,在Android Studio的控制台上,能看到如下的结果输出

其中,看到”Done 3 of 3”标识,一共3个检查点,都检查通过了。如果有检查不通过的话,右上角的绿色能量条会变成红色。

3. 进阶

3.1 onData的使用

对于ListView,如果要操作其中的某一个item,特别是不可见状态的item,是不能通过上述的ViewMatch来定位的。我们都知道ListViewView是复用的,不可见状态的item并没有把内容绘制到View上。Espresso针对AdapterViewListView的父类),提供了onData来支持。

onData(ObjectMatcher)
  .DataOptions
  .perform(ViewAction)
  .check(ViewAssertion);

onData传入的是一个ObjectMather。首先假设ListView的Adapter中的Item的定义如下:

public static class Item {
    private final int value;
    public Item(int value) {
        this.value = value;
    }
    public String toString() {
        return String.valueOf(value);
    }
}

下面定义一个withValue()的方法,返回一个BoundedMatcher。而其中的matchesSafely()方法是用来判断match与否的,判断的逻辑实现都放在这里。



public static Matcher<Object> withValue(final int value) {
    return new BoundedMatcher<Object,
            MainActivity.Item>(MainActivity.Item.class) {
        @Override public void describeTo(Description description) {
            description.appendText("has value " + value);
        }
        @Override public boolean matchesSafely(
                MainActivity.Item item) {
            return item.toString().equals(String.valueOf(value));
        }
    };
}

有了上面的铺垫,测试用例写起来就水到渠成了。在id是R.id.listAdapterView中找到数据项是27,然后执行click()操作。

@Test
public void clickItem() {
    onData(withValue(27))
            .inAdapterView(withId(R.id.list))
            .perform(click());
    //Do the assertion here.
}

最后需要注意的是,onData()并不适用于RecyclerView,因为它不是继承自AdapterView。Espresso提供专门给RecyclerView使用的RecyclerViewActions

@Test 
public void clickItem() {
    onView(withId(R.id.recycler_view))
            .perform(
                    RecyclerViewActions.actionOnItemAtPosition(27, click()));
}

3.2 Idling Resource的使用

应用开发中很常见的一个场景是,点击某个按钮,发起网络请求,等请求回来后解析数据,更新界面。Espresso针对这种测试场景,提供了原生的支持。
假设被测Activity初始化后有一个耗时的数据加载过程,activity.isSyncFinished()方法判断数据加载是否已经完成。代码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //模拟耗时的数据加载
    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
        @Override
        public void run() {
            mIsSyncFinished = true;
        }
    }, 5000);
}

private volatile boolean mIsSyncFinished = false;
public boolean isSyncFinished() {
    return mIsSyncFinished;
}

这种情况,Espresso提供了IdlingResource来保证数据加载完成了才开始执行测试用例代码。首先,需实现IdlingResource接口:

  • getName()方法返回的String是作为注册回调的Key,所以要确保唯一性
  • registerIdleTransitionCallback()的参数ResourceCallback会用做isIdleNow()时候的回调
  • isIdleNow()是否已经处于空闲状态,这里调用activity.isSyncFinished()方法来判断数据加载是否完成
private static class MyIdlingResource implements IdlingResource {
    private ResourceCallback mCallback = null;
    private MainActivity mActivity;

    MyIdlingResource(MainActivity activity) {
        mActivity = activity;
    }

    @Override
    public String getName() {
        return "MyIdlingResource";
    }

    @Override
    public void registerIdleTransitionCallback(ResourceCallback callback) {
        mCallback = callback;
    }

    @Override
    public boolean isIdleNow() {
        boolean isIdle = mActivity != null && mActivity.isSyncFinished();
        if (isIdle && mCallback != null) {
            mCallback.onTransitionToIdle();
        }
        return isIdle;
    }
}

MyIdlingResource需要在恰当的时机注册和反注册。@Before@After是依照JUnit4的惯例,分别在用例执行之前和之后去注册和反注册。那么,如下测试用例执行的过程是:

  1. 测试用例启动,注册MyIdlingResource
  2. 启动被测Activity
  3. Activity初始化,启动数据加载过程
  4. Activity数据加载完成,执行测试用例方法testTextViewDisplay()
  5. 测试用例结束,反注册MyIdlingResource
    可见,IdlingResource能够保证流转到Idle状态,才会执行测试代码:
@Test
public void testTextViewDisplay() {
    onView(withText("Show SnackBar")).check(ViewAssertions.matches(isDisplayed()));
}

@Before
public void registerIntentServiceIdlingResource() {
    Activity activity = mActivityRule.getActivity();
    idlingResource = new MyIdlingResource((MainActivity) activity);
    Espresso.registerIdlingResources(idlingResource);
}

@After
public void unregisterIntentServiceIdlingResource() {
    Espresso.unregisterIdlingResources(idlingResource);
}

3.3. 执行原理

本文开头提到Espresso其中一个特点,无需主动写Sleep等待UI事件的执行和UI的绘制。原因是,Espresso的用例运行过程是只有当UI线程IDLE和UI队列没有需要执行的事件时,Espresso的测试代码才会被执行。使用方无需写Sleep逻辑等待UI绘制完成。以下是Espresso测试用例执行简易的流程图,帮助理解:

写在最后

引用官方介绍的一段话,Espresso的目标受众是开发者。希望更多的团队能够实现Google的期许最大化利用Espresso,把Bug扼杀在摇篮中。

Target Audience
Espresso is targeted at developers, who believe that automated testing is an integral part of the development lifecycle. While it can be used for black-box testing, Espresso’s full power is unlocked by those who are familiar with the codebase under test.

引用

Getting Started With Espresso 2.0:https://www.youtube.com/watch?v=TGU0B4qRlHY
Advanced Android Espresso:https://realm.io/news/chiu-ki-chan-advanced-android-espresso-testing/
Android Espresso 测试框架探究:http://blog.csdn.net/weijianfeng1990912/article/details/51540468
Android自动化测试-AdapterView的测试:https://segmentfault.com/a/1190000004392396
Android单元测试研究与实践:http://tech.meituan.com/Android_unit_test.html

文章来自: QQ音乐技术团队 公众号

相关阅读

网页加速特技之 AMP

表格行与列边框样式处理的原理分析及实战应用

「腾讯云游戏开发者技术沙龙」11月24 日深圳站报名开启 畅谈游戏加速

 

此文已由作者授权腾讯云技术社区发布,转载请注明原文出处

原文链接:https://cloud.tencent.com/community/article/520289?utm_source=bky

海量技术实践经验,尽在腾讯云社区!

编辑:马密宗安

发布时间:2019-04-19 15:37:48

当前文章://unokeji/201946602.html

美娱国际登陆 易博国际娱城诚信平台 u优乐88国际 w882018优德官网_w88体育直播_w88wlive网页版 澳门美高梅娱乐_澳门美高梅官网娱乐_澳门美高梅娱乐官方网 澳门美狮美高梅 齐乐娱乐国际城平台 千赢国际|官方网站app 

点击获取礼包
亚虎娱乐手机版
沙发
发表于 2019-04-19 02:34:19 | 只看该作者
“攻击。”比比东怒吼一声,她虽然带来了六名封号斗罗。但这六个人都没有领域,只有她自己才拥有领域的能力,强烈的紫光从她身上奔涌而出,想要以领域对领域。但是,比比东终究还是没能得逞。她所释放出的紫光被一股澎湃的生命气息所阻挡,硬是没能蔓延到大明和二明脚下。
回复 支持 反对

使用道具 举报

云顶娱乐网址 - 娱乐从这里开始
板凳
发表于 2019-04-19 04:10:52 | 只看该作者
王小民不闪不避,一脸微笑,就当拳头轰击到面门,不到一厘米的时候,王小民忽然出手,用一根手指就挡住了彼得的重拳。/unokeji/201957672.html
回复 支持 反对

使用道具 举报

千龙国际官网
地板
发表于 2019-04-19 04:22:50 | 只看该作者
而队伍中不时有骑马的衙役来维持秩序,排解宗族之间的纠纷,这时,一户恒州蒋氏宗族和一户赵州穆氏家族因年轻人的气盛而发生了争吵,互不相让,数百年轻人对峙着,怒目对视,手执长剑木棒,大有集体斗殴的架势,有衙役见势不妙,急忙去禀报两州的高官。
回复 支持 反对

使用道具 举报

玛雅的钱汇娱乐官网
5#
发表于 2019-04-19 09:26:13 | 只看该作者
孔欣馨没有把整首《南山南》听完,上菜的服务员,让她意识到自己不该打扰丁宁和顾兮的二人世界,藉要好好听听为由,经过丁宁允许后,她把《南山南》传到了自己的手机里,然后回到了包间。
回复 支持 反对

使用道具 举报

乐虎国际电子游戏e68
6#
发表于 2019-04-19 04:49:35 | 只看该作者
突然,唐川想起了一件事,他嘿嘿笑着说道:“叶叔,我能求你帮我一件事么?”
回复 支持 反对

使用道具 举报

奇幻变脸秀手机版下载
7#
发表于 2019-04-19 02:36:19 | 只看该作者
发言的过程有些漫长,但是唐欣却很紧张!因为做为全国高考状元的得主,他也要发言。而且他的发言排名第三,仅次于吴市长以及海师高中校长发言之后。
回复 支持 反对

使用道具 举报

龙8国际客户端下载官网
8#
发表于 2019-04-19 09:53:08 | 只看该作者
“很难,那是天时地利人和三者齐全才能做到,而起我刚才也是九死一生才做到,如果在期间被白色妖虎的攻击打中的话那么就完蛋了,而且也是多亏了这里有一道瀑布,不然的话没有瀑布作为水灵气的载体,飞流直下的冲击作为力量,我的混元长河作为牵引和汇聚,根本无法做到刚才的一击薜
回复 支持 反对

使用道具 举报

胜博发手机客户端下载
9#
发表于 2019-04-19 01:56:57 | 只看该作者
四手相接,如果说刚才是技巧上的使用,那么眼前就是完全变成了力量上的较量。两双大小不同的手已经抓在了一起。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

连发lianfa注册送28是互联网最大的搜索引擎优化研究中心,是致力于培养学员用户体验意识和提供专业技术解答的专业培训机构, 成立于2007年,2008年第一家入驻歪歪的培训机构,2014年成为腾讯课堂战略合作机构。
© 2007-2016 连发lianfa注册送28 湘ICP备13004652号-1 Powered by Discuz!X  Template by 连发lianfa注册送28 
快速回复 返回顶部 返回列表