移动端测试
1. Android应用测试范围
- 测试范围
- 功能测试
- UI方面
- 陈故乡功能方面
- 稳定性测试
- 适配测试
- 分辨方面
- 手机交互方面
- 不同版本系统
- 不同厂家定制系统
- 性能测试
- 安全测试
- 功能测试
- 安装卸载测试
- 主要测试点 :
- 生成APK文件在真机上可以安装卸载
- Android手机端的通用安装工具 : 手机助手等工具可以正常安装卸载
- 检查软件是否能正常安装、运行、卸载
- 安装、卸载、更新错误报告
- 其他辅助信息 : 安装路径,内存空间大小的使用等
- 主要测试点 :
- 性能测试
- 偏重客户端测试CPU,MEM,流量,电量以及客户端在不同网络环境下响应速度等等
- 大数据的测试 : 主要在特定环境下,客户端一次性更新大量的日数据,客户端能否正常处理,分为三种情况:
- 客户端第一次使用,第一次就更新大量数据
- 客户端在平时更新中,更新大量的数据
- 客户端已经在手机本地下载很多数据后,再次更新大量数据
- 极限测试 :在各种边界压力情况下 (如电池、储存、网速等),验证App是否能正确响应
- 响应能力测试 : 测试App中的各类操作是否满足用户想用时间要求
- 压力测试 : 反复/长期操作下,系统资源是否占用异常等
- 电量与流量测试
- 内存泄漏测试
- 外网与场景测试
- 安全性测试
- 软件的权限 – 在对手机进行使用的过程中,是否对联系人,以及手机信息能够确保安全,像在连接网络等出现的额外扣费,以及后期出现的新增风险等
- 主要针对检测APP的用户授权级别,数据泄露,非法授权访问等,像对App的输入有效性校验,认证,授权,敏感数据存储,数据加密等方面进行检测,以及后期发现潜在的安全问题
- UI测试
- 测试用户使用的界面(如菜单、对话框、窗口和其他控件)布局是否满足客户要求,页面是否美观,文字,图片组合是否完美,操作是否流畅等。
- 支付测试
- 支付结果的测试,数据库查询
- 请求报文是否加密
- 不同场景的支付
- 金额足够、金额不足、重复支付、无网支付、弱网支付、同账号多平台一起支付、余额宝微信信用卡等多种支付方式、不同支付方式的组合、密码正确/错误,支付上限等情况
- 客户端数据库测试
- 一般的增删改查测试
- 当表不存在时是否自动创建,当数据库表被删除后能否再自建,数据是否能自动从服务器中获取并保存
- 当业务需要从客户端取数据时,检查客户端数据存在时,app数据是否能自动从客户端数据中取出,还是仍然会从服务器端获取,检查客户端数据不存在时,app数据能否自动从服务器端获取到并保存到客户端
- 当业务对数据进行了修改、删除后,客户端和服务端是和否会有相应的更新
- 登录模块
- 当用户输入用户名或密码错误时界面是否有提示性信息
- 当用户退出登录后,下次再开启app时,能否直接进入登录页面
- 当能够自动登录app,要做到是否能自动登录成功而且保证数据操作无误
- 当重新设置密码后,再一次登录是否对数据的有效性进行检测
- 当重新设置密码后,再一次去登录时是否对数据的有效性进行检测
- 再去切换账号时,检验登录的信息是否做到及时改变、当账号登录多个手机时,是否会登出其他设备,并且给出相应的提示信息
- 离线状态
- 离线的应用会在本地的客户端做一些缓存的数据
- 对于一些程序,在登录后,在没网络的情况下是否可以浏览本地数据
- 无网时,不能获取最新数据时,给出提示信息
- 前后台切换时,是否正常查看信息
- 离线后再次连接网络。对数据更新
- 消息推送
- 更新模块
2. Android基础
-
Android操作系统简介
- Android系统来源和发展历史
-
Android系统结构和原理
- Android系统结构
- 应用程序层
- 应用程序框架层
- 函数库
- Linux内核
- Android系统结构
-
Android测试常用术语
- 系统碎片化 : 指整个安卓平台的差异化越来越大
- 屏幕尺寸
- 分辨率
- 像素
- 网络制式
-
Android应用的构成
- Android四大组件
- Activity - 活动
- 指与用户交互的界面
- Service - 服务
- 后台运行的服务,Service承担着大部分的数据工作
- ContentProvider - 内容提供者
- 主要用来存取数据
- BroadcastReceiver - 广播接收器
- 发送和接收消息
- Activity - 活动
- Android四大组件
-
Android测试环境搭建
-
Android自带模拟器
-
Android Studio的安装
-
官网下载Android Studio SDK :
http://tools.android-studio.org/index.php/sdk
- 运行解压后的
SDK Manager.exe
安装需要的环境插件
- 运行解压后的
-
解压到准备好的目录
-
配置环境变量
1. 配置ANDROID_HOME : 新建系统变量: 变量名:ANDROID_HOME 变量值: E:\Android\android-sdk-windows 2.配置Path变量 : 新建变量 : %ANDROID_HOME% 新建变量 : %ANDROID_HOME%\platforms 新建变量 : %ANDROID_HOME%\platform-tools 新建变量 : %ANDROID_HOME%\tools 新建变量 : %ANDROID_HOME%\build-tools\29.03
-
-
-
第三方模拟器
- 夜神
- 雷电
- 腾讯手游
- …
-
-
ADB简介
- ADB简介
- adb工具即Android Debug Bridge(安卓调试桥) tools,它是一个命令行窗口,用于通过电脑端与模拟器或真实设备交互,包括三大内容
- 电脑上运行的客户端
- 在用于开发的机器上作为后台进程运行的服务器
- 一个以后台进程的形式运行于模拟器或设备上的守护程序
- adb工具即Android Debug Bridge(安卓调试桥) tools,它是一个命令行窗口,用于通过电脑端与模拟器或真实设备交互,包括三大内容
- 常用ADB命令
- 关闭和启动adb服务
adb kill-server
关闭adb服务adb start-server
启动adb服务
- 查看设备连接情况
adb devices
- 查看当前连接的设备,连接到计算机的Android设备或模拟器将会列表显示
- 多个设备指定设备操作
adb [-d|-e|-s<serial Number>] <command>
- d: 真机 (多个设备只有一个是真机时适用)
- e: 模拟器 (多个设备只有一个是模拟器时适用)
- s:序列号
- 例如 :
adb -s emulator-5556 install ES.apk
- 安装和卸载apk
- adb install apk文件路径 :
adb install E:/ES.apk
- adb uninstall 软件名 :
adb uninstall cn.androidfun.apkfetch
- adb uninstall -k 软件名 : 卸载程序但保留其配置和缓存文件
aapt dump badging apk路径
: 查看当前安装包的包名aapt dump badging E:/1.apk
- adb install apk文件路径 :
- 上传和下载文件
adb push <本地路径> <远程路径>
: 上传adb push E:/1.txt /sdcard/1.txt
adb pull <远程路径> <本地路径>
: 下载adb shell
: 进入Android命令行
- 日志Logcat的操作
adb logcat
: 查看日志adb logcat > E:/log.txt
: 导出日志
- 其他命令
android sdk
: 打开sdk管理界面android avd
: 打开android原生模拟器android list avd
: 列出android原生模拟器
- 关闭和启动adb服务
- ADB简介
Monkey测试
Monkey测试是Android自动化测试的一种手段
Monkey测试本身非常简单,即模拟用户的按键输入,触摸屏输入,手势输入等,观察设备多长时间出现异常
-
Monkey测试的特点
-
只能对应用程序包,有一定局限性
-
Monkey测试在使用过程中对事件的操作时随机的,不能特意指定
-
基于Android测试开发环境
-
Monkey使用过程
-
使用模拟器或真机,注意要在DOS里面使用adb devices验证
-
找到app应用程序的包名,
-
写出Monkey命令进行测试
-
格式 :
adb shell monkey [参数]
:例adb shell monkey 1000
(允许启动手机里的所有app,随机操作1000次)- 参数:
-p
:允许启动app的包名
- 参数:
-
adb shell monkey -p 包名 1000 > E:/log.txt
: 将运行日志导出 -
-v 操作日志记录
- -v :Level0(缺省值)除启动提示、测试完成提示和最终结果之外,提供较少信息
- -v -v : Level1 提供较为详细的测试信息,如猪哥发送到Activity的事件
- -v -v -v : Level2 提供更加详细的设置信息,如测试中被选中的活未被选中的Activity
- 示例代码 :
adb shell monkey -p 包名 -v -v -v 1000
-
分析Monkey命令结果
- 查看MOnkey命令运行结果,找出出错的地方,比如一些关键词error
- 查看monkey出错前的动作事件touch,这时可以选择手动执行该动作
- 注意switch关键词后面的信息:异常或者报错大部分就是在该关键词之后
Monkey测试的目的就在于找到“程序崩溃问题”和“应用程序未响应ANR”,要找出这两个问题,可以在log日志中搜索关键词 “exception” 和“ANR”
-
Monkey的关闭
-
Monkey在运行过程中就算PC拔掉USB数据线,也会继续进行,但是在某些情况下,需要我们把Monkey关掉,需要强制停止正在运行的Monkey
adb shell
ps|grep moneky
kill pid
-
-
-
Android常用布局及控件
- Android常用布局
- LinearLayout 线性布局
- RelativeLayout 相对布局
- GridLayout 网格布局
- Android常用控件
- TextView 文本视图
- EditText 文本编辑框
- Button 按钮
- RedioButton 单选按钮
- CheckBox 多选框
- Spinner 下拉列表
BMI体质指数计算器小app编写
-
activity_main.xml代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/two" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="BMI计算器" android:textSize="40sp" /> <!-- 身高输入框 --> <LinearLayout android:layout_width="match_parent" android:layout_height="46dp" android:layout_marginTop="30dp" android:gravity="center" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="bottom" android:text="身高:" android:textSize="20sp" /> <!-- 身高输入框 --> <EditText android:id="@+id/edit_h" android:layout_width="100dp" android:layout_height="match_parent" android:inputType="number"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="bottom" android:text="cm" android:textSize="20sp" /> </LinearLayout> <!-- 体重 --> <LinearLayout android:layout_width="match_parent" android:layout_height="46dp" android:layout_marginTop="10dp" android:gravity="center" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="bottom" android:text="体重:" android:textSize="20sp" /> <!-- 体重输入框 --> <EditText android:id="@+id/edit_w" android:layout_width="100dp" android:layout_height="match_parent" android:inputType="number"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="bottom" android:text="kg" android:textSize="20sp" /> </LinearLayout> <!-- 两个按钮 --> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal" android:gravity="center" android:layout_marginTop="20dp"> <Button android:id="@+id/btn_enter" android:layout_width="60dp" android:layout_height="40dp" android:text="计算" android:textSize="15sp" /> <Button android:id="@+id/btn_cls" android:layout_width="60dp" android:layout_height="40dp" android:text="清空" android:textSize="15sp"/> </LinearLayout> <!-- 标准图片 --> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/bmi" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp"/> </LinearLayout>
-
MainActivity.java代码
package com.ele.bmi; import java.text.DecimalFormat; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { //定义身高输入框 private EditText mEditH; //定义体重输入框 private EditText mEditW; //定义计算按钮 private Button mButE; //定义清空按钮 private Button mButC; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定id mEditH = (EditText) findViewById(R.id.edit_h); mEditW = (EditText) findViewById(R.id.edit_w); mButE = (Button) findViewById(R.id.btn_enter); mButC = (Button) findViewById(R.id.btn_cls); // 清空按钮功能实现 mButC.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // 清空输入框内容 mEditH.setText(""); mEditW.setText(""); } }); // 实现计算按钮 mButE.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // 先判断身高是否为空 if(mEditH.getText().toString().equals("")) { mEditH.setError("请输入身高!!!"); return; } // 判断体重是否为空 if(mEditW.getText().toString().equals("")) { mEditW.setError("请输入体重!!!"); return; } // 获取身高体重 double h = Double.parseDouble(mEditH.getText().toString()); double w = Double.parseDouble(mEditW.getText().toString()); // 计算bmi值 double mbmi = w/((h/100)*(h/100)); DecimalFormat df=new DecimalFormat("0.00"); String bmi = df.format(mbmi); // 跳转页面 Intent intent=new Intent(MainActivity.this,NextActivity.class); // 把bmi值传到下一个页面 intent.putExtra("BMI", bmi); startActivity(intent); // Toast.makeText(MainActivity.this, bmi, Toast.LENGTH_LONG).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
-
activity_next.xml代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/three" android:orientation="vertical" > <TextView android:id="@+id/text_bmi" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:gravity="center" android:text="测试1" android:textSize="30sp" android:textColor="#ffffff"/> <TextView android:id="@+id/text_tishi" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:gravity="center" android:text="测试2" android:textColor="#d04c77" android:textSize="30sp" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="100dp" android:src="@drawable/bmi" /> </LinearLayout>
-
NextActivity.java代码
package com.ele.bmi; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; public class NextActivity extends Activity { private TextView mTextView; private TextView tishiTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_next); // 定位BMI文字 mTextView = (TextView) findViewById(R.id.text_bmi); // 定位提示文字 tishiTextView = (TextView) findViewById(R.id.text_tishi); // 接收主界面传来的BMI值 Intent intent = getIntent(); String bmi = intent.getExtras().getString("BMI"); Double mbmi=new Double(bmi); // 把bmi值设置到TextView中 mTextView.setText("BMI:"+bmi); if (mbmi<=18.4) { Toast.makeText(NextActivity.this, "就不能多吃点吗??????", Toast.LENGTH_LONG).show(); tishiTextView.setText("就不能多吃点吗??????"); } else if(mbmi>18.5 && mbmi<=23.9) { Toast.makeText(NextActivity.this, "您这个身材也忒棒啦!", Toast.LENGTH_LONG).show(); tishiTextView.setText("您这个身材也忒棒啦!"); } else if(mbmi>23.9 && mbmi<27.9) { Toast.makeText(NextActivity.this, "过重了啊,注意少吃点!", Toast.LENGTH_LONG).show(); tishiTextView.setText("过重了啊,注意少吃点!"); } else{ Toast.makeText(NextActivity.this, "宁是猪吗???", Toast.LENGTH_LONG).show(); tishiTextView.setText("宁是猪吗???"); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.next, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
appium基础
-
appium是一个自动化测试开源工具,支持iOS平台和Android平台上的原生应用,web应用和混合应用
getMenuInflater().inflate(R.menu.next, menu);
return true;
}@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
appium基础
- appium是一个自动化测试开源工具,支持iOS平台和Android平台上的原生应用,web应用和混合应用
- appium是跨平台的,可以在OSX,Windows及Linux系统上运行