Robolectric测试框架使用文档
Robolectric使用文档
--keeng2008@qq.com 2016-01-07
1.测试驱动你的Android应用代码
在Android模拟器或者手机上运行单元测试是很漫长的。每次编译、部署、启动应用都需要耗时1分钟以上。有没有更好的办法呢?
Robolectric 是一个针对于Android SDK 的单元测试框架,使用它可以测试驱动你的Android应用程序的开发。测试用例只需要在JVM基础上就能运行起来,这节省了大量的时间。使用Robolectric后,你只需要写出类似这样的测试代码:
@RunWith(RobolectricTestRunner.class) public class MyActivityTest { @Test public void clickingButton_shouldChangeResultsViewTest() throws Excepiton { MyActivity activity = Robolectric.setupActivity(MyActivity.class); Button button = (Button) activity.findViewById(R.id.button); TextView results = (TextView) activity.findViewById(R.id.results); button.performClick(); assertThat(results.getText().toString()).isEqualTo("Robolectric Rocks!"); } } |
Robolectric 通过重写Android SDK 的实现类,然后被加载到测试工程中,然后让上面的测试代码可以在JVM上运行。
SDK,资源,原生方法的模拟
Robolectric 模拟了界面生成,资源加载,还有大量的基于Android设备底层C语言提供的原生方法提供的功能。这可以让测试模拟到跟真实设备一样的大部分事情。如果对于一些具体的SDK方法提供自己的实现,也是非常容易的,所以你可以模拟真实机器上发生的一些出错的条件,出错的行为。
2.开始使用Robolectric
Robolectric在Gradle和Maven上测试运行得很好。
使用Gradle
在build.gradle里添加下面一行:
testCompile “org.robolectric:robolectric:3.0” |
在测试用例代码中添加Gradle Test的注解
@RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class) public class SandwichTest { } |
注意,一定要配置constants属性指向BuildConfig.class, 编译系统会自动生成这个类,不用手动创建。Robolectric读取constants配置好的输出路径,Gradle生成项目时会使用到。如果没有这些值,Robolectric就找不到应用的manifest, resources还有assets等资源。
在Android Studio 生成
Robolectric支持Android Studio 1.1.0及更高的版本。只需要简单的参照上面Gradle的配置。然后在”Build Variants”选项中下拉选择Unit Tests就可以运行了。
在Gradle的Task列表中选择testDebug运行(第一次运行需要的时间很久)。
3.编写第一个例子
创建一个Activity,显示一个登陆界面。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/login" android:text="Login" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> |
当用户点击登陆按钮就跳转到欢迎界面
public class WelcomeActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.welcome_activity); final View button = findViewById(R.id.login); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivity(new Intent(WelcomeActivity.this, LoginActivity.class)); } }); } } |
我们希望测试的是,当用户点击登陆按钮后,我们启动了正常的intent。由于Robolectric只是一个模拟的单元测试框架,LoginActivity并不会真正的启动,但是我们可以检查是否准确的发出了WelcomActivity的intent。
@RunWith(RobolectricTestRunner.class) public class WelcomeActivityTest { @Test public void clickingLogin_shouldStartLoginActivity() { WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class); activity.findViewById(R.id.login).performClick(); Intent expectedIntent = new Intent(activity, WelcomeActivity.class); assertThat(Shadows.shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent); } } |
4.配置Robolectric
有几种方法来配置Robolectric的运行时行为。
Config注解
最简单的配置Robolectric的方法就是使用@Config注解。这个注解可以作用于类和方法,如果在类和方法都同时配置了同一个属性,方法的配置会覆盖类的配置。
基类的注解对于所有的子类都是有效的,所以如果你要在很多的类使用同一个配置,可以创建一个基类,然后把@Config注解移到基类中。
下面的例子展示了更多的配置内容。
配置SDK版本
Robolectric会使用你在manifest中指定的targetSdkVersion版本来运行测试代码。如果你想测试在其它指定版本的表现,可以通过下面的修改这个SDK版本:
@Config(sdk = Build.VERSION_CODES.JELLY_BEAN) public classSandwichTest { @Config(sdk = Build.VERSION_CODES.KITKAT) public void getSandwich_shouldReturnHamSandwich() { } } |
配置Application类
Robolectric会根据manifest的配置自动帮你创建一个Application类,如果你希望提供一个自己实现的类,可以这样设置:
@Config(application = CustomApplication.class) public class SandwichTest { @Config(application = CustomApplicationOverride.class) public void getSandwich_shouldReturnHamSandwich() { } } |
配置Resource路径
Robolectric为Gradle和Maven提供了默认的设置,但是也允许你修改这些资源的路径,包括manifest, resource目录,assets目录。如果你有一个自定义的生成脚本这会非常有用。示例:
@Config(manifest = "some/build/path/AndroidManifest.xml") public class SandwichTest { @Config(manifest = "other/build/path/AndroidManifest.xml") public void getSandwich_shouldReturnHamSandwich() { } } |
默认的,Robolectric会假定你的resouces和assets都是放在目录res和assets中。这些目录都是配置成相对于manifest的相对目录。你也可以在@Config注解中添加resourcesDir和assetsDir选项来修改资源路径。
使用属性配置文件
任何在@Config注解可以配置的属性也可以写成一个全局的properties文件。创建一个文件robolectric.properties,确认在classpath中可以找到。例如:
sdk=18 manifest=some/build/path/AndroidManifest.xml shadows=my.package.ShadowFoo,my.package.ShadowBar |
系统属性
还有以下的选项可以在properties中配置
robolectric.offline设置true后为离线状态,不会在运行时去下载jar文件
robolectric.dependency.idr在离线状态,提供一个运行时查找依赖文件的目录
robolectric.logging.enable设为true后打开debug日志
5.控制Activity的生命周期
在Robolectric 2.2版本以前,创建Activity多数都是直接调用构造函数(new MyActivity())然后手动调用生命周期的函数如onCreate()。还有广泛使用的ShadowActivity(例如ShadowActivity.callOnCreate()),这就是现在ActivityController的设计原型。
为了解决调用的混乱,Robolectric API提供了ActivityController,用它来简化创建Activity还有控制Activity的生命周期。
不需要调用onCreate这些函数,ActivityController确保了Activity生命周期的一致性,这包括把Activity显示到Window,还提供了如LayoutInflater这些系统服务。
具体怎么做
你不要直接new一个ActivityController,使用Robolectric.buildActivity()来获得一个实例。对于大多数基本的测试用命 ,你只需要一行代码就能初始化一个Activity:
Activity activity = Robolectric.buildActivity(MyAwesomeActivity.class).create().get(); |
这会创建一个MyAwesomeActivity,并且已经调用了onCreate()。
想去检查一些在onCreate()和onResume()之间发生的事件,这很简单:
ActivityController controller = Robolectric.buildActivity(MyAwesomeActivity.class).create().start(); Activity activity = controller.get(); // assert that something hasn't happened activityController.resume(); // assert it happened! |
还有类似的函数包括start(), pause(), stop()和destroy()。所以如果你想测试一个完整的创建周期:
Activity activity = Robolectric.buildActivity(MyAwesomeActivity.class).create().start().resume().visible().get(); |
模拟使用intent来启动一个Activity:
Intent intent = new Intent(Intent.ACTION_VIEW); Activity activity = Robolectric.buildActivity(MyAwesomeActivity.class).withIntent(intent).create().get(); |
还有保存状态等调用:
Bundle savedInstanceState = new Bundle(); Activity activity = Robolectric.buildActivity(MyAwesomeActivity.class) .create() .restoreInstanceState(savedInstanceState) .get(); |
需要更多关于ActivityController的功能可以查看Java Doc文档。
奇怪!调用visible() 有用吗?
实际上一个Android app, 一个Activity的视图会在onCreate()被调用后一段时间才添加到Window上的,在此之前,Activity的控件是不可见的,这意味着你没法处理任何的点击交互。Activity的控件树在onPostResume()被调用后才添加到设备或者模拟器的Window上。与其在猜测不确定的时候点Activity会被显示,Robolectric给单元测试的开发者提供了直接控制Activity显示的功能。
然而我们什么时候调用它呢?就是当你在Activity内部需要操作控件的交互时,调用类似于Robolectric.clickOn()需要视图是可见的。注意调用顺序是先onCreate()再调用visible()。
6.使用额外的子模块
为了减少测试时需要依赖的数量,Robolectric对Android的模拟也拆分为很多附加的子模块,只有在Android SDK的基本包里面的类才包含在Robolectric的主模块中。其它的如appcompat或者support 依赖库是作为附加子模拟提供的。下面的表格中列出了可用的附加包:
SDK包 |
Robolectric附加包 |
com.android.support.support-v4 |
org.robolectric:shadows-support-v4 |
com.android.support.multidex |
org.robolectric:shadows-multidex |
com.google.android.gms:play-services |
org.robolectric:shadows-play-services |
com.google.android.maps:maps |
org.robolectric:shadows-maps |
org.apache.httpcomponents:httpclient |
org.robolectric:shadows-httpclient |
注意附加包的功能需要在build.gradle或者pom.xml里添加后才能使用。
参考:http://robolectric.org/getting-started/
Robolectric测试框架使用文档相关推荐
- 框架、文档、视图类之间的调用关系
在多文档MFC应用程序执行过程中,创建了多于一个的文档类.视图类.子框架类对象和一个主框架类.应用类对象.这些对象之间是通过一定的方式联系在一起的,在应用程序设计中,时常需要通过这些对象之间的关系来实 ...
- OVAL验证框架帮助文档
OVAL验证框架帮助文档 java开源验证框架oval,功能非常强大,使用简单:现在整理帮助文档供大家参考,希望能得到更多的反馈和使用经验. 1. 注解说明 1.1. @Assert Check ...
- DL动态加载框架技术文档
DL动态加载框架技术文档 DL技术交流群:29969245 1. Android apk动态加载机制的研究 2. Android apk动态加载机制的研究(二):资源加载和activity生命周期管理 ...
- django框架学习文档_Python四大主流网络编程框架,你知道么?
高并发处理框架-- Tornado Tornado 是使用 Python 编写的一个强大的可扩展的 Web 服务器.它在处理高网络流量时表现得足够强健,却在创建和编写时有着足够的轻量级,并能够被用在大 ...
- SSM框架学习文档以及SSM整合(附Github地址=含SSM学习时的实例代码)
SSM框架学习 软件架构: 基于流行SSM框架:Spring+SpringMVC+Mybatis 项目配置: 使用Maven进行项目jar导入 使用Git进行版本控制,并将每次编写的代码上传到Gi ...
- 个性化测试学生评测软件,团队项目(2+3):自动测试平台-- 需求文档
0. 项目背景 在软件工程课程中,个人项目的测试一直是一个难以自动化的问题.不同的学校的项目题目不同,测试代码也不一样,每一届助教都需要手动测试或费时费力写一个自动批处理测试的程序.但在助教们使用的过 ...
- 一份MyBaits框架PDF文档,阿里架构师直言,Java程序员快收藏吧
mybatis技术相信各位都不陌生, 在我们目前最常见的三大框架中,其中就有mybatis, 也可以说,几乎所有的Java程序员, 都必须掌握mybatis框架,这一份文档,讲从0开始讲解,带着你由浅 ...
- SpringBoot集成Swagger2自动生成友好的RestApi测试页面及文档
springBoot集成swagger2 水煮鱼又失败了 https://www.jianshu.com/p/002ce2f26103 1 背景 springBoot作为微服务首选框架,为其他服务提供 ...
- 测试管理之--文档管理
测试文档是整个测试中的重要输出:测试文档同时也贯穿测试活动的始末:在测试计划.测试设计.测试执行.测试验收等过程中会产生各种各样的文档.测试文档的最终目的是为了更有效的测试及保存测试组织资产.我们在测 ...
最新文章
- SQL Server DB Link相关
- linux c 中 当前函数名 文件名 可变参 不定参 宏使用
- Android Service下载文件并自定义通知提示下载
- echart 数据视图_关于数据可视化图表的制作,你需要关注的30个小技巧
- RedisTemplate方法的一些简单运用
- 明天要上班了,假如上天再给我一个假期…
- GCD HDU - 1695
- scala 字符串转换数组_如何在Scala中将十六进制字符串转换为字节数组?
- a number of 和the number of用法
- html 制作静态页面新知识
- 行业报告归档 2019.2.8
- 基于无线传输的多点温度采集系统
- 离线强化学习(Offline RL)系列1:离线强化学习原理入门
- AWS申请邮件域名和ip绑定
- IDEA中enter键换行问题
- roce流量抓包 linux,roce性能测试方法
- 什么是SEO,为什么要做SEO?
- 华为交换机的远程登录和密码设置
- 转自51cto(http://smailes.blog.51cto.com/rss.php?uid=28248)
- 【论文解读 AAAI 2020 | Bi-GCN】Rumor Detection on Social Media with Bi-Directional GCN
热门文章
- Nginx教程-日志配置
- html动画效果放大,一个CSS+jQuery实现的放大缩小动画效果
- H5页面关于android软键盘弹出顶起底部元素的解决方案
- linux中shell变量$#,$@,$0,$1,$2的含义解释:
- SpringMVC的Controller
- hdoj1428 -- 漫步校园 (记忆化搜索)
- struts2重定向
- EL函数以及自定义标签的应用
- lua工具库penlight--06数据(一)
- Spring+Mybatis 多数据源配置