Android端自动化测试工具源码分享

简介: 在上篇的效果中,我们可以发现,所有的触发控制,都是通过网页端进行下发的,而网页的展示又是通过手机端进行开启服务的,也就是说,必须要把手机做为一个服务器,进行指令的发送和获取。

 Hello啊各位老铁,许久不见,也忘了更新了,在上一篇的文章中,针对Android端的自动化测试框架做了一个简单的了解与使用,今天这篇文章呢,咱们就谈一谈具体的实现思路。


实话实说,针对这个1.0.0的版本,还是有着很多的瑕疵之处,奈何自己时间跟不上继续开发的步伐,后续有充足的时间规划了,还是一定要好好搞一搞,这个东西的价值,在Android端自动化测试中,自我感觉还是很高的。



在上篇的效果中,我们可以发现,所有的触发控制,都是通过网页端进行下发的,而网页的展示又是通过手机端进行开启服务的,也就是说,必须要把手机做为一个服务器,进行指令的发送和获取。


以手机做为服务器,这是实现自动化测试的第一步,毕竟在自动化测试的页面,不仅需要获取到手机端安装的所有App,也需要向服务器(手机端)发送测试的指令,那么如何实现这样一个功能呢?


关注我的老铁可能知道,之前分享过一篇电脑端如何访问手机SD卡中的文件的文章,其实在这篇文章中,自己介绍过一个开源的框架,AndServer,它是一个Android 平台的 Web Server 和 Web Framework,通过这个框架,我们可以很方便的把手机做为一个服务器,这个框架确确实实可以解决很多问题,感兴趣的朋友可以多看一看。


相关文档地址:

https://yanzhenjie.com/AndServer/


AndServer这个框架只是给我们提供了一个做为一个服务的平台,但具体的发送指令和App列表的获取等一些功能,需要我们自己具体的完成,其实就是接口的编写,以手机做为“后端”,以网页做为前端。


我们把具体的实现拆解开来,基本上可以分为,前端页面的展示,”后端“接口的编写,自动化逻辑的编写三部分。


前端页面展示


前端页面,也就是上边我们所看到的网页,使用html,css和javascript编写的,大家可以查看源码中的assets目录,这个目录下面,就是上述网页效果的所有源码了,其中index.html文件是我们主要的网页源文件,web语言呢,还是比较简单的,html和css和我们Android中的xml很类似,而数据动态的交互javascript就和我们的java和kotlin类似,学起来呢也是比较简单的,针对这一块,就不做多解释了,看各位老铁如何了解了,我是希望大家,在有时间的前提下,还是多熟悉熟悉比较好。


“后端”接口的编写


前端页面写出来之后,需要有数据的渲染,也需要有逻辑的处理,根据AndServer的文档,我们就可以进行简单的书写相关接口了。


根据前端UI,左侧是需要拿到手机安装的所有App的,所以,需要一个获取手机App列表的相关接口。


接口以Get的方式进行提供:


/*** AUTHOR:AbnerMing* INTRODUCE:获取手机应用信息*/@GetMapping(path="/appList")
List<AppInfo>getAppList() {
returnAppUtils.getAppUtils().getAppInfo(1);
}


具体的获取手机列表逻辑:


// 获取已安装的应用信息队列publicArrayList<AppInfo>getAppInfo(inttype) {
ArrayList<AppInfo>appList=newArrayList<>();
SparseIntArraysiArray=newSparseIntArray();
// 获得应用包管理器PackageManagerpm=mContext.getPackageManager();
// 获取系统中已经安装的应用列表@SuppressLint("WrongConstant")
List<ApplicationInfo>installList=pm.getInstalledApplications(
PackageManager.PERMISSION_GRANTED);
for (inti=0; i<installList.size(); i++) {
ApplicationInfoitem=installList.get(i);
// 去掉重复的应用信息if (siArray.indexOfKey(item.uid) >=0) {
continue;
            }
// 往siArray中添加一个应用编号,以便后续的去重校验siArray.put(item.uid, 1);
try {
// 获取该应用的权限列表String[] permissions=pm.getPackageInfo(item.packageName,
PackageManager.GET_PERMISSIONS).requestedPermissions;
if (permissions==null) {
continue;
                }
booleanisQueryNetwork=false;
for (Stringpermission : permissions) {
// 过滤那些具备上网权限的应用if (permission.equals("android.permission.INTERNET")) {
isQueryNetwork=true;
break;
                    }
                }
// 类型为0表示所有应用,为1表示只要联网应用if (type==0|| (type==1&&isQueryNetwork)) {
AppInfoapp=newAppInfo();
app.uid=item.uid; // 获取应用的编号app.label=item.loadLabel(pm).toString(); // 获取应用的名称app.package_name=item.packageName; // 获取应用的包名//Drawable drawable = item.loadIcon(pm); // 获取应用的图标if (!app.label.contains(".") &&!app.label.contains(" ")) {
appList.add(app);
                    }
                }
            } catch (Exceptione) {
e.printStackTrace();
continue;
            }
        }
returnappList;  // 返回去重后的应用包队列    }


前端UI中间的部分则是应用的脚本展示和编写的区域,而脚本的存储和获取也是依赖于手机端,存储的方式有很多种,可以通过内存,文件或者数据库都是可以的,这里我简单的通过SharedPreferences来进行存储的。


存储的时候需要注意,因为应用的不同所存储的脚本也是不一样的,需要根据应用的标识来进行区分,这里是采用的是应用的编号uid,在上述获取应用列表里,通过ApplicationInfo可以拿到。在前端的执行效果就是,点击左侧不同的应用,来切换不同的uid,通过中间的脚本编辑,然后调用保存接口。


/*** AUTHOR:AbnerMing* INTRODUCE:存储脚本信息*/@PostMapping(path="/save")
voidsaveAppScript(
@RequestParam(name="appScript") StringappScript,
@RequestParam(name="appKey") StringappKey    ) {
SharedPreUtils.put(App.getInstance(), "script_"+appKey, appScript);
}


有的老铁可能会有疑虑,你用SharedPreferences进行保存,每个应用的脚本列表如何实现呢,这个也简单,通过json保存呗,具体的数组和对象转化成string后进行存储就可以了。

获取脚本信息:


/*** AUTHOR:AbnerMing* INTRODUCE:获取脚本信息*/@GetMapping(path="/appScript")
StringgetAppScript(@RequestParam(name="appKey") StringappKey) {
Stringjson=SharedPreUtils.getString(App.getInstance(), "script_"+appKey);
if (!TextUtils.isEmpty(json)) {
returnjson;
        } else {
returnJsonUtils.failedJson(400, "没有找到对应的脚本数据");
        }
    }


接收启动消息与当前进度消息


前端点击脚本运行之后,需要把当前的应用信息以及脚本信息,发送到后端,也就是手机端,那么手机端如何接收这个通知呢?这里在手机端做了一个定时操作,也就是不断的来轮询是否有指令过来,有的话,赋值一个变量为true,就直接执行程序,程序执行完或者点击了终止操作,把这个变量赋值为false,也就是说,轮询一直都在,但程序的执行是通过变量来控制的。

开启程序接口,包含开启的指令,调用的脚本信息,应用的包名字。


/*** AUTHOR:AbnerMing* INTRODUCE:开启程序*/@PostMapping(path="/startApp")
voidstartScript(
@RequestParam(name="startApp") StringstartApp,
@RequestParam(name="appScript") StringappScript,
@RequestParam(name="appPack") StringappPack    ) {
App.Companion.setMAppToastMessage("");
App.Companion.setMAppScriptMessage("");
App.Companion.setMStartApp(startApp);
App.Companion.setMAppPack(appPack);
App.Companion.setMAppScript(appScript);
    }


当然了还有一些其他的接口信息,大家主要看源码中PhoneAppController这个类即可,里面也有着详细的注释。


自动化逻辑


有了前端UI的展示,还有接口的提供,基本上,就可以实现上篇文章的效果,但触发运行指令之后,如何进行该脚本的正常执行呢?举个例子,我给京东写了一个脚本,搜索茅台,点击进详情,然后执行抢购操作,当程序下发后,怎么在手机上正常运行呢?


这里呢,我使用的是AccessibilityService,也就是Android端的无障碍服务,通过AccessibilityService我们可以监听到当前的可见的应用,以及捕获到页面的控件相关信息,进而执行我们的点击,输入,滑动等操作。


相关的源码大家可以看AutomaticService这个类,目前仅仅是初版,很多代码写的很随便,大家先凑合着看哈。


这个服务实现的相关逻辑就是开启服务后,直接启动一个定时,这个定时器是一直存在的,目的就是用来接收,是否有新的指令过来,一旦有指令过来,就去执行程序,并把开关关闭。



不为空,证明有新的脚本信息过来,就去执行,然后赋值为空,确保一个指令只执行一次。



执行脚本的时候,大家可以看到都是通过中文或简写进行编辑的,其实这些都是我们自己所定义的,也就说,我们可以随意定义,比如点击登录,最重要的是登录两个字,你点击也好,click也好,根据定义的这个,回到我们的程序中,进行截取,触发相关的逻辑即可,下面的图是我自己定义的。



在代码中是这样做截取的,可以看下面代码,非常的简单,拿到你的执行脚本,判断是否包含所定义的关键字,然后,截取,执行点击操作。


if (s.contains("点击") ||s.contains("ck")) {
try {
Stringclick="";
if (s.contains("点击")) {
click=s.replace("点击", "");
                } else {
click=s.replace("ck", "");
                }
//判断是否存在WUtils.findTextAndClick(this, click, newCallBackListener() {
@Overridepublicvoidsuccess() {
try {
Thread.sleep(1000);
                        } catch (Exceptione) {
e.printStackTrace();
                        }
App.Companion.setMAppScriptMessage(indexPosition+"=="+s);
Log.e(TAG, indexPosition+"=="+s);
containsContent();
                    }
@Overridepublicvoidfail() {
App.Companion.setMAppScriptMessage("-c==【"+s+"】未找到当前程序");
Log.e(TAG, "-c==【"+s+"】未找到当前程序");
//执行发生,错误之后,继续执行下一个逻辑containsContent();
                    }
                });
            } catch (Exceptione) {
e.printStackTrace();
App.Companion.setMAppScriptMessage("-c==【"+s+"】语法错误啊老铁");
Log.e(TAG, "-c==【"+s+"】语法错误啊老铁");
            }
        }


以上呢,是点击的操作,滑动,输入等等都是通过这种方式,大家可以直接看AutomaticService这个类。


关于点击,滑动,输入等等操作,我都封装好了,大家可以看WUtils或者BaseAccessibilityService即可,里面基本上也有注释。


这版的功能实现比较着急,没有好好的进行梳理,按照既定的规划,使用AccessibilityService是完全可以进行流畅的自动化的,目前只实现了一个大概,后续还得跟进啊,好了,各位老铁,就到这里吧,下面是源码,大家可以随意更改。


Github地址:

https://github.com/AbnerMing888/AndroidAutomatic

相关文章
|
1月前
|
Java 测试技术 数据安全/隐私保护
软件测试中的自动化策略与工具应用
在软件开发的快速迭代中,自动化测试以其高效、稳定的特点成为了质量保证的重要手段。本文将深入探讨自动化测试的核心概念、常见工具的应用,以及如何设计有效的自动化测试策略,旨在为读者提供一套完整的自动化测试解决方案,帮助团队提升测试效率和软件质量。
|
3月前
|
运维 Linux Apache
Puppet 作为一款强大的自动化运维工具,被广泛应用于配置管理领域。通过定义资源的状态和关系,Puppet 能够确保系统始终处于期望的配置状态。
Puppet 作为一款强大的自动化运维工具,被广泛应用于配置管理领域。通过定义资源的状态和关系,Puppet 能够确保系统始终处于期望的配置状态。
95 3
|
3月前
|
运维 Linux Apache
,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具
【10月更文挑战第7天】随着云计算和容器化技术的发展,自动化运维成为现代IT基础设施的关键部分。Puppet是一款强大的自动化运维工具,通过定义资源状态和关系,确保系统始终处于期望配置状态。本文介绍Puppet的基本概念、安装配置及使用示例,帮助读者快速掌握Puppet,实现高效自动化运维。
86 4
|
3月前
|
运维 Linux Apache
Puppet这一强大的自动化运维工具,涵盖其基本概念、安装配置及使用示例
【10月更文挑战第8天】本文介绍了Puppet这一强大的自动化运维工具,涵盖其基本概念、安装配置及使用示例。Puppet通过定义资源状态和关系,确保系统配置始终如一,支持高效管理基础设施。文章详细讲解了Puppet的安装步骤、配置方法及DSL语言示例,帮助读者快速掌握Puppet的使用技巧。
139 2
|
3月前
|
监控 虚拟化 云计算
从物理到云:使用自动化工具简化服务器迁移流程
【10月更文挑战第4天】随着云计算的快速发展,越来越多的企业选择将物理服务器迁移到云环境以提高效率和降低成本。本文详细介绍了使用自动化工具简化从物理到云的服务器迁移流程的技术实现细节,并提供了代码示例。
195 6
|
9天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
10天前
|
弹性计算 运维 监控
自动化AutoTalk第十一期-应知必会的自动化工具之阿里云配额中心
本次分享主题为“应知必会的自动化工具之阿里云配额中心”,课程围绕三个方面展开:1) 认识配额及其作用;2) 配额管理的意义与方法;3) 阿里云配额中心的功能和使用场景。通过学习,了解如何有效管理和监控配额,避免资源限制影响业务,并实现自动化集成,提升运维效率。
33 10
|
10天前
|
JavaScript Java 开发工具
AutoTalk第十三期-应知必会的自动化工具-阿里云SDK支持策略(一)
AutoTalk第十三期探讨阿里云SDK支持策略,涵盖四大方面:发布策略、版本规范、更新策略及停止支持策略。重点介绍SDK的及时性、完整性、测试覆盖度和版本命名规范;并以Python部分语言版本停止支持为案例,帮助开发者了解维护策略,确保平稳过渡到新版本。
|
11天前
|
算法 安全 Java
自动化AutoTalk第十期:应知必会的自动化工具-阿里云SDK
本期《自动化AutoTalk》第十期聚焦应知必会的自动化工具——阿里云SDK。主要内容分为三部分:1. 阿里云SDK概述,介绍其支持的300多款云产品和8种主流编程语言;2. 快速生成SDK示例,以Java语言为例展示如何通过OpenAPI门户快速生成并下载SDK工程;3. 进阶特性介绍,涵盖签名算法、Endpoint配置、代理设置、HTTPS请求配置、超时机制及异常处理等重要功能。通过这些内容,帮助开发者更高效、安全地使用阿里云SDK。
|
1月前
|
Web App开发 IDE 测试技术
Selenium:强大的 Web 自动化测试工具
Selenium 是一款强大的 Web 自动化测试工具,包括 Selenium IDE、WebDriver 和 Grid 三大组件,支持多种编程语言和跨平台操作。它能有效提高测试效率,解决跨浏览器兼容性问题,进行性能测试和数据驱动测试,尽管存在学习曲线较陡、不稳定等缺点,但其优势明显,是自动化测试领域的首选工具。
225 17
Selenium:强大的 Web 自动化测试工具

热门文章

最新文章