自动化-Appium-第一个Demo-混合(Java版)

2022-07-25 13:00:23 浏览数 (1)

第一个Demo-混合

什么是Hybrid(混合)?

App是移动混合应用程序,即在移动应用程序中嵌入了Webview,通过Webview访问网页。

移动应用和Webview分别属于两个不同的上下文,移动应用默认的Context为”NATIVE_APP”,Webview默认的Context为”WEBVIEW_被测进程名称”。测试Webview中的网页内容时,需要切换到Webview的Context下。

第1章 Android

1.1创建项目

1、启动Eclipse,鼠标右键New--->Project。

2、创建Java项目,选择Java目录下的Java Project。

3、输入项目名称(例如:My_Appium_Demo),点击Finish完成。

4、创建lib文件夹,用来存放jar包。把Appium Clients jar和Selenium jar包拷贝到文件夹里。

5、创建app文件夹,用来存放应用程序。把应用程序Bangbang.apk、Qunar.apk拷贝到文件夹里。

6、选中拷贝过来的Appium Clients jar和Selenium jar包,鼠标右键Build Path--->Add to Build Path。

7、Appium Clients jar和Selenium jar包已经被项目引用了。

8、选中src源文件夹,鼠标右键New--->Class,创建Java类,输入包名(例如:com.test.demo)、类名(例如:模拟器示例为Android_Hybrid_Simulator,真机示例为Android_Hybrid_RealMachine),点击Finish完成。

9、第一个Demo项目,Android-混合(模拟器/真机)创建完成。

1.2编写脚本

1.2.1模拟器

1、本章示例模拟器使用的是Genymotion,首先打开Genymotion模拟器,打开指定的Android版本。

2、首先获取模拟器设备标识,命令行输入命令 adb devices

如图所示,只查询到1台此模拟器,在脚本里可以不用添加此参数

capabilities.setCapability("udid", " 192.168.113.101:5555");

就可以指定此台模拟器执行。

如果是多台设备,如图所示,查询到2台(1台模拟器192.168.113.101:5555、1台真机MYV0215825000026),在脚本就要添加此参数

capabilities.setCapability("udid", "192.168.113.101:5555");

测试执行的时候来指定这台模拟器执行。

3、模拟器里没有要测试的应用程序,可以在执行自动化测试前先安装到模拟器里,输入安装命令 adb install -r 进行安装,或者使用手机助手进行安装,或者直接将.apk应用程序拖拽到模拟器上进行安装。

4、模拟器里没有要测试的应用程序,想在自动化测试执行的时候自动安装。则需要在脚本里添加如下代码:

代码语言:javascript复制
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "app");
File app = new File(appDir, "Bangbang.apk");

// `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
// Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
// 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
// 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
capabilities.setCapability("app", app.getAbsolutePath());

5、当模拟器里有要测试的应用程序,每次执行测试脚本可以不用安装被测应用,只要指定appPackage和appActivity就可以了。

6、接下来开始使用查找元素定位工具来获取元素的属性值等信息,那怎么知道所要测试的应用程序是否是混合型的呢?例如使用Android SDK的uiautomatorviewer工具查找元素,有时识别不到webview中的元素,并且显示android.webkit.WebView,如下图:打开帮帮应用,点击帮助中心页面。

接下来打开PC的Chrome浏览器,输入访问地址chrome://inspect/

如图所示,可以检测到当前应用程序界面是Webview,则可以确定此应用程序是混合的。

点击页面链接,弹出新窗口,显示当前页面的Webview元素信息(由于国内网络问题,第一次页面加载可能需要FANQIANG)。元素定位方法同Selenium WebDriver一致。

7、切换NATIVE_APP还是WEBVIEW_被测进程名称,使用context方法。

8、脚本代码:

代码语言:javascript复制
package com.test.demo;
import java.io.File;
import java.net.URL;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
/**
 * Android-混合-模拟器
 *
 * @author wangmcn
 *
 */
public class Android_Hybrid_Simulator {
       public static void main(String[] args) throws Exception {
              AndroidDriverdriver;
              File classpathRoot = new File(System.getProperty("user.dir"));
              File appDir = new File(classpathRoot, "app");
              File app = new File(appDir, "Bangbang.apk");
              DesiredCapabilities capabilities = new DesiredCapabilities();

              // 使用哪个自动化测试引擎
              // 默认为Appium,或Selendroid或UiAutomator2或Espresso用于Android;或XCUITest用于IOS
              capabilities.setCapability("automationName", "Appium");

              // 使用哪个移动操作系统平台
              // iOS, Android, FirefoxOS
              capabilities.setCapability("platformName", "Android");

              // 移动操作系统版本
              capabilities.setCapability("platformVersion", "6.0");

              // 使用的移动设备或模拟器的类型
              // iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android
              // Emulator, Galaxy S4 等等
              // 在IOS上,这个关键字的值必须是使用`instruments -s devices`得到的可使用的设备名称之一
              // 在Android上,这个关键字目前不起作用
              capabilities.setCapability("deviceName", "honor");

              // 连接的物理设备的唯一设备标识
              capabilities.setCapability("udid", "192.168.113.101:5555");

              // `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
              // Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
              // 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
              // 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
              capabilities.setCapability("app", app.getAbsolutePath());

              // 要运行Android应用的包名
              capabilities.setCapability("appPackage", "com.xiaoV.BWalletBeta");

              // 要从包中启动的Android activity的活动名称
              capabilities.setCapability("appActivity", "com.xiaoV.BWallet.yklogin.YkSplashActivity");

              // 启用Unicode输入法,设置为true可以输入中文字符,默认为false
              capabilities.setCapability("unicodeKeyboard", true);

              // 在设定了`unicodeKeyboard`关键字运行Unicode测试结束后,将键盘重置为其原始状态
              // 如果单独使用,将会被忽略,默认值`false`
              capabilities.setCapability("resetKeyboard", true);

              // 设置为true,每次启动时覆盖session,否则第二次运行会报错不能新建session
              capabilities.setCapability("sessionOverride", true);

              // 在此会话之前不要重置应用程序状态
              // Android 不要停止应用程序,不要清除应用程序数据,也不要卸载apk
              // IOS 测试后不要销毁或关闭SIM卡。开始测试运行在任何模拟运行,或设备插入
              capabilities.setCapability("noReset", true);

              // 执行完整的重置
              // Android 停止应用程序,清除应用程序数据并在测试后卸载apk
              // IOS 在真机设备测试后卸载应用程序,在模拟器测试后摧毁模拟器
              capabilities.setCapability("fullReset", false);

              // 设置命令超时时间,单位:秒
              // 达到超时时间仍未接收到新的命令时Appium会假设客户端退出然后自动结束会话
              capabilities.setCapability("newCommandTimeout", 60);

              driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
              System.out.println("启动应用程序");
              Thread.sleep(6000);

              // 弹出有新版本提示框,点击一会再说
              driver.findElement(By.id("com.xiaoV.BWalletBeta:id/bt_update_id_cancel")).click();

              Thread.sleep(2000);

              // 点击左侧菜单
              driver.findElement(By.id("com.xiaoV.BWalletBeta:id/iv_left_image")).click();

              Thread.sleep(2000);

              // 点击帮助中心
              driver.findElement(By.id("com.xiaoV.BWalletBeta:id/helpcenter")).click();

              Thread.sleep(5000);

              SetcontextNames = driver.getContextHandles();
              for (String contextName : contextNames) {
                     // 打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App
                     System.out.println(contextName);
                     if (contextName.contains("WEBVIEW_com.xiaoV.BWalletBeta")) {
                            // 切换到webview模式以便查找web元素
                            driver.context(contextName);
                            System.out.println("切换到webview:"   contextName);
                     }
              }

              Thread.sleep(2000);

              // 打印当前网页源码
              System.out.println(driver.getPageSource());

              Thread.sleep(2000);

              // 点击关于借钱
              driver.findElement(By.xpath(".//*[@id='question-list']/section/div[1]/ul/li[2]")).click();

              Thread.sleep(2000);

              // 切换到App模式
              driver.context("NATIVE_APP"); 

              System.out.println("切换到App:NATIVE_APP");
              Thread.sleep(2000);

              // 点击返回
              driver.findElement(By.id("com.xiaoV.BWalletBeta:id/iv_left_image")).click();

              Thread.sleep(2000);
              driver.quit();
       }
}

1.2.2真机

1、首先获取真机设备标识,命令行输入命令 adb devices

2、真机设备里没有要测试的应用程序,可以在执行自动化测试前先安装到设备里,输入安装命令 adb install -r 进行安装,或者使用手机助手进行安装。

3、真机设备里没有要测试的应用程序,想在自动化测试执行的时候自动安装。则需要在脚本里添加如下代码:

代码语言:javascript复制
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "app");
File app = new File(appDir, "Qunar.apk");

// `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
// Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
// 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
// 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
capabilities.setCapability("app", app.getAbsolutePath());

4、当真机设备里有要测试的应用程序,每次执行测试脚本可以不用安装被测应用,只要指定appPackage和appActivity就可以了。

5、接下来开始使用查找元素定位工具来获取元素的属性值等信息,那怎么知道所要测试的应用程序是否是混合型的呢?例如使用Android SDK的uiautomatorviewer工具查找元素,有时识别不到webview中的元素,并且显示android.webkit.WebView,如下图:打开去哪儿应用,点击我的页面。

接下来打开PC的Chrome浏览器,输入访问地址chrome://inspect/

如图所示,可以检测到当前应用程序界面是Webview,则可以确定此应用程序是混合的。

点击页面链接,弹出新窗口,显示当前页面的Webview元素信息(由于国内网络问题,第一次页面加载可能需要FANQIANG)。元素定位方法同Selenium WebDriver一致。

6、切换NATIVE_APP还是WEBVIEW_被测进程名称,使用context方法。

7、脚本代码:

代码语言:javascript复制
package com.test.demo;
import java.io.File;
import java.net.URL;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
/**
 * Android-混合-真机
 *
 * @author wangmcn
 *
 */
public class Android_Hybrid_RealMachine {
       public static void main(String[] args) throws Exception {
              AndroidDriverdriver;
              File classpathRoot = new File(System.getProperty("user.dir"));
              File appDir = new File(classpathRoot, "app");
              File app = new File(appDir, "Qunar.apk");
              DesiredCapabilities capabilities = new DesiredCapabilities();

              // 使用哪个自动化测试引擎
              // 默认为Appium,或Selendroid或UiAutomator2或Espresso用于Android;或XCUITest用于IOS
              capabilities.setCapability("automationName", "Appium");

              // 使用哪个移动操作系统平台
              // iOS, Android, FirefoxOS
              capabilities.setCapability("platformName", "Android");

              // 移动操作系统版本
              capabilities.setCapability("platformVersion", "6.0");

              // 使用的移动设备或模拟器的类型
              // iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android
              // Emulator, Galaxy S4 等等
              // 在IOS上,这个关键字的值必须是使用`instruments -s devices`得到的可使用的设备名称之一
              // 在Android上,这个关键字目前不起作用
              capabilities.setCapability("deviceName", "honor");

              // 连接的物理设备的唯一设备标识
              capabilities.setCapability("udid", "MYV0215825000026");

              // `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
              // Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
              // 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
              // 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
              capabilities.setCapability("app", app.getAbsolutePath());

              // 要运行Android应用的包名
              capabilities.setCapability("appPackage", "com.Qunar");

              // 要从包中启动的Android activity的活动名称
              capabilities.setCapability("appActivity", "com.mqunar.splash.SplashActivity");

              // 启用Unicode输入法,设置为true可以输入中文字符,默认为false
              capabilities.setCapability("unicodeKeyboard", true);

              // 在设定了`unicodeKeyboard`关键字运行Unicode测试结束后,将键盘重置为其原始状态
              // 如果单独使用,将会被忽略,默认值`false`
              capabilities.setCapability("resetKeyboard", true);

              // 设置为true,每次启动时覆盖session,否则第二次运行会报错不能新建session
              capabilities.setCapability("sessionOverride", true);

              // 在此会话之前不要重置应用程序状态
              // Android 不要停止应用程序,不要清除应用程序数据,也不要卸载apk
              // IOS 测试后不要销毁或关闭SIM卡。开始测试运行在任何模拟运行,或设备插入
              capabilities.setCapability("noReset", true);

              // 执行完整的重置
              // Android 停止应用程序,清除应用程序数据并在测试后卸载apk
              // IOS 在真机设备测试后卸载应用程序,在模拟器测试后摧毁模拟器
              capabilities.setCapability("fullReset", false);

              // 设置命令超时时间,单位:秒
              // 达到超时时间仍未接收到新的命令时Appium会假设客户端退出然后自动结束会话
              capabilities.setCapability("newCommandTimeout", 60);

              driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
              System.out.println("启动应用程序");
              Thread.sleep(6000);

              // 点击我的
              driver.findElement(By.id("com.mqunar.atom.alexhome:id/atom_alexhome_uc_default")).click();

              SetcontextNames = driver.getContextHandles();
              for (String contextName : contextNames) {
                     // 打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App
                     System.out.println(contextName);
                     if (contextName.contains("WEBVIEW_com.Qunar")) {
                            // 切换到webview模式以便查找web元素
                            driver.context(contextName);
                            System.out.println("切换到webview:"   contextName);
                     }
              }

              Thread.sleep(2000);

              // 打印当前网页源码
              System.out.println(driver.getPageSource());

              Thread.sleep(2000);

              // 点击返回
              driver.findElement(By.className("yo-ico")).click();

              // 切换到App模式
              driver.context("NATIVE_APP");

              System.out.println("切换到App:NATIVE_APP");
              Thread.sleep(2000);

              // 点击首页-机票
              driver.findElement(By.id("com.mqunar.atom.alexhome:id/atom_alexhome_mod_flight")).click();

              Thread.sleep(8000);
              driver.quit();
       }
}

1.3执行脚本

1.3.1模拟器

1、开启Appium服务(任选一种即可)

方式一:开启Appium Server

打开命令行,输入 appium --address 127.0.0.1 --port 4723 --no-reset --session-override

如图所示,Appium服务开启。

方式二:开启Appium Desktop

打开Appium Desktop

如服务IP和端口默认的情况下,直接点击Start Server v1.6.5来开启Appium服务,如图所示。

2、执行测试脚本,鼠标右键Run As--->Java Application。

脚本执行步骤:

(1)启动帮帮应用程序

(2)弹出有新版本提示框,点击一会再说

(3)点击左侧菜单

(4)点击帮助中心

(5)打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App,打印出来的结果:可以看到是混合型App

NATIVE_APP

WEBVIEW_com.xiaoV.BWalletBeta

(6)切换到WEBVIEW_com.xiaoV.BWalletBeta(webview模式)以便查找web元素

(7)打印当前网页源码

(8)点击关于借钱

(9)切换到NATIVE_APP(App模式)

(10)点击返回

(11)关闭帮帮应用程序

脚本执行结束后,控制台打印的信息:

3、在执行测试脚本切换到WebView模式操作中,可能多多少少会遇到一些报错,排除元素定位不对的情况,大部分报错都是WebView与驱动的版本不匹配所产生的。

例如以下报错,提示An unknown server-side error occurred while processing the command. Original error: session not created exception

from unknown error: Runtime.executionContextCreated has invalid 'context': {"auxData":{"frameId":"22596.1","isDefault":true},"id":1,"name":"","origin":"://"}

解决方法就是让WebView版本与驱动版本匹配,让驱动进行降级或者升级。

那如何知道WebView与驱动是否匹配呢?

模拟器开启,打开PC的Chrome浏览器,输入访问地址chrome://inspect/

如图所示,可以检测到udid为192.168.113.101:5555的模拟器

在udid为192.168.113.101:5555的模拟器里,打开要操作的应用程序webview页面,本章示例为打开帮帮应用-帮助中心页面,此时在PC的Chrome浏览器中可以看到帮助中心页的访问链接,如图所示,模拟器里的WebView版本号为44.0.2403.119

被测应用的WebView版本号知道了,接下来开始确定要匹配的驱动版本,与chromedriver版本是否匹配。

chromedriver历史版本下载地址:https://chromedriver.storage.googleapis.com/index.html

chromedriver版本支持的Chrome版本对应列表:

选择指定的chromedriver版本(如图:WebView版本为44.0.2403.119,所以chromedriver版本选为2.20),可根据不同的平台(Win、Mac、Linux)下载指定的chromedriver。

指定的chromedriver下载完成后,双击可看此驱动版本号。

chromedriver应该放在哪里呢?根据所要使用的Appium服务,拷贝到Appium Server或者Appium Desktop的相应目录下即可。拷贝完成后,就可以正常使用了。

在Windows环境下:

Appium Server的chromedriver路径,例如:

C:UsersAdministratorAppDataRoamingnpmnode_modulesappiumnode_modulesappium-chromedriverchromedriverwinchromedriver.exe

Appium Desktop的chromedriver路径,例如:

C:UsersAdministratorAppDataLocalProgramsappium-desktopresourcesappnode_modulesappiumnode_modulesappium-chromedriverchromedriverwinchromedriver.exe

在Mac环境下:

注意,当Appium服务用的是Appium Server时,执行脚本报错为An unknown server-side error occurred while processing the command. Original error: Trying to use a chromedriver binary at the path /usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver, but it doesn't exist!

说明没有找到chromedriver驱动,按报错提示创建相应目录,并把chromedriver驱动拷贝到指定位置里。

Appium Server的chromedriver路径,例如:

/usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver

Appium Desktop的chromedriver路径,例如:

/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver

1.3.2真机

1、开启Appium服务(任选一种即可)

方式一:开启Appium Server

打开命令行,输入 appium --address 127.0.0.1 --port 4723 --no-reset --session-override

如图所示,Appium服务开启。

方式二:开启Appium Desktop

打开Appium Desktop

如服务IP和端口默认的情况下,直接点击Start Server v1.6.5来开启Appium服务,如图所示。

2、执行测试脚本,鼠标右键Run As--->Java Application。

脚本执行步骤:

(1)启动去哪儿应用程序

(2)点击我的

(3)打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App,打印出来的结果:可以看到是混合型App

NATIVE_APP

WEBVIEW_com.Qunar

WEBVIEW_com.iflytek.ringdiyclient

WEBVIEW_com.huawei.wifiprobqeservice

(4)切换到WEBVIEW_com.Qunar(webview模式)以便查找web元素

(5)打印当前网页源码

(6)点击返回

(7)切换到NATIVE_APP(App模式)

(8)点击首页-机票

(9)关闭去哪儿应用程序

脚本执行结束后,控制台打印的信息:

3、在执行测试脚本切换到WebView模式操作中,可能多多少少会遇到一些报错,排除元素定位不对的情况,大部分报错都是WebView与驱动的版本不匹配所产生的。

例如以下报错,提示An unknown server-side error occurred while processing the command. Original error: session not created exception

from unknown error: Runtime.executionContextCreated has invalid 'context': {"auxData":{"frameId":"22596.1","isDefault":true},"id":1,"name":"","origin":"://"}

解决方法就是让WebView版本与驱动版本匹配,让驱动进行降级或者升级。

那如何知道WebView与驱动是否匹配呢?

连接真机后,打开PC的Chrome浏览器,输入访问地址chrome://inspect/

如图所示,可以检测到udid为MYV0215825000026的真机

在udid为MYV0215825000026的真机里,打开要操作的应用程序webview页面,本章示例为打开去哪儿应用-我的页面,此时在PC的Chrome浏览器中可以看到我的页面访问链接,如图所示,真机里的WebView版本号为55.0.2883.91

被测应用的WebView版本号知道了,接下来开始确定要匹配的驱动版本,与chromedriver版本是否匹配。

chromedriver历史版本下载地址:https://chromedriver.storage.googleapis.com/index.html

chromedriver版本支持的Chrome版本对应列表:

选择指定的chromedriver版本(如图:WebView版本为55.0.2883.91,所以chromedriver版本选为2.28),可根据不同的平台(Win、Mac、Linux)下载指定的chromedriver。

指定的chromedriver下载完成后,双击可看此驱动版本号。

chromedriver应该放在哪里呢?根据所要使用的Appium服务,拷贝到Appium Server或者Appium Desktop的相应目录下即可。拷贝完成后,就可以正常使用了。

在Windows环境下:

Appium Server的chromedriver路径,例如:

C:UsersAdministratorAppDataRoamingnpmnode_modulesappiumnode_modulesappium-chromedriverchromedriverwinchromedriver.exe

Appium Desktop的chromedriver路径,例如:

C:UsersAdministratorAppDataLocalProgramsappium-desktopresourcesappnode_modulesappiumnode_modulesappium-chromedriverchromedriverwinchromedriver.exe

在Mac环境下:

注意,当Appium服务用的是Appium Server时,执行脚本报错为An unknown server-side error occurred while processing the command. Original error: Trying to use a chromedriver binary at the path /usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver, but it doesn't exist!

说明没有找到chromedriver驱动,按报错提示创建相应目录,并把chromedriver驱动拷贝到指定位置里。

Appium Server的chromedriver路径,例如:

/usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver

Appium Desktop的chromedriver路径,例如:

/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver

第2章 IOS

2.1创建项目

1、启动Eclipse,鼠标右键New--->Project。

2、创建Java项目,选择Java目录下的Java Project。

3、输入项目名称(例如:My_Appium_Demo),点击Finish完成。

4、创建lib文件夹,用来存放jar包。把Appium Clients jar和Selenium jar包拷贝到文件夹里。

5、创建app文件夹,用来存放应用程序。把应用程序UICatalog.app、VWallet.ipa拷贝到文件夹里。

6、选中拷贝过来的Appium Clients jar和Selenium jar包,鼠标右键Build Path--->Add to Build Path。

7、Appium Clients jar和Selenium jar包已经被项目引用了。

8、选中src源文件夹,鼠标右键New--->Class,创建Java类,输入包名(例如:com.test.demo)、类名(例如:模拟器示例为IOS_Hybrid_Simulator、真机示例为IOS_Hybrid_RealMachine),点击Finish完成。

9、第一个Demo项目,IOS-混合(模拟器/真机)创建完成。

2.2编写脚本

2.2.1模拟器

1、使用Xcode创建模拟器,例如:本章示例模拟器名iPhone 8,IOS版本11.2。

2、关于测试的应用程序:

(1)如果是在模拟器上运行,需要装.app的应用程序文件。

要想在IOS模拟器中运行应用,则必须在Xcode中编译时选择模拟器类型,编译生成的文件后缀为.app

(2)如果是在真机上运行,需要装.ipa的应用程序文件。分为正式版和开发版。

正式版(已经发布到App Store上),可以直接在App Store上下载安装或者可以获取.ipa应用程序文件用命令安装到真机上。

开发版(没有发布到App Store上),只能获取.ipa应用程序文件,并且苹果开发者账号添加此真机的UDID,才可以用命令安装到此真机上。

3、模拟器里没有要测试的应用程序,直接将.app应用程序拖拽到模拟器上进行安装即可。

4、模拟器里没有要测试的应用程序,想在自动化测试执行的时候自动安装。则需要在脚本里添加如下代码:

代码语言:javascript复制
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "app");
File app = new File(appDir, "UICatalog.app");

// `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
// Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
// 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
// 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
capabilities.setCapability("app", app.getAbsolutePath());

5、当模拟器里有要测试的应用程序,每次执行测试脚本可以不用安装被测应用,只要指定bundleId就可以了。

6、在模拟器里测试应用程序,需要指定应用程序的bundleId,因为.app为测试版应用程序,所以bundleId可以询问开发人员提供。

例如:本章UICatalog应用bundleId为com.example.apple-samplecode.UICatalog。

代码语言:javascript复制
// 被测应用的bundle ID
// 用于在真实设备中启动测试,也用于使用其他需要bundle ID的关键字启动测试
// 在使用bundle ID在真实设备上执行测试时,你可以不提供`app`关键字,但你必须提供`udid`
capabilities.setCapability("bundleId", "com.example.apple-samplecode.UICatalog");

7、接下来开始使用查找元素定位工具来获取元素的属性值等信息,那怎么知道所要测试的应用程序是否是混合型的呢?例如使用Appium Desktop的Inspector工具查找元素,有时识别不到webview中的元素,并且显示XCUIElementTypeWebView。

首先打开Appium Desktop,点击Start Server v1.7.2来开启Appium服务。

点击放大镜(Start Inspector Session)。

输入Desired Capabilities相关参数信息。例如:

代码语言:javascript复制
{
  "platformName": "iOS",
  "platformVersion": "11.2",
  "deviceName": "iPhone 8",
  "automationName": "XCUITest",
  "bundleId": "com.example.apple-samplecode.UICatalog"
}

之后点击Start Session。

获取指定的元素信息。

如图所示显示Webview页面,XCUIElementTypeWebView。

8、接下来开始使用查找元素定位工具来获取Webview元素的属性值等信息。

获取Webview元素方式有2种(任选一种即可),元素定位方法同Selenium WebDriver一致。

方式一:通过Mac上的Safari

首先将模拟器上的应用程序打开,之后打开此应用显示的Webview页面;之后打开Mac上的Safari,选择开发--->模拟器,可以看到此时模拟器打开的Webview页面,例如:苹果首页。

点击苹果首页的链接,会弹出新窗口,显示苹果首页的html源码信息,则可以获取相应的Webview元素信息。

方式二:通过ios_webkit_debug_proxy工具

首先将模拟器上的应用程序打开,之后打开此应用显示的Webview页面;

之后在Mac上打开终端,输入启动代理命令

ios_webkit_debug_proxy -f chrome-devtools://devtools/bundled/inspector.html

Mac上打开Chrome浏览器,在地址栏输入http://localhost:9221/,这里会显示所有已连接的设备清单,选择一个设备并点击打开。例如:模拟器

此时检测到模拟器上打开的Webview页面,例如苹果首页

选中后,鼠标右键点击转到……

打开选中的页面,将Chrome的开发者工具打开,显示html源码信息,则可以获取相应的Webview元素信息。

或者,选中后,鼠标右键复制链接地址

例如:

chrome-devtools://devtools/bundled/inspector.html?ws=localhost:9222/devtools/page/1

打开Chrome新窗口,将复制的地址粘贴后访问

显示html源码信息,则可以获取相应的Webview元素信息。

9、切换NATIVE_APP还是WEBVIEW_被测进程名称,使用context方法。

10、脚本代码:

代码语言:javascript复制
package com.test.demo;
import java.io.File;
import java.net.URL;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.IOSElement;
/**
 * IOS-混合-模拟器
 *
 * @author wangmcn
 *
 */
public class IOS_Hybrid_Simulator {
       public static void main(String[] args) throws Exception {
              IOSDriverdriver;
              File classpathRoot = new File(System.getProperty("user.dir"));
              File appDir = new File(classpathRoot, "app");
              File app = new File(appDir, "UICatalog.app");
              DesiredCapabilities capabilities = new DesiredCapabilities();

              // 使用哪个自动化测试引擎
              // 默认为Appium,或Selendroid或UiAutomator2或Espresso用于Android;或XCUITest用于IOS
              capabilities.setCapability("automationName", "Appium");

              // 使用哪个移动操作系统平台
              // iOS, Android, FirefoxOS
              capabilities.setCapability("platformName", "iOS");

              // 移动操作系统版本
              capabilities.setCapability("platformVersion", "11.2");

              // 使用的移动设备或模拟器的类型
              // iPhone Simulator, iPad Simulator, iPhone Retina 4-inch
              // Android Emulator, Galaxy S4 等等
              // 在IOS上,这个关键字的值必须是使用`instruments -s devices`得到的可使用的设备名称之一
              // 在Android上,这个关键字目前不起作用
              capabilities.setCapability("deviceName", "iPhone 8");

              // `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
              // Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
              // 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
              // 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
              capabilities.setCapability("app", app.getAbsolutePath());

              // 被测应用的bundle ID
              // 用于在真实设备中启动测试,也用于使用其他需要bundle ID的关键字启动测试
              // 在使用bundle ID在真实设备上执行测试时,你可以不提供`app`关键字,但你必须提供`udid`
              capabilities.setCapability("bundleId", "com.example.apple-samplecode.UICatalog");

              // 设置为true,每次启动时覆盖session,否则第二次运行会报错不能新建session
              capabilities.setCapability("sessionOverride", true);

              // 在此会话之前不要重置应用程序状态
              // Android 不要停止应用程序,不要清除应用程序数据,也不要卸载apk
              // IOS 测试后不要销毁或关闭SIM卡。开始测试运行在任何模拟运行,或设备插入
              capabilities.setCapability("noReset", true);

              // 执行完整的重置
              // Android 停止应用程序,清除应用程序数据并在测试后卸载apk
              // IOS 在真机设备测试后卸载应用程序,在模拟器测试后摧毁模拟器
              capabilities.setCapability("fullReset", false);

              // 设置命令超时时间,单位:秒
              // 达到超时时间仍未接收到新的命令时Appium会假设客户端退出然后自动结束会话
              capabilities.setCapability("newCommandTimeout", 60);

              // Appium中使用IWDP,指的就是ios-webkit-debug-proxy
              capabilities.setCapability("startIWDP", true);

              // 当IOS的个人信息访问警告(如:位置、联系人、图片)出现时,自动选择接受(Accept),默认值`false`
              capabilities.setCapability("autoAcceptAlerts", false);

              driver = new IOSDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
              System.out.println("启动UICatalog应用程序");
              Thread.sleep(2000);

              // 向下滑动
              driver.swipe(170, 430, 170, 230, 1000);

              Thread.sleep(2000);

              // 向下滑动
              driver.swipe(170, 430, 170, 230, 1000);

              Thread.sleep(2000);

              // 点击Web View
              driver.findElement(By.name("Web View")).click();

              Thread.sleep(5000);

              SetcontextNames = driver.getContextHandles();
              for (String contextName : contextNames) {
                     // 打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App
                     System.out.println(contextName);
                     if (contextName.contains("WEBVIEW")) {
                            // 切换到webview模式以便查找web元素
                            driver.context(contextName);
                            System.out.println("切换到webview:"   contextName);
                     }
              }

              Thread.sleep(2000);

              // 打印当前网页源码
              System.out.println(driver.getPageSource());

              Thread.sleep(2000);

              // 切换到App模式
              driver.context("NATIVE_APP");

              System.out.println("切换到App:NATIVE_APP");
              Thread.sleep(2000);

              // 点击返回
              driver.findElement(By.name("UICatalog")).click();

              Thread.sleep(2000);
              driver.quit();
       }
}

2.2.2真机

1、首先获取真机udid设备标识,终端输入 idevice_id -l

如图所示:显示该真机的udid信息。

2、关于测试的应用程序:

(1)如果是在模拟器上运行,需要装.app的应用程序文件。

要想在IOS模拟器中运行应用,则必须在Xcode中编译时选择模拟器类型,编译生成的文件后缀为.app

(2)如果是在真机上运行,需要装.ipa的应用程序文件。分为正式版和开发版。

正式版(已经发布到App Store上),可以直接在App Store上下载安装或者可以获取.ipa应用程序文件用命令安装到真机上。

开发版(没有发布到App Store上),只能获取.ipa应用程序文件,并且苹果开发者账号添加此真机的UDID,才可以用命令安装到此真机上。

3、本章示例使用的是真机,测试开发版帮帮应用(通过访问非App Store渠道下载帮帮应用安装到真机上)。

4、真机设备里没有要测试的应用程序,可以在执行自动化测试前先安装到设备里,输入安装命令ideviceinstaller -i [xxx.ipa] -o [设备udid] 进行安装,或者使用手机扫描应用程序二维码进行下载安装。例如:

ideviceinstaller -i /Users/automation/test/VWallet.ipa -o c5dc675bddf7d1ac6d91783d5224d72b427f8d04

5、真机设备里没有要测试的应用程序,想在自动化测试执行的时候自动安装。则需要在脚本里添加如下代码:

代码语言:javascript复制
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "app");
File app = new File(appDir, "VWallet.ipa");

// `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
// Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
// 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
// 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
capabilities.setCapability("app", app.getAbsolutePath());

6、真机设备里有要测试的应用程序,每次执行测试脚本可以不用安装被测应用,只要指定bundleId就可以了。

7、获取应用程序的bundleId,打开终端,输入 ideviceinstaller -l

如图所示:本章示例帮帮应用的bundleId为com.xiaoV.BangWalletBeta。

代码语言:javascript复制
// 被测应用的bundle ID
// 用于在真实设备中启动测试,也用于使用其他需要bundle ID的关键字启动测试
// 在使用bundle ID在真实设备上执行测试时,你可以不提供`app`关键字,但你必须提供`udid`
capabilities.setCapability("bundleId", "com.xiaoV.BangWalletBeta");

8、因测试开发版应用,在Appium执行的时候,要加

"xcodeOrgId": "< Apple开发者账户中的Team ID >",

"xcodeSigningId": "< 打包时证书的名字 >"

这两个参数。

如何获取TeamID?

登录https://developer.apple.com/account/ 里左侧的 Membership 中找到。

脚本添加如下参数:

代码语言:javascript复制
// Apple开发者帐户中的Team ID
capabilities.setCapability("xcodeOrgId", "69XXXXXXXX");

// 打包时证书的名字
capabilities.setCapability("xcodeSigningId", "iPhone Developer");

9、接下来开始使用查找元素定位工具来获取元素的属性值等信息,那怎么知道所要测试的应用程序是否是混合型的呢?例如使用Appium Desktop的Inspector工具查找元素,有时识别不到webview中的元素,并且显示XCUIElementTypeWebView。

首先打开Appium Desktop,点击Start Server v1.6.5来开启Appium服务。

点击放大镜(Start Inspector Session)。

输入Desired Capabilities相关参数信息。例如:

代码语言:javascript复制
{
  "platformName": "iOS",
  "platformVersion": "11.1",
  "deviceName": "test",
  "automationName": "XCUITest",
  "bundleId": "com.xiaoV.BangWalletBeta",
  "udid": "c5dc675bddf7d1ac6d91783d5224d72b427f8d04",
  "xcodeOrgId": "69XXXXXXXX",
  "xcodeSigningId": "iPhone Developer"
}

之后点击Start Session。

获取指定的元素信息。

如图所示显示Webview页面,XCUIElementTypeWebView。

10、接下来开始使用查找元素定位工具来获取Webview元素的属性值等信息。

获取Webview元素方式有2种(任选一种即可),元素定位方法同Selenium WebDriver一致。

方式一:通过Mac上的Safari

首先将真机设备上的应用程序打开,之后打开此应用显示的Webview页面;之后打开Mac上的Safari,选择开发--->真机设备(如图:设备名为test),可以看到此时真机设备打开的Webview页面,例如:帮帮应用的帮助中心页面。

点击帮助中心页面的链接,会弹出新窗口,显示帮助中心页面的html源码信息,则可以获取相应的Webview元素信息。

方式二:通过ios_webkit_debug_proxy工具

首先将真机设备上的应用程序打开,之后打开此应用显示的Webview页面;

之后在Mac上打开终端,输入启动代理命令

ios_webkit_debug_proxy -f chrome-devtools://devtools/bundled/inspector.html

Mac上打开Chrome浏览器,在地址栏输入http://localhost:9221/,这里会显示所有已连接的设备清单,选择一个设备并点击打开。例如:真机设备(test)

此时检测到真机设备上打开的Webview页面,例如:帮助中心页面

选中后,鼠标右键点击转到……

打开选中的页面,将Chrome的开发者工具打开,显示html源码信息,则可以获取相应的Webview元素信息。

或者,选中后,鼠标右键复制链接地址

例如:

chrome-devtools://devtools/bundled/inspector.html?ws=localhost:9223/devtools/page/1

打开Chrome新窗口,将复制的地址粘贴后访问

显示html源码信息,则可以获取相应的Webview元素信息。

11、切换NATIVE_APP还是WEBVIEW_被测进程名称,使用context方法。

12、脚本代码:

代码语言:javascript复制
package com.test.demo;
import java.io.File;
import java.net.URL;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.IOSElement;
/**
 * IOS-混合-真机
 *
 * @author wangmcn
 *
 */
public class IOS_Hybrid_RealMachine {
       public static void main(String[] args) throws Exception {
              IOSDriverdriver;
              File classpathRoot = new File(System.getProperty("user.dir"));
              File appDir = new File(classpathRoot, "app");
              File app = new File(appDir, "VWallet.ipa");
              DesiredCapabilities capabilities = new DesiredCapabilities();

              // 使用哪个自动化测试引擎
              // 默认为Appium,或Selendroid或UiAutomator2或Espresso用于Android;或XCUITest用于IOS
              capabilities.setCapability("automationName", "Appium");

              // 使用哪个移动操作系统平台
              // iOS, Android, FirefoxOS
              capabilities.setCapability("platformName", "iOS");

              // 移动操作系统版本
              capabilities.setCapability("platformVersion", "11.1");

              // 使用的移动设备或模拟器的类型
              // iPhone Simulator, iPad Simulator, iPhone Retina 4-inch
              // Android Emulator, Galaxy S4 等等
              // 在IOS上,这个关键字的值必须是使用`instruments -s devices`得到的可使用的设备名称之一
              // 在Android上,这个关键字目前不起作用
              capabilities.setCapability("deviceName", "test");

              // 连接的物理设备的唯一设备标识
              capabilities.setCapability("udid", "c5dc675bddf7d1ac6d91783d5224d72b427f8d04");

              // `.ipa`或`.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`
              // Appium会先尝试安装路径对应的应用在适当的真机或模拟器上
              // 针对Android,如果你指定`app-package`和`app-activity`的话,那么就可以不指定`app`
              // 例如/abs/path/to/my.apk or http://myapp.com/app.ipa
              capabilities.setCapability("app", app.getAbsolutePath());

              // 被测应用的bundle ID
              // 用于在真实设备中启动测试,也用于使用其他需要bundle ID的关键字启动测试
              // 在使用bundle ID在真实设备上执行测试时,你可以不提供`app`关键字,但你必须提供`udid`
              capabilities.setCapability("bundleId", "com.xiaoV.BangWalletBeta");

              // 设置为true,每次启动时覆盖session,否则第二次运行会报错不能新建session
              capabilities.setCapability("sessionOverride", true);

              // 在此会话之前不要重置应用程序状态
              // Android 不要停止应用程序,不要清除应用程序数据,也不要卸载apk
              // IOS 测试后不要销毁或关闭SIM卡。开始测试运行在任何模拟运行,或设备插入
              capabilities.setCapability("noReset", true);

              // 执行完整的重置
              // Android 停止应用程序,清除应用程序数据并在测试后卸载apk
              // IOS 在真机设备测试后卸载应用程序,在模拟器测试后摧毁模拟器
              capabilities.setCapability("fullReset", false);

              // 设置命令超时时间,单位:秒
              // 达到超时时间仍未接收到新的命令时Appium会假设客户端退出然后自动结束会话
              capabilities.setCapability("newCommandTimeout", 60);

              // Apple开发者帐户中的Team ID
              capabilities.setCapability("xcodeOrgId", "69XXXXXXXX");

              // 打包时证书的名字
              capabilities.setCapability("xcodeSigningId", "iPhone Developer");

              // Appium中使用IWDP,指的就是ios-webkit-debug-proxy
              capabilities.setCapability("startIWDP", true);

              // 当IOS的个人信息访问警告(如:位置、联系人、图片)出现时,自动选择接受(Accept),默认值`false`
              capabilities.setCapability("autoAcceptAlerts", false);

              driver = new IOSDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
              System.out.println("启动帮帮应用程序");
              Thread.sleep(6000);

              // 弹出有新版本提示框,点击一会再说
              driver.findElement(By.name("一会再说")).click();

              Thread.sleep(2000);

              // 点击左侧菜单
              driver.findElement(By.name("logout Sidebar")).click();

              Thread.sleep(2000);

              // 点击帮助中心
              driver.findElement(By.name("帮助中心")).click();

              Thread.sleep(5000);

              SetcontextNames = driver.getContextHandles();
              for (String contextName : contextNames) {
                     // 打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App
                     System.out.println(contextName);
                     if (contextName.contains("WEBVIEW")) {
                            // 切换到webview模式以便查找web元素
                            driver.context(contextName);
                            System.out.println("切换到webview:"   contextName);
                     }
              }

              Thread.sleep(2000);

              // 打印当前网页源码
              System.out.println(driver.getPageSource());

              Thread.sleep(2000);

              // 点击关于借钱
              driver.findElement(By.xpath(".//*[@id='question-list']/section/div[1]/ul/li[2]")).click();

              Thread.sleep(2000);

              // 切换到App模式
              driver.context("NATIVE_APP");

              System.out.println("切换到App:NATIVE_APP");
              Thread.sleep(2000);

              // 点击返回
              driver.findElement(By.name("btn back")).click();

              Thread.sleep(2000);
              driver.quit();
       }
}

2.3执行脚本

2.3.1模拟器

1、开启Appium服务(任选一种即可)

方式一:开启Appium Server

打开终端,输入 appium --address 127.0.0.1 --port 4723 --no-reset --session-override

如图所示,Appium服务开启。

方式二:开启Appium Desktop

打开Appium Desktop

如服务IP和端口默认的情况下,直接点击Start Server v1.7.2来开启Appium服务,如图所示。

2、执行测试脚本,鼠标右键Run As--->Java Application。

脚本执行时,Appium Desktop或Appium Server自动将WDA(WebDriverAgent)安装到模拟器上。

脚本执行步骤:

(1)启动UICatalog应用程序

(2)向下滑动

(3)向下滑动

(4)点击Web View

(5)打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App,打印出来的结果:可以看到是混合型App

NATIVE_APP

WEBVIEW_6650.1(每次执行时WEBVIEW值是变化的,不是固定的)

(6)切换到WEBVIEW_6650.1(webview模式)以便查找web元素

(7)打印当前网页源码

(8)切换到NATIVE_APP(App模式)

(9)点击返回

(10)关闭UICatalog应用程序

脚本执行结束后,控制台打印的信息:

2.3.2真机

1、开启Appium服务(任选一种即可)

方式一:开启Appium Server

打开终端,输入 appium --address 127.0.0.1 --port 4723 --no-reset --session-override

如图所示,Appium服务开启。

方式二:开启Appium Desktop

打开Appium Desktop

如服务IP和端口默认的情况下,直接点击Start Server v1.6.5来开启Appium服务,如图所示。

2、执行测试脚本,鼠标右键Run As--->Java Application。

脚本执行步骤:

(1)启动帮帮应用程序

(2)弹出有新版本提示框,点击一会再说

(3)点击左侧菜单

(4)点击帮助中心

(5)打印出被测App是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App,打印出来的结果:可以看到是混合型App

NATIVE_APP

WEBVIEW_20(每次执行时WEBVIEW值是变化的,不是固定的)

(6)切换到WEBVIEW_20(webview模式)以便查找web元素

(7)打印当前网页源码

(8)点击关于借钱

(9)切换到NATIVE_APP(App模式)

(10)点击返回

(11)关闭帮帮应用程序

脚本执行结束后,控制台打印的信息:

0 人点赞