跟测试老兵3天成为APP高手(三)
(十四)安装Python的基础包工具setuptools
一种安装方法:
C:\Users\IBM\AppData\Local\Programs\Python\Python37\Lib\test\libregrtest\setup.py install
另一种是下载安装的exe文件,默认安装Python37\Lib\site-packages下面
(十五)检查安装selenium 和selenium server端
C:\Users\IBM>pip install -U selenium
Requirement already up-to-date: selenium in c:\users\ibm\appdata\local\programs\python\python37\lib\site-packages
提示上面信息,表明已经安装成功。下面绿色字体表示pip版本可以升级。
打开https://code.google.com/p/selenium/下载selenium server服务端。
安装selenium sever,使用java -jar selenium-server-standalone-3.14.0.jar进行安装,安装界面成功后如下图,
查看安装的selenium版本:
C:\Users\IBM>pip show selenium
Name: selenium
Version: 3.14.1
如果安装IE driver,则需要与selenum相同的版本(主版本号相同,小版本号可不同)。
(十六)安装Chrome Driver(如果想学习Web自动化测试的话安装)
https://sites.google.com/a/chromium.org/chromedriver/downloads,下载chrome driver驱动放在chrome安装目录中,目前下载只有32位版本。应该也支持64位,但是有可能有坑。
在环境变量的path中添加上述地址。或者把chromedriver.exe拷贝到与代码相同的路径下。
在python编辑器中,添加下面代码,则可以执行。
from selenium import webdriver
driver =webdriver.Chrome()
driver.get('http://www.baidu.com')
print(driver.title)
driver.quit()
(十七)Appium代码框架解释
public AndroidDriver<?> driver; //驱动程序
private String apkName="proname.apk"; //安卓的安装包,被测软件
private String platformVersion = "4.4.2";//安卓模拟器的版本
private String serverURL = "http://127.0.0.1:4723/wd/hub";//appium测试服务的地址
File classpathRoot = new File(System.getProperty("user.dir"));//获得项目路径
File appDir = new File(classpathRoot, "apps");//获得APK所在文件夹名称
File app = new File(appDir, apkName);//获得APK文件
DesiredCapabilities capabilities = new DesiredCapabilities(); /*新建一个DesiredCapabilities对象,是import org.openqa.selenium.remote.DesiredCapabilities;作者个人认为是用来收集驱动初始化信息用的;*/
capabilities.setCapability(CapabilityType.BROWSER_NAME, ""); //指定浏览器的名字,我们测试的是APK所以没有浏览器,故而为空;
capabilities.setCapability("platformName", "Android"); // 指定平台,为安卓
capabilities.setCapability("deviceName", "Android Emulator"); //指定设备,"Android Emulator"这个属性作者认为是“安卓设备即可”
capabilities.setCapability("platformVersion", platformVersion); //指定版本,作者的模拟器是4.4.2的
capabilities.setCapability("app", app.getAbsolutePath()); //指定需要测试的APK,也就是需要安装的APK文件;
//核心关键步骤,创建驱动,指定服务地址,和初始化信息
driver = new AndroidDriver (new URL(serverURL),capabilities);
driver.findElementByAccessibilityId("using").click(); //点击操作
driver.findElementByAccessibilityId("using").clear(); //清除操作,一般是有文字的信息的输入框
driver.findElementByAccessibilityId("using").sendKeys("XXYYMM"); //输入操作"XXYYMM"为你要输入的内容
driver.pressKeyCode(Android_KeyCode.KEYCODE_3); //模拟键盘输入
driver.tap(fingers, element, duration); //点击,fingers是几根手指,element是什么元素(WebElement element = driver.findElementByAccessibilityId("using")), //duration为点击时长,处理长按操作,单位是毫秒,1000毫秒=1秒
driver.tap(fingers, x, y, duration); //坐标点击
driver.zoom(el); //放大,el为元素
driver.zoom(x, y); //放大,通过坐标位置
driver.pinch(el); //缩小,el为元素
driver.pinch(x, y); //缩小,通过坐标
driver.swipe(startx, starty, endx, endy, duration); //滑动,从一个点到另一个点,duration为时长,单位是毫秒,1000毫秒=1秒
下面是测试浅言app的代码,解析如下:
package com.mooctest; //代码放在一个Java包中,包的名称可以随意填写,一般是公司名称或网址相关
import org.testng.AssertJUnit;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.AndroidKeyCode;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Time;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import org.apache.commons.exec.OS;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
//通过import引入各种需要的包,包里是我们需要的一些方法
public class Main {
private boolean isInstall =false;
/**
* "appPackage", "com.zhy.qianyan"
* "app-launchActivity", "com.zhy.qianyan.MainActivity"
* 本示例脚本仅作为参考,具体请根据自己的测试机型可能出现的特殊情况进行脚本的编写调整
*/
/**
* 所有和AppiumDriver相关的操作都必须写在该函数中
* @param driver
*/
public void test(AppiumDriver driver) {
String ret=null;
try {
Thread.sleep(6000); //等待6s,待应用完全启动后,再做后续处理
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS); //设置尝试定位控件的最长时间为8s,也就是最多尝试8s
/*
* 余下的测试逻辑请按照题目要求进行编写
*/
try {
Thread.sleep(4000); //等待4s,待应用完全显示完整
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driver.findElement(By.xpath("//android.widget.Button[@resource-id='com.huawei.systemmanager:id/btn_allow']")).click();
try {
Thread.sleep(6000); //等待6s,待操作完成
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获得屏幕窗口的宽和高
int width = driver.manage().window().getSize().width;
int height = driver.manage().window().getSize().height;
//从屏幕右侧向左侧滑动三次,滑过三个页面
driver.swipe(width*9/10, height/2, width/10, height/2,5000);
driver.swipe(width*9/10, height/2, width/10, height/2,5000);
driver.swipe(width*9/10, height/2, width/10, height/2,5000);
//单击页面中的热点,名称为“开启你的故事”
driver.findElement(By.xpath("//android.widget.TextView[@text='开启你的故事']")).click();
driver.findElement(By.id("android:id/button2")).click(); //单击取消按钮
driver.findElement(By.xpath("//android.view.ViewGroup/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]")).click();
try {
Thread.sleep(3000); //等待3s,待应用完全显示完整
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driver.swipe(width*2/5, height*6/10, width*2/5, height/10,5000); //为了显示出注册/登录按钮,需要向上滑动
try {
Thread.sleep(3000); //等待3s,待应用完全显示完整
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driver.findElement(By.xpath("//android.widget.TextView[@text='注册/登录']")).click(); //单击登录按钮进入登录界面
//输入用户名和密码
driver.findElementByName("请输入手机号码").sendKeys("13910077365"); driver.findElementByXPath("//android.view.ViewGroup/android.widget.EditText[2]").sendKeys("123456");
driver.findElement(By.xpath("//android.widget.TextView[@text='浅 言']")).click(); //去掉输入法
driver.findElement(By.xpath("//android.widget.TextView[@text='登录']")).click(); //单击登录窗口
try {
Thread.sleep(3000); //等待3s,待应用完全显示完整
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ret = driver.findElement(By.xpath("//android.widget.TextView[@text='个人中心']")).getText(); //获得个人中心这个窗口信息
System.out.println(ret); //打印找到文本
//AssertJUnit.assertEquals("个人中心", driver.findElementByXPath("//android.widget.TextView[@text='个人中心']").getText());
/*
AppiumDriver driver1 = Screenshot.getDriver();
File location = new File("screenshots1");
String screenShotName = location.getAbsolutePath()+File.separator+tr.getMethod().getMethodName()+".png";
File screenShot = driver.getScreenshotAs(OutputType.FILE);
try{
FileUtils.copyFile(screenShot, new File(screenShotName));
}
catch(IOException e){
e.printStackTrace();
}
*/
if(isElement(driver,By.xpath("//android.widget.TextView[@text='用户名或密码错误!']")))
{
System.out.println("登录失败!");
return;
}
}
/**
* AppiumDriver的初始化逻辑必须写在该函数中
* @return
*/
public AppiumDriver initAppiumTest() {
AppiumDriver driver=null;
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "apk");
File app = new File(appDir, "qianyan.apk");
//设置自动化相关参数
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("browserName", "");
capabilities.setCapability("platformName", "Android");
//capabilities.setCapability("deviceName", "Android Emulator");
capabilities.setCapability("platformVersion", "6.0.0");
capabilities.setCapability("deviceName", "HUAWEI MT7-TL10");
//设置apk路径
capabilities.setCapability("app", app.getAbsolutePath());
//设置app的主包名和主类名
capabilities.setCapability("appPackage", "com.zhy.qianyan");
capabilities.setCapability("appActivity", ".MainActivity");
//设置使用unicode键盘,支持输入中文和特殊字符
capabilities.setCapability("unicodeKeyboard","true");
//设置用例执行完成后重置键盘
capabilities.setCapability("resetKeyboard","true");
//初始化
try {
driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return driver;
}
public void start() {
test(initAppiumTest());
}
public static void main(String[] args) {
Main main = new Main();
main.start();
}
public boolean isElement(AppiumDriver driver,By locator) {
try {
driver.findElement(locator);
System.out.println("kongjian is appeard!");
return true;
} catch (NoSuchElementException e) {
System.out.println("does not exist!");
return false;
}
}
}
下面是自动化脚本执行过程中的界面。
看到上面有三个tab页面
登录按钮被输入法遮盖,所以需要把输入法隐藏
(十八)Appium-java API详解
目前appium-java最新版本是5.0.0-BETA3,因此就拿最新的说明,以Java为例,首先引入java client的依赖:
<dependency>
<groupId>
io.appium
</groupId>
<artifactId>
java-client
</artifactId>
<version>
5.0.0-BETA3
</version>
</dependency>
API主要分为两类,分别是元素定位类和模拟操作类。
元素定位类findElementByXX
- driver.findElementById(“id”);
id获取方法:利用uiautomater截屏,获取resource id; - driver.findElementByClassName(“className”);
通常通过这种方式获取的view不止一个,需要遍历一遍得到的 views,然后根据条件匹配需要的view。 - driver.findElementByName(“text”);
name获取方法:利用uiautomater截屏,获取text; - driver.findElementsByLinkText (“text”);
针对webview上元素的超链接 - driver.findElementByXPath(“//*[@name=’62’]”);
举例,我要定位下图页面中的这个元素,我采用xpath定位时,可以这样写:
WebElement webElement = driver
.findElementByXPath(
"//android.widget.TextView[contains(@text,'商品描述')]")
;
webElement.click();
查找多元素时,直接用相应的findElementsByXX即可。
模拟操作类
- driver.runAppInBackground(5); //将当前活跃的应用放在后台运行
- driver.hideKeyboard(); //隐藏键盘
- driver.lockDevice(); //锁屏
- driver.openNotifications(); //打开Android的下拉通知栏
- driver.isAppInstalled(“com.example.android.apis”) //判断应用是否安装
- driver.installApp(“path/to/my.apk”) //安装应用
- driver.removeApp(“com.example.android.apis”) //卸载应用
- driver.closeApp() //关闭App
- driver.getContextHandles() //可用上下文,context可以理解为可进入的窗口,如果是native则为native_app,如果是webview为对应webview;
- driver.context(); //设置上下文 (context),对hybrid app会用到
- driver.getAppStringMap(); //获取应用的字符串
- driver.pressKeyCode(AndroidKeyCode.HOME); //给设备发送一个按键事件,所有键盘按键值可参考AndroidKeyCode类
- driver.pullFile(“Library/AddressBook/AddressBook.sqlitedb”); //从设备中拉出文件
- driver.pullFolder(“Library/AddressBook”); //从设备中拉出文件夹
- driver.PushFile(“/data/local/tmp/file.txt”, “some data for the file”); //推送文件到设备中去
- driver.swipe(75, 500, 75, 0, 0.8) //模拟用户滑动
- driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1)); //设置等待时间
- driver.navigate().forward(); // 前进
- driver.navigate().back(); // 后退
- driver.navigate().refresh(); // 刷新
- driver.currentActivity(); //当前activity,可用于断言跳转是否正确
- driver.startActivity(appPackage,appActivity); //启动其他app的activity
- 坐标操作,降低适配带来的不适用:
double Screen_X = driver.Manage().Window.Size.Width;//获取手机屏幕宽度
double Screen_Y = driver.Manage().Window.Size.Height;//获取手机屏幕高度
double startX = element.Location.X; //获取元素的起点坐标,即元素最左上角点的横坐标
double startY = element.Location.Y; //获取元素的起点坐标,即元素最左上角点的纵坐标
double elementWidth = element.Size.Width; //获取元素的宽度
double elementHight = element.Size.Height; //获取元素的宽度
我对照着看了appium-client的官方文档,然后对着demo演示,发现一些个别API都找不到,查了下资料才发现,问题出现在:
publicstatic
AppiumDriver driver;
如果改成这样就ok了:
publicstatic
AndroidDriver driver;
这里要说下AppiumDriver和AndroiDriver的关系,AndroidDriver已经继承了AppiumDriver,在AppiumDriver基础上再封装一些基本功能。而AppiumDrvier是原生webdriver的子类,所以一些webdriver的方法都是适用的[Freeman1] 。
16、SDK android device monitor/android studio 进行android内存查看、Eclipse memory analyzer tool(MAT)分析内存获取详细信息。
安装MAT
下载安装:http://www.eclipse.org/mat/downloads.php
在线安装:http://archive.eclipse.org/mat/1.2/update-site/
Shallow Size
对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。
Retained Size
Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage
从上图可以看到它的大部分功能。
1. Histogram可以列出内存中的对象,对象的个数以及大小。
2. Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。
3.Top consumers通过图形列出最大的object。
4.Leak Suspects通过MA自动分析泄漏的原因。
Histogram如下图:
Objects:类的对象的数量。
Shallow size:就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。
Retained size:是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。
我们发现ThreadLocal和bingo.persister.dao.Daos类的对象占用了很多空间。
(十九)APP内存测试
常见的app内存测试工具:
Android Studio/Memory Monitor:观察Dalvik内存
Dumpsys meminfo:观察整体内存
Smaps:观察整体内存的详细组成
Eclipse Memory Analyzer:详细分析Dalvik内存
APP开发中关注内存:
尽量不要在循环中创建太多的临时变量
尽量把大型的循环拆散,分段或按需执行
引入SDK库和调用新的系统API时,主要不常用功能的消耗,可考虑多进程方案,影响内存放入临时进程执行
调整Dex文件的顺序可以优化空间
Native Heap:Native代码分配的内存,虚拟机和Android框架分配内存。关于什么是Native代码,即非Java代码分配的内存。详细介绍请找百度。
Dalvik Heap:Java对象分配的占据内存
Dalvik Other:类数据结构和索引占据内存
Stack:栈内存
Ashmem:不以dalvik- 开头的内存区域,匿名共享内存用来提供共享内存通过分配一个多个进程可以共享的带名称的内存块。匿名共享内存(Anonymous Shared Memory-Ashmem。Android匿名共享内存是基于Linux共享内存的,都是在tmpfs文件系统上新建文件,并将其映射到不同的进程空间,从而达到共享内存的目的,只是,Android在Linux的基础上进行了改造,并借助Binder+fd文件描述符实现了共享内存的传递。
Other dev:内部driver占用的内存
.so mmap C库代码占用的内存
.jar mmap java文件代码占用的内存
.apk mmap apk代码占用的内存
.ttf mmap ttf文件代码占用的内存
.dex mmap dex文件代码占用内存。类函数的代码和常量占用的内存,dex mmap是映射classex.dex文件,Dalvik虚拟机从dex文件加载类信息和字符串常量等。Dex文件有索引区和Data区
Other mmap 其它文件占用的内存
Pss:进程各部分内存的消耗,是所有进程pss相加得到系统占用内存的总和。
Dalvik heap Pss内存=私有内存Private Dirty+ 共享内存Share Dirty/共享的进程数Dalvik heap Pss内存=私有内存Private Dirty+ 共享内存Share Dirty/共享的进程数
Heap Size:Dalvik Heap总共的内存大小
Heap Alloc:所有应用实例分配的内存,包括了应用从zygote共享分享的内存
Native Heap Size 约等于Native Heap Alloc + Native Heap Free
主要内容就讲完了,你学得怎么样?欢迎跟我交流。36115774
(完)
跟测试老兵3天成为APP高手(三)相关推荐
- 跟测试老兵3天成为APP高手(二)
今天继续第二天的分享. (六)ADB安卓调试桥使用 ADB的全称为Android Debug Bridge,安卓调试桥.如安装软件.卸载软件.系统升级.运行shell命令等.adb就是连接Androi ...
- dt测试软件的学习心得,无线网络优化dt测试心得_适合新手入门,高手进阶_5年项目经验实战经验.docx...
无线网络优化DT测试心得_适合新手入门,高手进阶_5年项目经验实战经验 无线网络优化DT测试心得_适合新手入门,高手进阶_5年项目经验实战经验 路测中不常见的问题和个人心得 1.深井子镇投诉测试报告 ...
- 微软测试基于云的剪贴板App,可跨平台同步
微软测试基于云的剪贴板App,可跨平台同步 这一周真的是未公布的微软App的一周啊.几天前,一个轻量级邮件解决方案的新闻爆出,并且今天另外两个生产率管理app被提出来.感谢@h0x0d的推特--流邮件 ...
- 测试nfc功能软件,一般app测试的最佳方法
一提到软件测试,测试员基本想到的就是去检查文件,功能,API,性能并确定软件是否安全,以及关于软件特定部分的其他事项.而对于移动测试,测试员不得不基于用户移动使用模式考虑移动相关的功能. 功能测试 每 ...
- Android 天气APP(三十一)每日提醒弹窗
上一篇:Android 天气APP(三十)分钟级降水 效果图 每日提醒弹窗 前言 正文 一.弹窗背景 二.每天第一次弹窗 三.弹出每日提示弹窗 四.弹窗的开关 文末 前言 为了增强用户的体验,所以 ...
- Android 天气APP(三十)分钟级降水
上一篇:Android 天气APP(二十九)壁纸设置.图片查看.图片保存 运行效果图 分钟级降水 前言 正文 一.新增分钟级降水API 二.修改布局 三.增加适配器 四.增加网络请求与回调 五.控件初 ...
- 用Swift实现一款天气预报APP(三)
这个系列的目录: 用Swift实现一款天气预报APP(一) 用Swift实现一款天气预报APP(二) 用Swift实现一款天气预报APP(三) 通过前面的学习,一个天气预报的APP已经基本可用了.至少 ...
- android启动其他app的服务器,Android中通过外部程序启动App的三种方法
这篇文章主要介绍了Android中通过外部程序启动App的三种方法, 本文讲解了直接通过包名. 通过自定义的Action. 通过Scheme三种方法,并分别给出操作代码,需要的朋友可以参考下 ==== ...
- 制作单词记录App(三)
制作单词记录App(三) 制作单词记录App(三) 改造Adapter为ListAdapter(用以处理后台提交的列表数据) 修正视图序号上的改变(变更为数据层面的序号改变) 制作添加数据时的数据信息 ...
最新文章
- WSUS3.0的部署及安装
- 解决Kali Linux XFCE桌面Tab无法补全
- java集合框架(Framework)的性能
- Idea debugger 无法启动-unable to open debugger port , java.net.SocketException socket closed
- 干货收藏 | 如何优化前端性能?
- Python—实训day9—使用pandas进行数据预处理
- 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 12丨销售分析 III【难度简单】
- 自制反汇编逆向分析工具 迭代第六版本 (一)
- 【Elasticsearch】追踪同步分片副本 in-sync allocation IDs
- Python之数据分析(Numpy的矩阵相关操作、ufunc泛化函数对象)
- linux debian硬盘安装,Debian硬盘安装方法
- c语言作业模块化设计具体,C语言程序模块化设计.doc
- 关于微信小程序上线流程的简单总结
- 9个实用的,可以写进简历的数据分析项目!
- 单片机 一键开关机 软件结合
- 李帅燕山大学计算机,燕山大学第二十三届学生会复试结果
- Linux学习(一)初识Linux(适合萌懂阶段)
- NOIp 2020 微信步数 题解
- 榜单发布!国产智能驾驶域控制器市场竞争力TOP10供应商
- linux shell 操作二进制文件(xxd、dd)
热门文章
- 数据结构和算法-2023.06.29
- java comparable 泛型_Java泛型的应用——T extends Comparable? super T
- div内容居中(div块内容居中)
- C语言零基础项目:生命游戏!详细思路+源码分享
- Mysql数据库sql语句
- oppor17山寨机的特点_oppor17怎么样优缺点
- 通过Leaguepedia API实现抓取英雄联盟赛事数据
- 谈软件工程各环节中的辅助工具
- 导师推荐信计算机,美国留学导师推荐信范文(计算机)
- 浪潮信息与宁盾共建的统一身份管理联合解决方案获澎湃技术认证