大家目测一下是不是fake love bts下载

拒绝访问 | www.eeff.net | 百度云加速
请打开cookies.
此网站 (www.eeff.net) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(d743d1-ua98).
重新安装浏览器,或使用别的浏览器解读Android官方MVP项目单元测试 - 简书
解读Android官方MVP项目单元测试
Google在3月份推出了一个项目,用来介绍Android MVP架构的各种组合,可以认为是官方在这方面的最佳实践。令人称道的是除了MVP本身之外,这些工程配备了极其完善的单元测试用例,学习价值极高。本文着重针对todo-mvp的单元测试进行解读。官方MVP项目的Github地址是:
关于MVP的介绍很多,这不是本文的重点,这里列举近期一些比较好的文章。
这篇文章对MVC/MVP/MVVM有很多自己的思考,为什么要有这样架构的演变,以及各自的优缺点的思考,很棒!
大部分业务场景一个View对应一个Presenter,但是如果一个界面需要多个View/Presenter或者同一个View有多个实现且使用同一个PresenterView时候,如何来设计Presenter,这篇文章是很好的延伸阅读。
关于单元测试
对于单元测试,需要预先了解以下内容
Android Studio的test和AndroidTest
:一个兼容Junit4的Andriod单元测试框架
:单元测试利器
:支持UI测试的单元测试框架
关于todo-mvp的功能
简而言之,这个工程包含了三个模块:待办事项列表模块,待办事项详情模块,统计模块。
MVP各层的单元测试选型
在该项目中,MVP各层所使用的单元测试框架如下图所示:
官方todo-mvp的UT选型
P层:不需要任何Android环境,因此使用Junit测试即可
V层:使用Google强大的Espresso进行UI的测试
M层:涉及到数据库相关操作,因此需要依赖Android环境,使用AndroidJUnitRunner进行测试
在此处,我们先大致了解一下MVP各层的UT选型,然后通过一个例子,看看各层之间如何配合测试,最后再对各层UT选型的原因进行分析,从而理解整体测试架构。
接下来我们以TO-DO List页面(TasksActivity/TaskFragment)中加载任务列表功能为例,此场景的功能界面如下图所示:
待办任务列表
Presenter层的测试
在这个功能里,Presenter只做了一件事情,就是loadTask(),时序图如下所示:
loadTask的时序图
从时序图上看,loadTask执行的逻辑是,1.调用View层开启进度条-&2.从Model层获取待办任务列表-&3.Model层以回调函数的形式返回数据-&4.调用View层关闭进度条-&5.调用View层显示任务列表。这5个步骤里,每个步骤的逻辑是否准确是View层和Model层该测试的事情,对于Presenter层来讲,他的测试任务是确保这5个步骤如期调用。为了达成此目的,我们会采用Mockito.verify()的api进行测试,这个测试类是TasksPresenterTest,代码如下:
public void loadAllTasksFromRepositoryAndLoadIntoView() {
//确保当前视图是All视图
mTasksPresenter.setFiltering(TasksFilterType.ALL_TASKS);
//第0步:开始加载数据
mTasksPresenter.loadTasks(true);
//验证第2步:获取待办事项的逻辑有调用
verify(mTasksRepository).getTasks(mLoadTasksCallbackCaptor.capture());
//通过Mockito的Capture进行回调函数的测试,对应第3步
mLoadTasksCallbackCaptor.getValue().onTasksLoaded(TASKS);
//验证第1步:进度条显示
verify(mTasksView).setLoadingIndicator(true);
//验证第4步:进度条关闭
verify(mTasksView).setLoadingIndicator(false);
ArgumentCaptor&List& showTasksArgumentCaptor = ArgumentCaptor.forClass(List.class);
//验证第5步:View层显示待办任务列表
verify(mTasksView).showTasks(showTasksArgumentCaptor.capture());
//在Before周期里,事先初始化了3条待办任务数据
assertTrue(showTasksArgumentCaptor.getValue().size() == 3);
注:这里涉及到异步回调函数如何测试的问题,使用Mockito的Capture可以解决此问题。具体细节,三言两语说不清,后续考虑专门写篇文章。
总结:让Presenter充当个合格的皮条客,去调用其他两层的逻辑,在假设其他两层代码逻辑都是正确的前提下,做一些mock测试,尽可能覆盖所有逻辑路径。
View层的测试
这一层的测试其实很清晰,站在QA的角度,我们想要验证待办任务列表时候,会设计以下的测试用例:
验证待办任务列表的测试流程
通过Espresso可以模拟这些步骤,并进行验证,这个测试类是TasksScreenTest,代码如下:
public void showAllTasks() {
//添加2个待办任务,对应第1、2、3步
createTask(TITLE1, DESCRIPTION);
createTask(TITLE2, DESCRIPTION);
//切换为All视图,对应第4步
viewAllTasks();
//验证Title1和Title2对应的Item存在,对应第5步
onView(withItemText(TITLE1)).check(matches(isDisplayed()));
onView(withItemText(TITLE2)).check(matches(isDisplayed()));
其中,createTask()的实现如下:
private void createTask(String title, String description) {
//点击添加按钮,对应第1步
onView(withId(R.id.fab_add_task)).perform(click());
//打开软键盘,输入标题和描述,对应第2步
onView(withId(R.id.add_task_title)).perform(typeText(title),
closeSoftKeyboard());
onView(withId(R.id.add_task_description)).perform(typeText(description),
closeSoftKeyboard());
//保存待办任务,对应第3步
onView(withId(R.id.fab_edit_task_done)).perform(click());
viewAllTasks()的实现如下:
private void viewAllTasks() {
//点击过滤按钮
onView(withId(R.id.menu_filter)).perform(click());
//点击ALL的选项
onView(withText(R.string.nav_all)).perform(click());
连上设备,跑起UT,会自动启动相应的Activity界面,做相应的操作后进行测试。
总结:Espresso好强大,而且这一层的测试站在用户的角度,所有逻辑是黑盒,在功能层面测试输入(用户操作)输出(用户得到的界面反馈),而技术层面,由于界面是所有层的入口,得到输出后,除了测试View层本身的逻辑之外,其实已经粗糙的覆盖了M和P的逻辑了。
Model层的测试
关于Model层的测试,首先要了解下该项目中,model层的设计,类层次如下图所示:
Model层的类图
TasksLocalDataSource:负责本地数据库增删改查操作
TasksRemoteDataSource:负责网络请求(该项目中用handler.postDelayed()延时来模拟网络请求)
TasksRepository:相当于整个Model层的门面,根据逻辑判断决定数据来自于本地数据库或是网络。Presenter层只与它打交道。
根据以上分析,可见对Model层的测试要完整的覆盖这三个类。
我们先看门面TasksRepository的测试,先看看这个类中有关获取待办任务列表的流程图:
TasksRepository流程图
所以对于TasksRepository来讲,测试的内容主要是验证1,2,3的逻辑是否在相应的输入下覆盖到位,对于1,2,3的数据准确性无需关心,由各自DataSource去验证,因此它的测试与Android环境无关,用Junit+Mockito测试。要完整覆盖的话,需要多个测试case,篇幅有限,这里只讲第2种。这个测试类是TasksRepositoryTest,代码如下:
public void getTasksWithDirtyCache_tasksAreRetrievedFromRemote() {
//将数据设置为脏数据
mTasksRepository.refreshTasks();
//数据为脏数据,因此此时需要从网络获取
mTasksRepository.getTasks(mLoadTasksCallback);
//验证第2种情况:用TasksRemoteDataSource调用getTasks()获取数据后返回
setTasksAvailable(mTasksRemoteDataSource, TASKS);
//验证第1种情况没有发生
verify(mTasksLocalDataSource, never()).getTasks(mLoadTasksCallback);
//验证TasksRemoteDataSource执行了回调函数
verify(mLoadTasksCallback).onTasksLoaded(TASKS);
其中,setTasksAvailable()代码如下:
private void setTasksAvailable(TasksDataSource dataSource, List&Task& tasks) {
//验证第2种情况:使用TasksRemoteDataSource调用getTasks()
verify(dataSource).getTasks(mTasksCallbackCaptor.capture());
//执行回调 函数
mTasksCallbackCaptor.getValue().onTasksLoaded(tasks);
接下来是是TasksLocalDataSource的测试。该测试与数据库有关,因此依赖于Android环境,且要验证数据存取的准确性,因此需要做一些断言,使用AndroidJUnitRunner进行测试,这个类是TasksLocalDataSourceTest,代码如下:
public void getTasks_retrieveSavedTasks() {
//事先往DB中插入两条数据
final Task newTask1 = new Task(TITLE, "");
mLocalDataSource.saveTask(newTask1);
final Task newTask2 = new Task(TITLE, "");
mLocalDataSource.saveTask(newTask2);
//执行获取数据列表的方法,并在回调函数中进行断言
mLocalDataSource.getTasks(new TasksDataSource.LoadTasksCallback() {
public void onTasksLoaded(List&Task& tasks) {
//断言数据非空,且有&=2条的Task数据
assertNotNull(tasks);
assertTrue(tasks.size() &= 2);
boolean newTask1IdFound =
boolean newTask2IdFound =
for (Task task: tasks) {
if (task.getId().equals(newTask1.getId())) {
newTask1IdFound =
if (task.getId().equals(newTask2.getId())) {
newTask2IdFound =
//验证查询出的数据包含事先插入的数据
assertTrue(newTask1IdFound);
assertTrue(newTask2IdFound);
public void onDataNotAvailable() {
最后来看看跟网络请求相关的TasksRemoteDataSource的测试
Google并没有对这个类本身进行测试,但是对其他层依赖网络请求数据进行测试的场景做了支持。试想一下,通过上面的分析,我们知道View层是真刀真枪的在模拟用户的操作进行测试,如果某个测试case需要发起网络请求,此时我们不知道何时才能返回数据,且由于网络状况等原因可能导致请求失败,种种不确定因素下,是不可能完成一个测试的,解决的办法很简单,就是对网络请求进行Fake,这个类是FakeTasksRemoteDataSource,原理便是当需要用到TasksRemoteDataSource时,不会真正使用该类,而是注入FakeTasksRemoteDataSource,返回事先定义好的数据。
为此,这个项目在项目结构和代码方面提供了很多支撑,体现在:
提供了mock和prod两种Flavors
两种Flavor分别提供了Injection,注入Fake类或真实类
所有与网络请求相关的测试代码存放在androidTestMock下
总结:Model层的测试时而在androidTest写UT,时而在test里写,时而在androidTestMock里,有点精神分裂的感觉。但是,真的好清晰,看起测试的结构来非常舒服。
MVP的单元测试架构总结
通过这个例子,我们已经了解了MVP各层之间的职责以及对应的测试内容,接下来做个总结,首先看下MVP测试架构图:
MVP测试架构图
职责:MVP模式下,View层终于扬眉吐气了,View本身该做的事情都能做了,比如UI布局,数据渲染,点击按钮交互等等
测试方式:以正常小QA的测试思维方法,就可以来定义这一层的测试方式,测试过程中需要真机或模拟器,并做真实的操作。
测试选型:依赖于Android环境,用谷歌强大的Espresso+AndroidJUnitRunner,Espresso用于模拟和验证各种各样的UI操作,代码存放于AndroidTest中。
Presenter层:
职责:这一层是拉皮条的,负责M和V层的对接,所以有较少的处理输入输出的机会,他只用来控制逻辑,去调用相应的Model和View的逻辑。
测试选型:他的职责决定了他很少去断言输入输出,测试逻辑覆盖的路径是否正确即可,因此他与Android环境无关,用Junit+Mockito测试即可,代码存放于test中。
职责:负责数据的存取,数据可能来自于网络、数据库和内存
数据库增删改查:需测试数据存取的准确性,依赖Android环境进行测试,因此使用AndroidJUnitRunner,代码存放于androidTest中
网络请求:不测试真实的网络请求,但提供了Fake供其他层调用测试。
封装的门面类:决定了数据的来源和去向是来自于本地数据库 or 网络 or 内存,此为真正对其他层暴露的Model类。此类不做数据准确性的验证,只做mock测试,验证覆盖路径。UT选型Junit+Mockito,代码存放于test中。
Android官方MVP架构示例项目在单元测试方面真是良心之作,分析测试用例远比分析MVP本身得到的收获多得多,感谢Google,感谢他粗壮的大腿,抱大腿的感觉真好。
此外,在做架构时,不能忽视在单元测试方面的架构,所以,好的架构是可以支撑代码的可测试性的,Google给我们做了非常棒的最佳实践,接下来就是各自的项目实践,不妨从某个模块开始,步步为营,写好MVP,补齐单元测试用例。
喜欢此文,觉得此文有用,请打赏_!
『如何写有价值的测试用例』也是非常重要的话题,在todo-mvp中大大小小的测试用例也有几十个,所以耐心的看看测试代码,可以给我们带来很多思路和指导,由于这部分篇幅较长,且枯燥无味,因此另起一篇文章,有需要的请。
Androooooooooooid|技术人文|项目管理
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金 相信有很多...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金相信有很多朋友...
综述 对于MVP (Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的。而对于Android应用的开发中本身可视为一种MVC架构。通常在开发中将XML文件视为MVC中的View角色,而将Activity...
作者:李旺成 时间:日 “Android MVP 详解(下)”已经发布,欢迎大家提建议。 MVP 在 Android 上的使用其实已经有挺长一段时间了,长到似乎有点“过时”了(目前风头正劲的是MVVM),那为什么现在还要讲 MVP。今天我想要讨论它的主要原因...
转载至:http://www.jianshu.com/p/9a “Android MVP 详解(下)”已经发布,欢迎大家提建议。 MVP 在 Android 上的使用其实已经有挺长一段时间了,长到似乎有点“过时”了(目前风头正劲的是MVVM),那为什么现...
尿不湿方便的是父母,坑害的是孩子!
80年代,“太空服之父”华人唐鑫源为解决太空人排尿问题,改进了太空服,加入高分子吸收体,发明了能吸水1400毫升的纸尿片,尿尿才不再是宇航员的难题。 技术后来转为民用,就是现在千家万户使用的“尿不湿”。
传统尿布和尿不...
01 看着在我眼里这个世界上最帅最可爱的小脸,听着他均匀的呼吸,久久舍不得移开眼镜。是的,这个萌萌哒水嫩嫩的小天使就是我上辈子亏欠的情人,这辈子要把所有的爱都还给他。 舍不得让他一个人睡婴儿床,从出生那天起就一直睡在我的旁边,即将14个月的他习惯了半夜醒来摸摸我,感受一下我...
暗恋一个人是什么感觉?我想大概就是……认识你之前,从未有过结婚的想法,暗恋你以后,觉得你就是最好的。 1 我从未得到过ta,却像经历了几千次失去。 2 把ta的每一个状态,都当成了阅读理解。 3 ta是我的秘密,怕ta知道,也怕ta不知道,又怕ta知道却装作不知道。 4 没...
第一次报名丽芳老师亲自授课的课程,有些兴奋,今天又把课程内容回听一遍,收获多多,也很认真思考和绘制作业,希望能得到老师的指点……
以前挺害怕狗,因为被咬过,一朝被蛇咬,十年怕草绳,对于狗也一样。那个秋天,穿着稍厚的衣服,与小伙伴在小道上嬉戏玩耍,一只黄狗,卧在道旁。自己一不小心,踩到了它,汪的一声,吓得我的心扑通扑通跳。我看着它,它看着我,惊得我忘了走开。它突然张开大口,朝我扑来,锋利的牙齿,触碰到我...什么是Fake,仿的鞋子什么品质最好?
我发现大家现在买鞋都对一个新鲜名词产生了极大的兴趣,Fake,什么是Fake呢,它又分几类呢,什么样的品质才是适合我们学生,又高性价比的呢?下面我就跟大家来探讨一下吧。
说到Fake我们会不由自主的想到福建莆田,为什么呢?因为在如今这个仿品占据中国大部分市场的情况下,福建莆田可以说是制造Fake鞋的领先者,他们会有专门的厂去制作这些鞋子,并销往各地,那有些人说了Fake到底是什么呢?从字面理解它的英文释义是赝品,仿品,所以这个词对于大多数喜欢买鞋的人当然是非常理解的,那为什么很多买正品的原意加入到买仿品的队伍中呢
?这个也有它其中的道理,一是中国市场的混乱,大家找不到合适的购买渠道,害怕用正品的钱却买到的是仿品这是其一,这也不能多说什么,目前这市场毒奶粉,毒豆芽什么不是假的,大家对市场的警惕性也是可以理解的。
是因为仿品本着其优质的做工和质量,和其独特的价格优势已经完全占据了正品的市场,有人说我喜欢买正品,我有钱,当然你有钱消费是可以的,但是对于尚未走入社会的学生群体,他们往往看中的只是产品的款式,但是正品的价格也是他们所不能承受的,也许,有些人会问家里要钱,但是有些就会存钱,省去自己的生活费买上一双700,甚至一千的鞋子,先不说对不对,只是耽误了自己的健康,而且鞋子毕竟也不用太过于高端,700百的价位毕竟只是小部分家庭所能够承受的,大部分都只是选择观望,所以仿鞋以其价格优势,款式优势,和质量优势迅速上升,不过并不是说支持正品,当然在自己有购买能力的情况下是可以购买正品的,但是,如果你只是学生,高昂的价位你又如何承受呢?
这里会有人问了,我穿一双高仿出去别人一眼就看出来了,丢脸死了,我还不如不穿,那这里我就得好好跟你们科普一下了,仿鞋也是有类别的,分几种类型当然价位也会随着品质的上升而上升,这时无可厚非的,毕竟一分价钱一分货。所以说买贵不算好,买便宜也不算,买到价位最合适,品质又最好的才算是高性价比的好货,而且单单只从鞋子款式上来看也是不行的,最重要的是上脚要够舒服。因为最主要的鞋子还是用来走路的,不是用来观赏的。
&&&&&&&&&三&莆田的鞋子最好的货在它那最差的货也在它那,很幸运,我选择的厂家是给力的,过硬的质量无疑给我增加了好的口碑,别人冲的就是你的品质来的,是金子总会发光,而且不说仿鞋是好是坏,现在很多莆田厂家革新技术,有些仿鞋甚至比专柜货的品质还要高,你与其相信代购,不如看清事实,代购那么低的价位你觉得可以拿到正品吗?只是卖仿换了一个说辞,并且现在仿品技术含量越来越高,小票,购物袋全套都能做的跟正品天衣无缝,那么与其相信代购花个600买个所谓的正品,你和不看清事实,直接去买到最合适最直接的FAKE呢?我也坚信我的鞋店不用其他与别人竞争,光靠品质和口碑加上好的售后就足以取胜~这里给大家科普完了,下次再聊~
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。视频暂时不能查看
下载好看APP扫一扫 下载吧
您所浏览的视频已不在
《好看》依托百度技术,精准推荐优质短视频内容,懂你所好,量身打造最适合你的短视频客户端!大家目测一下这一届上犹一中录取分数线是多少?【上犹二中吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:2,734贴子:
大家目测一下这一届上犹一中录取分数线是多少?收藏
楼主先来。听别人说的:488
因为达到488的人就要1200多人了。
呵呵,想多了
最少都530左右
1400百名前
去看看排名表
犹中的老师都还不清楚
出来了。。。是五百多
没想到是486吧
500多还高?当初我中考在定南562分想回上犹一中结果特么不行要12000所以还是乖乖到回定南读尖子班吧!唉!
登录百度帐号

我要回帖

更多关于 fake taxi是不是演的 的文章

 

随机推荐