appium自动化中测试手机的管理与分配

       前段时间,参与开发了公司基于appium的UI自动化的工作。写此文章是为了把所用到的技术和思路做一个保留,以便日后查看方便。

       PS:1.本文章不涉及服务端代码。2.本文章所涉及的内容只支持Android手机,IOS不在这里说明。

            前段时间有幸参与了公司的UI自动化平台的工作, 对于运行自动化case前需要做一系列的准备工作(比如手机的管理工作等),由我来开发完成。因无人请教,所以开始做的时候也无思路,通过Googld或baidu了很多东西,一步一步的从理清思路到开发完成。废话不多说,直接上内容。

 本程序主要的功能是在运行自动化case之前,为平台提供一些手机的必要参数、手机状态及与自动化平台的交互功能。目前可承载能力如下:

1:自动识别手机的上线与下线。

2:实时获取手机的状态(用来判断当前手机是否为空闲状态)。

3:获取手机基本参数。

4:http网络协议的引入(用来与服务端进行通信)。

-----------------------------据说有分割线是为了好看???---------------------------------

下面来说下详细的实现步骤:

 因工程需要管理手机设备,监听手机上线与下线,而谷歌ddmlib库提供了解决方案。ddmlib是DDMS工具的核心,它封装了一系列对ADB功能的封装,在使用时,需引入ddmlib.jar、ddms.jar和ddmuilib.jar三个jar包,其中ddmlib.jar是核心功能,其它两个是为了查看其实现原理而引的(ddms.jar和ddmuilib.jar包不引入也不会影响其功能的使用)。对于ddmlib库,本工程只使用了很少一部分功能,ddmlib是个很强大的库,能做的事情很多,有兴趣的话可以自行Google其使用攻略。

代码实现:

public void init(boolean clientSupport) {
		AndroidDebugBridge.init(clientSupport);
		mAdbBridge = AndroidDebugBridge.createBridge("adb", false);
	}

            要使用ddmlib首先需要初始化AndroidDebugBridge或者说首先要create一个AndroidDebugBridge出来,并且通过getDevices()方法获得了一个设备类(IDevice),这样我们就可以正常的使用ddmlib库里面提供的东西了。

	public static void waitDevicesList(AndroidDebugBridge bridge) {
		int count = 0;
		while (bridge.hasInitialDeviceList() == false) {
			try {
				Thread.sleep(500);
				count++;
			} catch (InterruptedException e) {
			}
			if (count > 60) {
				System.err.print("主类等待获取设备超时");
				break;
			}
		}
	}

自动识别手机的上线与下线:

识别手机的上线与下线,用到了ddmlib库下的AndroidDebugBridge包(com.android.ddmlib.AndroidDebugBridge)。AndroidDebugBridge.IDeviceChangeListener此接口是可以监听到手机的上线与下线,只需实现此接口中的三个方法即可。deviceConnected(上线),deviceDisconnected(下线),deviceChanged(状态改变)。

@Override
	public void deviceConnected(IDevice device) {
		this.device = device;
		System.out.println("监听到设备ID为  =  " + device.getSerialNumber() + "的设备上线");
		serialNumberlist.add(device.getSerialNumber());
		PCount = serialNumberlist.size();
		System.out.println("所有线上手机的ID是  = " + serialNumberlist);
		testPcClient.writeFreePhone();
	}

  deviceConnected:实现deviceConnected()方法后,只要有手机插入就可监听到。上面我们已经获得了一个设备类(IDevice),通过getSerialNumber()就可以获得此设备的devicesID。我这里是只要监听到有设备上线,就add到一个list里方便管理,list.size()就是我当前所有线上手机的个数。

PS:这里与服务端交互的代码删除掉了,关于list的建立只是为了我本地调式方面而使用。当监听到有手机上线时,这时应该调用与服务端规定好的接口,此接口的作用就是用来告送服务器有手机上线了,并且把之前所拿到的手机基本信息一并发送过去(通过adb shell命令来获得手机信息,下面有详细解答),且由服务器记录同时标记此手机为空闲状态。而排重功能也由服务器来做(同一部手机不停的插拔),只要我这里监听到有上线,就会请求此接口。

@Override
	public void deviceDisconnected(IDevice device) {
		this.device = device;
		System.out.println("监听到设备ID为  =  " + device.getSerialNumber() + "的设备下线");
		serialNumberlist.remove(device.getSerialNumber());
		PCount = serialNumberlist.size();
		testPcClient.writeFreePhone();
	}

deviceDisconnected:实现deviceDisconnected()方法后,就可以监听到手机的下线,原理同手机上线。

PS:同样,这里也需调用与服务器规定好的接口,来通知服务器哪台手机下线,并由服务器更新当前手机状态。

@Override
	public void deviceChanged(IDevice device, int changeMask) {
		if (device.isOnline()) {
			System.out.println("Device change online " + device.getSerialNumber());
		} else {
			System.out.println("Device change offline " + device.getSerialNumber());
		}
	}

 

deviceChanged:可以监听到手机状态改变的接口。

实现了上面的三个接口后,我们就可以实时的获取到当前手机的个数以及每个手机devicesID,为自动分配手机打下了基础。为了使代码清晰简洁,以及使用便利的考虑,我们需要对AndroidDebugBridge类做一次封装,封装其初始化、注册监听器、移除监听器等等一系列方法。

    // 注册设备监听器
	public void addDeviceChangeListener(
		AndroidDebugBridge.IDeviceChangeListener listener) {
		AndroidDebugBridge.addDeviceChangeListener(listener);
	}
  
	// 移除监听器
	public void removeDeviceChangeListener(
		AndroidDebugBridge.IDeviceChangeListener listener) {
		AndroidDebugBridge.removeDeviceChangeListener(listener);
	}

 最后新建DeviceManager设备管理类(单例模式),通过该类可启动服务,注册监听器等。

public static DeviceManager getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new DeviceManager();
		}
		return INSTANCE;
	}

	// 启动
	public void start() {
		androidDebugBridgeWrapper = new AndroidDebugBridgeWrapper();
		deviceChangeListener = new DeviceChangeListener();
		androidDebugBridgeWrapper.addDeviceChangeListener(deviceChangeListener);
		androidDebugBridgeWrapper.init(false);
	}

	// 销毁
	public void destory() {
		if (androidDebugBridgeWrapper == null) {
			return;
		}
		androidDebugBridgeWrapper.removeDeviceChangeListener(deviceChangeListener);
		androidDebugBridgeWrapper.terminate();
	}

至此识别手机的上线与下线基本完成了。

PS:关于ddmilb的使用,是我在网上借鉴了某位大神的文章,可惜写这篇文章的时间过久,大神的文章已经找不到了。。。

 

实时获取手机的状态(判断手机是否为空闲状态)

实时获取手机状态的目的是为了当自动化case运行的时候,可以智能的分配当前空闲状态的手机。对于自动化而言,我定义的空闲状态为当前所有未运行自动化case的手机,全部都是空闲状态的手机。运行自动化case的时候,不管你是使用appium,robotium或是monkey等等的这些框架,都会在某个app里面运行,所以我的做法查看当前手机是否在运行滴滴的app,有则是非空闲,无则是空闲。

PS:还有一种做法是可以监听自动化框架的进程,比如监听appium是否运行,原理与监听app程序是一样的。

public static String getPhoneProcess(String devName, String packageName) {
		Process process = null;
		String buff = "";
		String processName = null;
		try {
			process = Runtime.getRuntime().exec(
					"adb -s " + devName + " shell ps | grep " + packageName);
			BufferedReader br = new BufferedReader(new InputStreamReader(
					process.getInputStream(), "utf-8"));
			while ((buff = br.readLine()) != null) {
				System.out.println("我是手机:" + devName + "我有xx进程" + buff);
				processName = buff;
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return processName;
	}

这里直接用的adb shell命令来获取,devName是当前手机的devicesID,packageName是你要查看app的包名。在上面我们已经把所有在线手机放到了一个list里面了,而这个list存的都是我们当前手机的devicesID,这里我们需要取出全部的devicesID,来检查哪些手机有xx的进程,并且每N秒会轮询一次,反复不断的检查当前手机的状态是否已经变更。

获取手机的基本参数

不管是在appium运行时还是平台化都需要当前运行手机的一些参数。尤其是当你想做成平台化时,咱们的测试人员就可以在平台上看到当前都有哪些手机在线,哪些是空闲状态且可以通过平台来执行自动化case,所以就要知道这些手机都是什么型号,什么品牌等一些的手机基本信息。

我这里同样使用到了adb shell命令来获取,比如:获取手机系统版本号、 获取手机厂商、获取手机型号、获取手机分辨率等。

// 获取手机屏幕分辨率
	public String getScreen(String devName) {
		process = null;
		String buff = "";
		try {
			process = Runtime.getRuntime().exec(
					"adb -s " + devName + " -d shell wm size");
			BufferedReader br = new BufferedReader(new InputStreamReader(
					process.getInputStream(), "utf-8"));
			while ((buff = br.readLine()) != null) {
				System.out.println("手机" + devName + "的分辨率是:" + buff);
				return buff;
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 获取手机系统版本号
	public String getSystemVersion(String devName) {
		process = null;
		String buff = "";
		try {
			process = Runtime.getRuntime().exec(
					"adb -s " + devName
							+ " shell getprop ro.build.version.release");
			BufferedReader br = new BufferedReader(new InputStreamReader(
					process.getInputStream(), "utf-8"));
			while ((buff = br.readLine()) != null) {
				System.out.println("手机" + devName + "的系统版本是:" + buff);
				return buff;
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 获取手机厂商
	public String getModel(String devName) {
		process = null;
		String buff = "";
		try {
			process = Runtime.getRuntime().exec(
					"adb -s " + devName + " -d shell getprop ro.product.model");
			BufferedReader br = new BufferedReader(new InputStreamReader(
					process.getInputStream(), "utf-8"));
			while ((buff = br.readLine()) != null) {
				System.out.println("手机" + devName + "的厂商是:" + buff);
				return buff;
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 获取手机型号
	public String getBrand(String devName) {
		process = null;
		String buff = "";
		try {
			process = Runtime.getRuntime().exec(
					"adb -s " + devName + " -d shell getprop ro.product.brand");
			BufferedReader br = new BufferedReader(new InputStreamReader(
					process.getInputStream(), "utf-8"));
			while ((buff = br.readLine()) != null) {
				System.out.println("手机" + devName + "的型号是:" + buff);
				return buff;
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

关于获取手机信息就不一一帖出代码了,反正adb shell是很强大的,根据自己的项目使用就好了。

http网络协议的引入(用来与服务端进行通信)。

这部分内容不做重点交代,我使用的是okhttp框架,关于这个框架的攻略网上一大把。。

这里我只说下关于手机管理的接口思路,个人认为比较重要的接口至少要有下面这3个需要跟服务器的同学协商定义。

uploadxxxxxxData:当监听到有手机进入时,会调用此接口。此接口的作用就是用来告送服务器有手机上线了,并且把之前所拿到的手机基本信息一并发送过去,且由服务器记录同时标记此手机为空闲状态。而排重功能由服务器来做,也就是同一部手机不停的插拔,服务器不能重复记录。

updatexxxxStates:此接口是用来更新手机的状态,情况一:当有手机下线时,调用此接口,通知服务器当前手机离线。情况二:当我监听到有手机在运行自动化case时,调用此接口,通知服务器当前手机为非空闲状态。情况三:当自动化执行完毕时,调用此接口,通知服务器当前手机为空闲状态。

getxxxxxxxxxData:这个接口简单的说就是从服务器获取要运行自动化case的手机。通过上面2个接口,服务器已经知道当前有多少手机在线,有多少是空闲状态,当我运行自动化case的时候,服务器要下发其中的一部或者几部空闲的手机给我。这里服务要注意并发的情况,比如自动化这边要同时运行3个自动化case,服务就要下发不同devicesID的手机给我。

以上就是本人认为运行自动化case前该做的工作,因无人指导完全靠自己摸索,也希望能看到此贴的大神们提出不同意见,或是你有别的思路想法,并且也应用到所在项目中的话,非常乐意大神们留言,咱们可以一起探讨探讨。

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值