工程公路试验检测小软件app

APP测试及上线_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
APP测试及上线
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
你可能喜欢百度移动云测试中心 | MTC - 流畅 快速 权威
百度MTC-移动云测试中心
专注您的App本身,技术、设备、人力烦恼交给我们
海量用户17,000,000人
测试专员10,000名
真实手机10,000部
覆盖机型1500款
188畅享远程真机调试服务
最划算的测试套餐
首次完善资料,领取测试基金
专家团队测试
适用于“0”测试团队、或测试团队人力不足的客户。平台会根据App产品特征为您匹配专属的测试团队,全面接管您的产品测试环节。
200名测试领域专家(6年以上工作经验)
多种行业、名企专业背景
1-2天交付测试报告
自动化测试
适用于已完成基本功能测试、对App质量有较高要求的客户,平台为您提供海量设备,帮您验证App的兼容性、稳定性和安全性。
10000台手机1500款机型
多地域、系统、网络环境
4小时交付测试报告
海量用户测试
适用于App发版前需进行灰度测试和反馈收集的客户,平台会根据您的测试需求筛选用户,在真实场景中体验产品,帮您控制新版发布风险。
10000名考核认证测试专员
多地域、行业、年龄属性
1-5天交付测试报告
适用于产品推广阶段需要进行市场调研、收集产品体验反馈的客户,平台为您提供问卷设计工具及样本精准投放服务,帮您快速完成调研。
1700万样本用户
多地域、年龄、行业属性
1天回收1000份问卷
大客户定制解决方案
通过云测实验室的海量真实手机及百度专业的测试专家团队,为企业提供移动App定制测试方案及多样化的交付结果
通过百度MTC独创的本地化移动App测试解决方案,为企业迅速搭建一个内网真机自动化测试实验室,实现测试数据私有,设备远程管理等服务。
垂类解决方案
提供智能硬件与手机间的联通性测试、兼容测试,快速定位缺陷
提供智能硬件与手机间的联通性测试、兼容测试,快速定位缺陷
提供应用商店海量APP与手机厂商手机的兼容性测试,快速完成上架审核
提供应用商店海量APP与手机厂商手机的兼容性测试,快速完成上架审核
提供真机兼容测试、真人体验测试,覆盖手机端、服务器、用户端
提供真机兼容测试、真人体验测试,覆盖手机端、服务器、用户端
提供兼容测试、性能测试、功能测试、用户评测、安全测试等服务
提供兼容测试、性能测试、功能测试、用户评测、安全测试等服务
本文邀请到前华为首席测试专家杨晓慧,凭借自己18年的测试经验,为大家分析围绕效率提升,测试可以做什么。
作者:杨晓慧日期:
六年软件测试经验且非常喜欢探索式测试的James Bach迷妹,为您带来James Bach经典文章中译版,不容错过~
作者:张莹日期:
工程应用与学术研究,对测试技术的了解和兴趣,差异巨大。
作者:杨晓慧日期:
关注微信公众号
了解前沿测试技术 每周领取代金券
百度手机助手
百度移动应用推广
百度移动联盟
百度移动游戏
恭喜您,获得新用户首免福利
深度兼容测试(20款)
远程真机调试
用户接受度评测
功能回放测试
深度遍历测试
深度性能测试
为确保给您提供更好的服务,请尽快完善资料!
现在完善还能领取¥500测试代金券
关注微信公众号了解前沿测试技术 每周领取代金券
&2017Baidu&|&百度MTC如何做一个优秀的APP测试工程师?
| 更新于 日
工作几年了,做的不够好,如何提升测试水平呢?
1.一直做,但是每次上线都遗漏一些比较明显的BUG,但BUG不严重,不知道如何能cover到所有的点
2.如何在快速迭代中稳定版本。
3.想学习or培训,找不到合适的。
4.不知道优秀团队是如何实现稳定测试的
先详细说说你自己的情况吧
@ tiny叔,已经写了
@ 格式看看右边的格式建议
做开发比做测试爽 当然是个人感觉 很多公司 我说的天朝大部分公司都不重视测试 不重视测试!!!!!!
@ 也不是,主要是重视,但是资源给不够,压力太大
tiny 叔 不是给《iOS 测试指南》写了一个序嘛。
做测试的童鞋也可以去看看
http://tiny4.org/blog/2014/04/ios-app-test/
@ 这个是不是白盒的东西,黑盒测试的能用上吗?
@ 先买了看看,真的不想再裸奔了作者:Ringoyan,腾讯测试开发工程师。先后为植物大战僵尸Online,糖果传奇等游戏担任测试经理,其负责的“我叫MT2”测试项目曾获腾讯互动娱乐精品文化奖银奖。目前担任腾讯WeTest测试经理。擅长领域:App的自动化测试和Web的安全测试工作。
注:核心内容转自许奔的《深入理解Android自动化测试》,本书将在许奔公众号“巴哥奔”中全文连载。
商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。
WeTest导读
说起Android的自动化测试,相信有很多小伙伴都接触过或者有所耳闻,本文从框架最基本的功能介绍及API的使用入手,结合简单的项目实战来帮忙大家对该框架进一步理解和加深印象。下面让我们来一睹标准App的四大自动化测试法宝的风采!
法宝1:稳定性测试利器——Monkey
要想发布一个新版本,得先通过稳定性测试。理想情况是找个上幼儿园的弟弟妹妹,打开应用把手机交给他,让他胡乱的玩,看你的程序能不能接受这样的折腾。但是我们身边不可能都有正太和萝莉,也不能保证他们拿到手机后不是测试软件的健壮性,反而测试你的手机经不经摔,这与我们的期望差太远了…
Google公司考虑到我们的需要,开发出了Monkey这个工具。但在很多人的印象中,Monkey测试就是让设备随机的乱点,事件都是随机产生的,不带任何人的主观性。很少有人知道,其实Monkey也可以用来做简单的自动化测试工作。
Mokey基本功能介绍
首先,介绍下Monkey的基本使用,如果要发送500个随机事件,只需运行如下命令:
adb shell monkey 500
插上手机运行后,大家是不是发现手机开始疯狂的运行起来了。So Easy!
在感受完Monkey的效果后,发现这“悟空”太调皮了,根本招架不住啊!是否有类似“紧箍咒”这种约束类命令,让这只猴子在某个包或类中运行呢?要想Monkey牢牢的限制在某个包中,命令也很简单:
adb shell monkey –p your-package-name 500
-p后面接你程序的包名。多想限制在多个包中,可以在命令行中添加多个包:
adb shell monkey –p your-package1-name –p your-package2-name 500
这样“悟空”就飞不出你的五指山了。
Mokey编写自动化测试脚本
若控制不住“悟空”,只让它随机乱点的话,Monkey是替代不了黑盒测试用例的。我们能不能想些办法,控制住“悟空”让他做些简单的自动化测试的工作呢?下面来看一下,如何用Monkey来编写脚本。
先简单介绍下Monkey的API,若有需要详细了解的小伙伴,可自行百度或谷歌一下查阅哈。
(1) 轨迹球事件:DispatchTrackball(参数1~参数12)
(2) 输入字符串事件:DispatchString(String text)
(3) 点击事件:DispatchPointer(参数1~参数12)
(4) 启动应用:LaunchActivity(String pkg_name, String class_name)
(5) 等待事件:UserWait(long sleeptime)
(6) 按下键值:DispatchPress(int keyCode)
(7) 长按键值:LongPress(int keyCode)
(8) 发送键值:DispatchKey(参数1~参数8)
(9) 打开软键盘:DispatchFlip(Boolean keyboardOpen)
了解完常用API后,我们来看一下Monkey脚本的编写规范。Monkey Script是按照一定的语法规则编写的有序的用户事件流,使用于Monkey命令工具的脚本。Monkey脚本一般以如下4条语句开头:
type = user
count = 10
speed = 1.0
start data &&
下面来看一个简单应用的实战,实现的效果很简单,就是随便输入文本,选择选项再进行提交,提交后要验证提交后的效果。
type = user
count = 10
speed = 1.0
start data &&LaunchActivity(com.ringo.bugben,com.ringo.bugben.MainActivity)
# 点击文本框1
captureDispatchPointer(10,10,0,210,200,1,1,-1,1,1,0,0)
captureDispatchPointer(10,10,1,210,200,1,1,-1,1,1,0,0)
# 确定文本框1内容
captureDispatchString(Hello)
# 点击文本框2
captureDispatchPointer(10,10,0,210,280,1,1,-1,1,1,0,0)
captureDispatchPointer(10,10,1,210,280,1,1,-1,1,1,0,0)
# 确定文本框2内容
captureDispatchString(Ringo)
# 点击加粗
captureDispatchPointer(10,10,0,210,420,1,1,-1,1,1,0,0)
captureDispatchPointer(10,10,1,210,420,1,1,-1,1,1,0,0)
# 点击大号
captureDispatchPointer(10,10,0,338,476,1,1,-1,1,1,0,0)
captureDispatchPointer(10,10,1,338,476,1,1,-1,1,1,0,0)
# 等待500毫秒
UserWait(500)
# 点击提交
captureDispatchPointer(10,10,0,100,540,1,1,-1,1,1,0,0)
captureDispatchPointer(10,10,1,100,540,1,1,-1,1,1,0,0)
将上述代码另存为HelloMonkey文件,然后将该脚本推送到手机的sd卡里。
adb push HelloMonkey /mnt/sdcard/
然后运行:
adb shell monkey -v -f /mnt/sdcard/HelloMonkey 1
脚本后面的数字1表示运行该脚本的次数。小伙伴们可以安装附件里的Bugben.apk再执行下脚本感受下哦!
Monkey工具总结
Monkey可以编写脚本做简单的自动化测试,但局限性非常大,例如无法进行截屏操作,不能简单的支持插件的编写,没有好的办法控制事件流,不支持录制回放等。我们在平时的使用中,关注较多的是利用好Monkey的优势,如不需源码,不需编译就可以直接运行。
法宝2:Monkey之子——MonkeyRunner
Monkey虽然能实现部分的自动化测试任务,但本身有很多的局限性,例如不支持截屏,点击事件是基于坐标的,不支持录制回放等。我们在实际应用中,尽量关注利用好Monkey测试的优势。若平时的工作中遇到Monkey工具无法满足的,这里给大家推荐另一款工具MonkeyRunner。
同样先简单的介绍下MonkeyRunner的API,这里重点介绍能够实现上文Monkey脚本的API,其余的API感兴趣的小伙伴可以自行查阅。
(1) 等待设备连接:waitForConnection()
(2) 安装apk应用:installPackage(String path)
(3) 启动应用:startActivity(String packageName+activityName)
(4) 点击事件:touch(int xPos, int yPos, dictionary type)
(5) 输入事件:type(String text)
(6) 等待:sleep(int second)
(7) 截图:takeSnapshot()
(8) 发送键值:press(String name, dictionary type)
MokeyRunner编写自动化测试脚本
下面我们来看下,用MonkeyRunner实现的自动化脚本。
# import monkeyrunner modules
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
# Parameters
txt1_x = 210
txt1_y = 200
txt2_x = 210
txt2_y = 280
txt3_x = 210
txt3_y = 420
txt4_x = 338
txt4_y = 476
submit_x = 100
submit_y = 540
type = 'DOWN_AND_UP'
seconds = 1
txt1_msg = 'Hello'
txt2_msg = 'MonkeyRunner'
# package name and activity name
package = 'com.ringo.bugben'
activity = '.MainActivity'
component = package + '/'+activity
# Connect device
device = MonkeyRunner.waitForConnection()
# Install bugben
device.installPackage('./bugben.apk')
print 'Install bugben.apk...'
# Launch bugbendevice.startActivity(component)
print 'Launching bugben...'
MonkeyRunner.sleep(seconds)
# Input txt1
device.touch(txt1_x, txt1_y, type)device.type(txt1_msg)
print 'Inputing txt1...'
# Input txt2
device.touch(txt2_x, txt2_y, type)
device.type(txt2_msg)
print 'Inputing txt2...'
#select bold and size
device.touch(txt3_x, txt3_y, type)
device.touch(txt4_x, txt4_y, type)
MonkeyRunner.sleep(seconds)
# Submitdevice.touch(submit_x, submit_y, type)
print 'Submiting...'
MonkeyRunner.sleep(seconds)
# Get the snapshot
picture = device.takeSnapshot()
picture.writeToFile('./HelloMonkeyRunner.png','png')
print 'Complete! See bugben_pic.png in currrent folder!'
# Back to home
device.press('KEYCODE_HOME', type)
print 'back to home.'
将脚本保存为HelloMonkeyRunner.py,并和Bugben.apk一起拷贝到Android SDK的tools目录下,执行monkeyrunner
HelloMonkeyRunner.py
执行完成后,效果如上,并且会在当前目录生成HelloMonkeyRunner.png截图。
MokeyRunner的录制回放
首先是环境配置,在源码“~\sdk\monkeyrunner\scripts”目录下有monkey_recorder.py和monkey_playback.py,将这两个文件(附件中有这两文件)拷贝到SDK的tools目录下,就可以通过如下代码进行启动:
monkeyrunner monkey_recorder.py
运行结果如下图所示:
下面用MonkeyRecorder提供的控件,来进行脚本的录制。
录制完成后,导出脚本保存为HelloMonkeyRunnerRecorder.mr,用文本编辑器打开代码如下:
TOUCH|{'x':317,'y':242,'type':'downAndUp',}
TYPE|{'message':'Hello',}TOUCH|{'x':283,'y':304,'type':'downAndUp',}
TYPE|{'message':'MonkeyRecorder',}
TOUCH|{'x':249,'y':488,'type':'downAndUp',}
TOUCH|{'x':375,'y':544,'type':'downAndUp',}
TOUCH|{'x':364,'y':626,'type':'downAndUp',}
脚本录制完毕,接来下看看回放脚本是否正常。回放脚本时执行以下命令:
monkeyrunner monkey_playback your_script.mr
由于脚本中未加入拉起应用的代码,这里运行前需手动拉起应用。
结果运行正常,符合我们的预期。
MonkeyRunner工具总结
MonkeyRunner有很多强大并好用的API,并且支持录制回放和截图操作。同样它也不需源码,不需编译就可以直接运行。但MonkeyRunner和Monkey类似,也是基于控件坐标进行定位的,这样的定位方式极易导致回放失败。
法宝3:单元测试框架——Instrumentation
Monkey父子均可通过编写相应的脚本,在不依赖源码的前提下完成部分自动化测试的工作。但它们都是依靠控件坐标进行定位的,在实际项目中,控件坐标往往是最不稳定的,随时都有可能因为程序员对控件位置的调整而导致脚本运行失败。怎样可以不依赖坐标来进行应用的自动化测试呢?下面就要亮出自动化测试的屠龙宝刀了——Instrumentation框架。
Instrumentation框架主要是依靠控件的ID来进行定位的,拥有成熟的用例管理系统,是Android主推的白盒测试框架。若想对项目进行深入的、系统的单元测试,基本上都离不开Instrumentation这把屠龙宝刀。
在了解Instrumentation框架之前,先对Android组件生命周期对应的回调函数做个说明:
从上图可以看出,Activity处于不同状态时,将调用不同的回调函数。但Android API不提供直接调用这些回调函数的方法,在Instrumentation中则可以这样做。Instrumentation类通过“hooks”控制着Android组件的正常生命周期,同时控制Android系统加载应用程序。通过Instrumentation类我们可以在测试代码中调用这些回调函数,就像在调试该控件一样一步一步地进入到该控件的整个生命周期中。
Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的,我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。
下面通过一个简单的例子来讲解Instrumentation的基本测试方法。
1. 首先建立项目名为HelloBugben的Project,类名为HelloBugbenActivity,代码如下:
package com.example.
import android.app.A
import android.os.B
import android.text.TextP
import android.view.M
import android.widget.TextV
public class HelloBugbenActivity extends Activity{
private TextView textview1;
private TextView textview2;
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String bugben_txt = "bugben";
Boolean bugben_bold = true;
Float bugben_size = (float)60.0;
textview1 = (TextView)findViewById(R.id.textView1);
textview2 = (TextView)findViewById(R.id.textView2);
setTxt(bugben_txt);
setTv1Bold(bugben_bold);
setTv2Size(bugben_size);
publicvoidsetTv2Size(Float bugben_size){
TextPaint tp = textview2.getPaint();
tp.setTextSize(bugben_size);
publicvoidsetTv1Bold(Boolean bugben_bold){
TextPaint tpPaint = textview1.getPaint();
tpPaint.setFakeBoldText(bugben_bold);
publicvoidsetTxt(String bugben_txt){
textview1.setText(bugben_txt);
textview2.setText(bugben_txt);
这个程序的功能很简单,就是给2个TextView的内容设置不同的文本格式。
2. 对于测试工程师而言,HelloBugben是一个已完成的项目。接下来需创建一个测试项目,选择“New-&Other-&Android Test Project”,命名为HelloBugbenTest,选择要测试的目标项目为HelloBugben项目,然后点击Finish即可完成测试项目的创建。
可以注意到,该项目的包名自带了com.example.hellobugben.test这个test标签,这就说明该测试项目是针对HelloBugben所设置的。
打开AndroidManifest可看到标签,该标签元素用来指定要测试的应用程序,自动将com.example.hellobugben设为targetPackage对象,代码清单如下:
&?xml version="1.0" encoding="utf-8"?&///apk/res/android"
package="com.example.hellobugben.test"
android:versionCode="1"
android:versionName="1.0" &
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.hellobugben" /&
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" &
在标签中,android:name声明了测试框架,android:targetPackage指定了待测项目包名。
下面来看一下,如何用Instrumentation框架编写测试程序,代码如下:
package com.example.hellobugben.
import com.example.hellobugben.HelloBugbenA
import com.example.hellobugben.R;
import android.os.H
import android.text.TextP
import android.widget.TextV
import android.test.ActivityInstrumentationTestCase2;
public classHelloBugbenTestBaseextendsActivityInstrumentationTestCase2&HelloBugbenActivity&{
public HelloBugbenTestBase() {
super(HelloBugbenActivity.class);
HelloBugbenActivity helloB
private Handler handler = null;
private TextView textView1;
private TextView textView2;
String bugben_txt = "bugben";
Boolean bugben_bold = true;
Float bugben_sizeFloat = (float)20.0;
public void setUp() throws Exception{
super.setUp();
helloBugben = getActivity();
textView1 = (TextView)helloBugben.findViewById(R.id.textView1);
textView2 = (TextView)helloBugben.findViewById(R.id.textView2);
handler = new Handler();
public voidtearDown()throws Exception{
super.tearDown();
public void testSetTxt(){
new Thread(){
public voidrun(){
if (handler != null) {
handler.post(runnableTxt);
}.start();
String cmpTxtString = textView1.getText().toString();
pareToIgnoreCase(bugben_txt) == 0);
public void testSetBold(){
helloBugben.setTv1Bold(bugben_bold);
TextPaint tp = textView1.getPaint();
Boolean cmpBold = tp.isFakeBoldText();
assertTrue(cmpBold);
publicvoidtestSetSize(){
helloBugben.setTv2Size(bugben_sizeFloat);
Float cmpSizeFloat = textView2.getTextSize();
pareTo(bugben_sizeFloat) == 0);
Runnable runnableTxt = new Runnable() {
publicvoidrun(){
helloBugben.setTxt(bugben_txt);
上述代码中,我们首先引入import android.test.ActivityInstrumentationTestCase2。其次让HelloBugbenTestBase继承自ActivityInstrumentationTestCase2这个类。接着在setUp()方法中通过getActivity()方法获取待测项目的实例,并通过textview1和textview2获取两个TextView控件。最后编写3个测试用例:控制文本设置测试testSetText()、字体加粗属性测试testSetBold、字体大小属性测试testSetSize()。这里用到的关键方法是Instrumentation API里面的getActivity()方法,待测的Activity在没有调用此方法的时候是不会启动的。
眼尖的小伙伴可能已经发现控制文本设置测试这里启用了一个新线程,这是因为在Android中相关的view和控件不是线程安全的,必须单独在新的线程中做处理,不然会报
android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views
这个错误。所以需要启动新线程进行处理,具体步骤如下:
1) 在setUp()方法中创建Handler对象,代码如下:
public void setUp() throws Exception{
super.setUp();
handler = new Handler();
2) 创建Runnable对象,在Runnable中进行控件文本设置,代码如下:
Runnable runnableTxt = new Runnable() {
public void run(){
helloBugben.setTxt(bugben_txt);
3) 在具体测试方法中通过调用runnable对象,实现文本设置,代码如下:
new Thread(){
public void run() {
if (handler != null) {
handler.post(runnableTxt);
}.start();
我们运行一下结果,结果截图如下:
可以看到3个测试用例结果运行正常。
可能有小伙伴要问,程序中为啥要继承ActivityInstrumentationTestCase2呢?我们先看一下ActivityInstrumentationTestCase2的继承结构:
java.lang.Object
junit.framework.Assert
junit.framework.TestCase
android.test.InstrumentationTestCase
android.test.ActivityTestCase
android.test.ActivityInstrumentationTestCase2
ActivityInstrumentationTestCase2允许InstrumentationTestCase. launchActivity来启动被测试的Activity。而且ActivityInstrumentationTestCase2还支持在新的UI线程中运行测试方法,能注入Intent对象到被测试的Activity中,这样一来,我们就能直接操作被测试的Activity了。正因为ActivityInstrumentationTestCase2有如此出众的有点,它才成功取代了比它早出世的哥哥:ActivityInstrumentationTestCase,成为了Instrumentation测试的基础。
Instrumentation测试框架实战
了解完Instrumentation的基本测试方法后,我们来看一下如何运用Instrumentation框架完成前文Monkey父子完成的自动化测试任务。
首先建立项目名为Bugben的Project,类名为MainActivity,代码如下:
package com.ringo.bugben
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.View
import android.view.View.OnClickListener
import android.widget.Button
import android.widget.EditText
import android.widget.RadioButton
public classMainActivityextendsActivity{
private EditText editText1 = null
private EditText editText2 = null
private RadioButton bold = null
private RadioButton
small = null
private Button button = null
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
editText1 = (EditText)findViewById(R.id.editText1)
editText2 = (EditText)findViewById(R.id.editText2)
button = (Button)findViewById(R.id.mybutton1)
bold = (RadioButton)findViewById(R.id.radioButton1)
small = (RadioButton)findViewById(R.id.radioButton3)
button.setOnClickListener(new OnClickListener(){
publicvoidonClick(View v){
Log.v("Ringo", "Press Button")
String isBold = bold.isChecked() ? "bold" : "notbold"
String wordSize = small.isChecked() ? "small" : "big"
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, OtherActivity.class)
intent.putExtra("text1", editText1.getText().toString())
intent.putExtra("text2", editText2.getText().toString())
intent.putExtra("isBold", isBold)
intent.putExtra("wordSize", wordSize)
startActivity(intent)
在建立一个名为OtherActivity的类,点击提交按钮后,跳转到这个界面,代码如下:
package com.ringo.bugben
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.text.TextPaint
import android.widget.TextView
public classOtherActivityextendsActivity{
private TextView textView2 = null
private TextView textView3 = null
Boolean bugben_bold = true
Boolean bugben_notbold = false
Float bugben_small_size = (float)20.0
Float bugben_big_size = (float)60.0
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
setContentView(R.layout.other)
textView2 = (TextView)findViewById(R.id.textView2)
textView3 = (TextView)findViewById(R.id.textView3)
Intent data = getIntent()
textView2.setText(data.getStringExtra("text1"))
textView3.setText(data.getStringExtra("text2"))
if (data.getStringExtra("isBold").equalsIgnoreCase("bold")) {
TextPaint tPaint = textView2.getPaint()
tPaint.setFakeBoldText(bugben_bold)
TextPaint tPaint = textView2.getPaint()
if (data.getStringExtra("wordSize").equalsIgnoreCase("small")) {
TextPaint tPaint = textView3.getPaint()
tPaint.setTextSize(bugben_small_size)
TextPaint tPaint = textView3.getPaint()
tPaint.setTextSize(bugben_big_size)
3.接下来需创建一个测试项目,命名为BugbenTestBase,选择要测试的目标项目为Bugben项目,然后点击Finish即可完成测试项目的创建。
在com.ringo.bugben.test包中添加BugbenTestBase这个类,类的代码如下:
package com.ringo.bugben.test
import com.ringo.bugben.MainActivity
import com.ringo.bugben.OtherActivity
import com.ringo.bugben.R
import android.app.Instrumentation.ActivityMonitor
import android.content.Intent
import android.os.SystemClock
import android.test.ActivityInstrumentationTestCase2
import android.text.TextPaint
import android.util.Log
import android.widget.Button
import android.widget.RadioButton
import android.widget.TextView
public class BugbenTestBase extends ActivityInstrumentationTestCase2&MainActivity&{
publicBugbenTestBase(){
super(MainActivity.class)
MainActivity mainActivity
OtherActivity otherActivity
private EditText txt1
private EditText txt2
private RadioButton bold
private RadioButton notbold
private RadioButton small
private RadioButton big
private Button subButton
private TextView textView1
private TextView textView2
String bugben_txt1 = "RingoYan"
String bugben_txt2 = "自动化测试"
Boolean bugben_bold = true
Boolean bugben_notbold = false
Float bugben_small_size = (float)20.0
Float bugben_big_size = (float)60.0
public void setUp() throws Exception{
super.setUp()
// 启动MainActivity
Intent intent = new Intent()
intent.setClassName("com.ringo.bugben", MainActivity.class.getName())
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
mainActivity = (MainActivity)getInstrumentation().startActivitySync(intent)
// 通过mainActivity的findViewById获取MainActivity界面的控件
txt1 = (EditText)mainActivity.findViewById(R.id.editText1)
txt2 = (EditText)mainActivity.findViewById(R.id.editText2)
bold = (RadioButton)mainActivity.findViewById(R.id.radioButton1)
notbold = (RadioButton)mainActivity.findViewById(R.id.radioButton2)
small = (RadioButton)mainActivity.findViewById(R.id.radioButton3)
big = (RadioButton)mainActivity.findViewById(R.id.radioButton4)
subButton = (Button)mainActivity.findViewById(R.id.mybutton1)
publicvoidtearDown()throws Exception{
super.tearDown()
// 提交测试
public void testSubmit()throws Throwable{
Log.v("Ringo", "test normal submit")
// 添加一个监听器,监视OtherActivity的启动
ActivityMonitor bugbenMonitor = getInstrumentation().addMonitor(
OtherActivity.class.getName(), null, false)
// 要操作待测程序的UI必须在runTestOnUiThread中执行
runTestOnUiThread(new Runnable() {
publicvoidrun(){
// TODO Auto-generated method stub
txt1.setText(bugben_txt1)
txt2.setText(bugben_txt2)
bold.setChecked(true)
big.setChecked(true)
// 等待500毫秒,避免程序响应慢出错
SystemClock.sleep(500)
// 点击提交按钮
subButton.performClick()
// 从ActivityMonitor监视器中获取OtherActivity的实例
otherActivity = (OtherActivity)getInstrumentation().waitForMonitor(bugbenMonitor)
// 获取的OtherActivity实例应不为空
assertTrue(otherActivity != null)
textView1 = (TextView)otherActivity.findViewById(R.id.textView2)
textView2 = (TextView)otherActivity.findViewById(R.id.textView3)
assertEquals(bugben_txt1, textView1.getText().toString())
assertEquals(bugben_txt2, textView2.getText().toString())
TextPaint tp = textView1.getPaint()
Boolean cmpBold = tp.isFakeBoldText()
assertTrue(cmpBold)
Float cmpSize = textView2.getTextSize()
assertTrue(cmpSize.compareTo(bugben_big_size) == 0)
// 等待500毫秒,避免程序响应慢出错
SystemClock.sleep(5000)
上述代码中,共包括自动化测试需要进行的5个步骤,具体如下:
(1) 启动应用:通过Intent对象setClassName()方法设置包名和类名,通过setFlags()方法设置标示,然后通过getInstrumentation()的startActivitySync(intent)来启动应用,进入到主界面。
(2) 编辑控件:在Android中相关的view和控件不是线程安全的,所以必须单独在新的线程中做处理。代码中我们在runTestOnUiThread(new Runnable())中的run()方法中执行的。
(3) 提交结果:点击提交按钮进行结果的提交,由于点击按钮也属于界面操作,所以也需要在runTestOnUiThread这个线程中完成。
(4) 界面跳转:这是Instrumentation自动化测试中最需要注意的一个点,特别是如何确认界面已经发生了跳转。在Instrumentation中可以通过设置Monitor监视器来确认。代码如下:
ActivityMonitor bugbenMonitor = getInstrumentation().addMonitor(
OtherActivity.class.getName(), null, false);
然后通过waitForMonitor方法等待界面跳转。
otherActivity = (OtherActivity)getInstrumentation().waitForMonitor(bugbenMonitor);
若返回结果otherActivity对象不为空,说明跳转正常。
(5) 验证显示:跳转后,通过assertEquals()或assertTrue()方法来判断显示的正确性。
我们运行一下结果,结果截图如下:
Instrumentation工具总结
Instrumentation框架的整体运行流程图如下:
Instrumentation是基于源码进行脚本开发的,测试的稳定性好,可移植性高。正因为它是基于源码的,所以需要脚本开发人员对Java语言、Android框架运行机制、Eclipse开发工具都非常熟悉。Instrumentation框架本身不支持多应用的交互,例如测试“通过短信中的号码去拨打电话”这个用例,被测应用将从短信应用界面跳转到拨号应用界面,但Instrumentation没有办法同事控制短信和拨号两个应用,这是因为Android系统自身的安全性限制,禁止多应用的进程间相互访问。
法宝4:终极自动化测试框架——UIAutomator
鉴于Instrumentation框架需要读懂项目源码、脚本开发难度较高并且不支持多应用交互,Android官网亮出了自动化测试的王牌——UIAutomator,并主推这个自动化测试框架。该框架无需项目源码,脚本开发效率高且难度低,并且支持多应用的交互。当UIAutomator面世后,Instrumentation框架回归到了其单元测试框架的本来位置。
下面我们来看一下这个框架是如何运行起来的。首先运行位于Android SDK的tools目录下的uiautomatorviewer.bat,可以看到启动界面。
启动bugben应用后,点击
这个图标来采集手机的界面信息,如下所示:
我们可以看到,用uiautomatorviewer捕捉到的控件非常清晰,很方便元素位置的定位。在UIAutomator框架中,测试程序与待测程序之间是松耦合关系,即完全不需要获取待测程序的控件ID,只需对控件的文本(text)、描述(content-desc)等信息进行识别即可。
在进行实战之前,我们先看一下UIAutomator的API部分,由以下架构图组成。
下面来看下如何利用该框架创建测试工程。
1. 创建BugBenTestUIAuto项目,右键点击项目并选择Properties & Java Build Path
点击Add Library & Junit & Junit3,添加Junit框架。
点击Add External Jar,并导航到Android SDK目录下,选择platforms目录下面的android.jar和UIAutomator.jar两个文件。
2. 设置完成后,可以开始编写项目测试的代码,具体如下:
package com.ringo.bugben.test
import java.io.File
import com.android.uiautomator.core.UiDevice
import com.android.uiautomator.core.UiObject
import com.android.uiautomator.core.UiObjectNotFoundException
import com.android.uiautomator.core.UiSelector
import com.android.uiautomator.testrunner.UiAutomatorTestCase
public class BugBenTest extends UiAutomatorTestCase{
public BugBenTest (){
String bugben_txt1 = "xiaopangzhu"
String bugben_txt2 = "bugben"
String storePath = "/data/local/tmp/displayCheck.png"
String testCmp = "com.ringo.bugben/.MainActivity"
public void setUp ()throws Exception{
super.setUp()
// 启动MainActivity
startApp(testCmp)
private int startApp(String componentName){
StringBuffer sBuffer = new StringBuffer()
sBuffer.append("am start -n ")
sBuffer.append(componentName)
int ret = -1
Process process = Runtime.getRuntime().exec(sBuffer.toString())
ret = process.waitFor()
catch (Exception e) {
// TODO: handle exception
e.printStackTrace()
return ret
public void tearDown()throws Exception{
super.tearDown()
// 提交文字测试
public void testSubmitTest() throws UiObjectNotFoundException{Log.v
("Ringo", "test change the textview's txt and size by UIAutomator")
// 获取文本框1并赋值
UiObject bugben_et1 = new UiObject(new UiSelector().text("Ringoyan"))
if(bugben_et1.exists() && bugben_et1.isEnabled()){
bugben_et1.click()
bugben_et1.setText(bugben_txt1)
Log.e("Ringo", "can not find bugben_et1")
// 获取文本框2并赋值
UiObject bugben_et2 = new UiObject(new UiSelector().text("18888"))
if(bugben_et2.exists() && bugben_et2.isEnabled()){
bugben_et2.click()
bugben_et2.setText(bugben_txt2)
Log.e("Ringo", "can not find bugben_et2")
// 获取加粗选项并赋值
UiObject bugben_bold = new UiObject(new UiSelector().text("加粗"))
if(bugben_bold.exists() && bugben_bold.isEnabled()){
bugben_bold.click()
Log.e("Ringo", "can not find 加粗")
// 获取大号字体选项并赋值
UiObject bugben_big = new UiObject(new UiSelector().text("大号"))
if(bugben_big.exists() && bugben_big.isEnabled()){
bugben_big.click()
Log.e("Ringo", "can not find 大号")
// 获取提交按钮并跳转
UiObject subButton = new UiObject(new UiSelector().text("提交"))
if(subButton.exists() && subButton.isEnabled()){
subButton.clickAndWaitForNewWindow()
Log.e("Ringo", "can not find 提交")
// 获取文本框1文本
UiObject bugben_tv1 = new UiObject(new UiSelector()
.className("android.widget.LinearLayout")
.childSelector(new UiSelector()
.className("android.widget.FrameLayout")
.index(1))
.childSelector(new UiSelector()
.className("android.widget.TextView")
.instance(0)))
// 获取文本框2文本
UiObject bugben_tv2 = new UiObject(new UiSelector()
.className("android.widget.LinearLayout")
.index(0).childSelector(new UiSelector()
.className("android.widget.FrameLayout")
.index(1))
.childSelector(new UiSelector()
.className("android.widget.TextView")
.instance(1)))
if (bugben_tv1.exists() && bugben_tv1.isEnabled()) {
assertEquals(bugben_txt1, bugben_tv1.getText().toString())
Log.e("Ringo", "can not find bugben_tv1")
if (bugben_tv2.exists() && bugben_tv2.isEnabled()) {
assertEquals(bugben_txt2, bugben_tv2.getText().toString())
Log.e("Ringo", "can not find bugben_tv2")
File displayPicFile = new File(storePath)
Boolean displayCap = UiDevice.getInstance().takeScreenshot(displayPicFile)
assertTrue(displayCap)
上述代码中,我们首先引入import com.android.uiautomator.testrunner.UiAutomatorTestCase类,并让BugbenTest继承自UiAutomatorTestCase这个类。同样,我们来看下UiAutomator框架下自动化测试进行的5个步骤,具体如下:
(1) 启动应用:于Instrumentation框架不同,UiAutomator是通过命令行进行应用启动的。
am start –n 包名/.应用名
(2) 编辑控件:UiAutomator框架中,控件的编辑相对简单,直接通过UiSelector的text()方法找到对应的控件,然后调用控件的setText()即可对其赋值。
UiObject bugben_et1 = new UiObject(new UiSelector().text("Ringoyan"))
if(bugben_et1.exists() && bugben_et1.isEnabled()){
bugben_et1.click()
bugben_et1.setText(bugben_txt1)
(3) 提交结果:点击提交按钮进行结果的提交,也是通过UiSelector的text()方法找到对应的控件,然后调用clickAndWaitForNewWindow()方法来等待跳转完成。
UiObject subButton = new UiObject(new UiSelector().text("提交"));
if(subButton.exists() && subButton.isEnabled()){
subButton.clickAndWaitForNewWindow();
(4) 界面跳转元素获取:用uiautomatorviewer捕捉跳转后的控件,例如捕捉跳转后的文本1:
UiObject bugben_tv1 = new
UiObject(new UiSelector()
.className("android.widget.LinearLayout")
.childSelector(new UiSelector()
.className("android.widget.FrameLayout")
.index(1))
.childSelector(new UiSelector()
.className("android.widget.TextView")
.instance(0)))
(5) 验证显示:跳转后,通过assertEquals()或assertTrue()方法来判断显示的正确性。
if (bugben_tv1.exists() && bugben_tv1.isEnabled())
{assertEquals(bugben_txt1, bugben_tv1.getText().toString())
至此核心代码部分已编写完毕。UIAutomator有一个麻烦之处:没法通过Eclipse直接编译。可以借助于一系列命令行进行编译,详细步骤如下:
1) 通过如下命令创建编译的build.xml文件
android create uitest-project –n BugBenTestUIAuto –t 1 –p "E:\workspace\BugBenTestUIAuto"
创建完成后,刷新BugBenTestUIAuto项目,得到如下图:
打开build.xml会看到,编译项目名为BugBenTestUIAuto。
2) 设置SDK的路径:
set ANDROID_HOME="E:\sdk\android-sdk-windows"
3) 进入测试目录,然后进行编译:
cd /d E:\workspace\android\BugBenTestUIAutoant build
编译完成后,再次刷新项目,你将看到BugBenTestUIAuto.jar包生成在bin目录下了,如图:
4) 将生成的jar包推送到手机端
adb push E:\workspace\android\BugBenTestUIAuto\bin\BugBenTestUIAuto.jar /data/local/tmp/
5) 在手机端运行自动化脚本,即jar包中的测试用例,命令行如下:
adb shell uiautomator runtest BugBenTestUIAuto.jar -c com.ringo.bugben.test.BugBenTest
运行结果如下,返回OK表示运行成功。
6) 最后,将运行后的截图从手机端拷贝到PC上
adb pull /data/local/tmp/displayCheck.png E:\workspace\android\BugBenTestUIAuto
至此整个代码就编译和运行完毕,如果觉得调试时反复修改和编译比较麻烦,可以将以上脚本写成一个批处理文件。
UIAutomator工具总结
相比于Instrumentation工具,UIAutomator工具更灵活一些,它不需要项目源码,拥有可视化的界面和可视化的树状层级列表,极大降低了自动化测试脚本开发的门槛。并且UIAutomator支持多应用的交互,弥补了Instrumentation工具的不足。但UIAutomator难以捕捉到控件的颜色、字体粗细、字号等信息,要验证该类信息的话,需要通过截图的方式进行半自动验证。同时,UIAutomator的调试相比Instrumentation要困难。所以在平时的测试过程中,建议将两者结合起来使用,可达到更佳的效果!
关于腾讯WeTest ()
腾讯WeTest是腾讯游戏官方推出的一站式游戏测试平台,用十年腾讯游戏测试经验帮助广大开发者对游戏开发全生命周期进行质量保障。腾讯WeTest提供:适配兼容测试;云端真机调试;安全测试;耗电量测试;服务器性能测试;舆情监控等服务。
本文已收录于以下专栏:
相关文章推荐
无线客户端的发展很快,特别针对是android和ios两款无线操作系统的客户端应用,相应的测试工具也应运而生,这里主要给大家介绍一些针对iPhone
App的自动化测试工具。
  首先,我们把这...
/punkisnotdead/p/5103323.html
在日常的开发中,尤其是app开发,因为不像web端那样 出错以后可以热...
网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。
nick说过,没个人都要有一套自己的测试方法,针对模块有一套自己的解决思路,之后一直在寻找。这就是个人的测试分析思路,
元素分析:
这里之前一篇只分析了静态的元素,经过工作中实践后应...
Android 的 monkey test 工具提供了 -f scriptfile 参数,可以指定 test 脚本,然而翻遍了 Android 的网站也没有找到这个脚本的文档,最终只在 monkey ...
虽然说我们知道Monkey是monkey.jar相手机发送伪随机事件流,但是通过对monkey的API研究发现,我们可以通过-f这个参数来实现monkey执行脚本。
在monkey的源码中我...
 移动APP的UI自动化测试长久以来一直是一个难点,难点在于UI的”变”, 变化导致自动化用例的大量维护。从分层测试的角度,自动化测试应该逐层进行。最大量实现自动化测试的应该是单元测试,最...
作者:Ringoyan,腾讯测试开发工程师。先后为植物大战僵尸Online,糖果传奇等游戏担任测试经理,其负责的“我叫MT2”测试项目曾获腾讯互动娱乐精品文化奖银奖。目前担任腾讯WeTest测试经理。...
Robot Framework+Selenium搭建自动化测试环境
1      安装包
Python—python解释器,安装后可以运行python程序。
Ez_setup--第三方pyt...
他的最新文章
讲师:王渊命
讲师:蔡栋
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 公路水运工程试验app 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信