测试着实很重要。

一个应用发布前,测试阶段不可忽视。测试包括自动化测试和人工测试,本文总结的是如何进行自动化测试。

基本概念

黑盒测试与白盒测试

(摘自“百度百科”)

白盒测试:是通过程序的源代码进行测试而不使用用户界面。这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条件等等中的缺点或者错误,进而加以修正。

黑盒测试:又被称为功能测试、数据驱动测试或基于规格说明的测试,是通过使用整个软件或某种软件功能来严格地测试, 而并没有通过检查程序的源代码或者很清楚地了解该软件的源代码程序具体是怎样设计的。测试人员通过输入他们的数据然后看输出的结果从而了解软件怎样工作。

黑盒测试着重测试软件功能。黑盒测试并不能取代白盒测试,它是与白盒测试互补的测试方法,它很可能发现白盒测试不易发现的其他类型错误。

冒烟测试

冒烟测试,是对软件基本的功能进行测试,测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本的功能正常,保证软件系统能跑的起来,可以进行后续的正式测试工作。

 

测试流程

(摘自 Android测试流程)

android 测试概念 什么是安卓测试_android 测试概念

一、 Monkey测试(冒烟测试)(使用monkey测试工具进行操作)
1. APP的安装、卸载
2. APP随机操作测试(APP压力测试)
二、 安装卸载测试
1. 使用测试真机进行APP的安装与卸载
三、 升级测试(APP的在线升级安装及使用测试)
目的:
1. 验证签名是否一致
2. 跨版本升级是否正常
四、 功能测试
1. 功能逻辑测试
2. 功能点测试(单元测试)
3. 关联性测试(集成测试)
五、 自动化测试
1. monkeyrunner编写python脚本测试(可使用小萝贝、按键精灵代替)
六、联机调试测试
1. 使用Android Studio进行Android Debug真机调试
2. 通过Logcat记录每一步操作,定位错误代码
七、稳定性测试
1. 交互性测试
2. 异常性测试(手机断电、断网情况)
八、手机流量、电量、内存测试
1. 测试机使用监控软件观察APP使用所耗的流量
2. 测试机使用监控软件观察APP耗电量
3. 测试机使用监控软件观察APP占用内存情况(不能泄露内存) 
九、性能测试(Loadrunner)
1. 接口测试
2. 服务器压力测试
十、适配性测试(兼容性测试)(可使用testin云测试)
1. 分辨率
2. 系统版本
3. 厂商定制系统
4. 屏幕尺寸 
十一、界面易用性测试
1. 界面与交互测试(交互规范、用户体验、易用性等)
2. 可用性测试(可用性强、操作简单、出错率低、完成任务时间短等)
十二、外网测试
1.使用WIFI和手机网络2G/3G/4G网络测试APP

 

测试工具

(以下仅简单介绍,详情请查看原博客以及相应参考资料。本部分摘自:Android 程序员必须掌握的三种自动化测试方法)

一、Monkey 

详细请点击:参考

这个工具是最简单的,可用来做压力测试(就是乱点)。非常简单 但是作用也非常有限。不过可以极大帮助你 找出你app的一些隐藏极深的bug。

二、MonkeyRunner

详细请点击:参考

就是python脚本测试android,需要从com.android.monkeyrunner文件中导入相应的包。

三、UiAutomator

详细请点击:参考

有人认为是所有android 程序员都必须要掌握的,有了这个强大的工具,我们就可以负责任的对自己的代码说没问题。此工具 能模拟几乎所有对android设备的操作。代码也非常简单,全部都是java代码,并且android的api 几乎都能够使用。比android studio 自带的ApplicationTestCase 好用。(注意:不支持Hybird App、WebApp)

四、Testin

云测试,可用来做兼容性测试。

五、其他

Appium:功能比较强大。支持Hybird App、Web App等,属于黑盒测试工具。

Instrumentation:很早之前Google提供的框架,功能还行,优势在于支持早期系统。

Robolectric:主流的单元测试框架之一,可直接运行与JVM 上。

JUnit和AndroidTest:Android Studio自带的测试框架(前者是Java单元测试框架)(测试代码不会被打包)。

 

测试示例

(感谢:Android 进阶之自动化测试 UIAutomator

本人某个APP的测试代码如下(采用UiAutomator)(其实这个测试是为了查看最终的数据分布特征):

import android.content.Context;
import android.content.Intent;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiAutomatorTestCase;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;

public class MyAndroidTest extends UiAutomatorTestCase {
    String[] lastName = {"赵", "钱", "孙", "李", "周", "吴", "郑", "王"};
    String[] firstName1= {"方", "法", "行", "延", "迟", "操", "作", "式", "待", "相", "当"};
    String[] firstName2= {"隐", "来", "启", "动", "某", "多", "线", "程", "断", "点", ""};
    int x,y,z;

    @Override
    protected void setUp() throws Exception {
        /*
        super.setUp();
        */
    }

    public void testMain() throws UiObjectNotFoundException {

        UiDevice mDevice = getUiDevice();
        Context context = getInstrumentation().getContext();
        Intent intent = context.getPackageManager()
                .getLaunchIntentForPackage("com.fanjin.rctrandom");
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        // Clear out any previous instances
        context.startActivity(intent);
        mDevice.wait(Until.hasObject(By.pkg("com.fanjin.rctrandom").depth(0)),1000);

        int i;
        for (i=0; i<10; i++){
            UiObject main = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/buttonMain"));
            main.click();

            try{
                Thread.sleep(1000);
            }catch (Exception e){
                //
            }

            UiObject text1 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/editTextInput_name"));
            x=(int)(Math.random()*8);
            y=(int)(Math.random()*11);
            z=(int)(Math.random()*11);
            text1.setText(lastName[x]+firstName1[y]+firstName2[z]);

            UiObject radion21 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/radioButtonInput_21"));
            UiObject radion22 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/radioButtonInput_22"));
            x=(int)(Math.random()*2);
            if (x==0){
                radion21.click();
            } else{
                radion22.click();
            }

            UiObject text3 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/editTextInput_age"));
            x=(int)(Math.random()*20+60);
            text3.setText(x+"");

            UiObject radion41 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/radioButtonInput_41"));
            UiObject radion42 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/radioButtonInput_42"));
            x=(int)(Math.random()*2);
            if (x==0){
                radion41.click();
            } else{
                radion42.click();
            }

            UiObject radion51 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/radioButtonInput_51"));
            UiObject radion52 = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/radioButtonInput_52"));
            x=(int)(Math.random()*2);
            if (x==0){
                radion51.click();
            } else{
                radion52.click();
            }

            UiObject buttonInput = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/buttonInput2"));
            buttonInput.click();

            try{
                Thread.sleep(1000);
            }catch (Exception e){
                //
            }

            UiObject buttonConfirm = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/buttonConfirm2"));
            buttonConfirm.click();

            try{
                Thread.sleep(1000);
            }catch (Exception e){
                //
            }

            UiObject buttonResult = new UiObject(new UiSelector().resourceId("com.fanjin.rctrandom:id/buttonResult"));
            buttonResult.click();
        }

    }

UiAutomator确实很方便,可作为首选方法。