Appium上下文和H5测试(二)

坚持原创输出,点击蓝字关注我吧

做者:清菡
博客:oschina、云+社区、知乎等各大平台都有。html

文章总览图

1、往期回顾

loc='new UiSelector().text("全程班")'
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.ANDROID_UIAUTOMATOR,loc))
driver.find_element_by_android_uiautomator(loc).click()

这个步骤后进入了这个页面:android

进入这个页面也是须要时间的。WebView 这个元素当中,放的才是 html 页面。真的等到 html 页面加载出来以后,再去获取全部相关的内容,这样比较好。web

万一切过来的时候,html 页面尚未开始加载,我就立刻去获取当前全部能够操做的对象,这样很容易丢失,因此也同样要讲究等待。chrome

讲究等待,首先等到 WebView 这个元素出现。等到 WebView 这个 class 控件出现,class 值表明它的控件。session

# 等待Web View元素出现  -Web View里面放的是Html
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.CLASS_NAME,'android.webkit.WebView')))

sleep1 秒钟,确保里面的 html,全部的都能加载完成。app

time.sleep(1)koa

2、怎么切换?

用什么样的语句来获取咱们的 WebView、获取咱们的原生控件呢?

它这个东西在咱们 App 当中叫作context,翻译成中文就是上下文。编辑器

上下文在咱们自动化中就是指能够切换的东西,就是咱们的原生控件。 原生控件是咱们默认的,就像窗口切换就是咱们默认的窗口是同样的。原生控件是它的默认上下文。打开 app,默认就是在它的原生控件当中。布局

WebView 就是它的第二种context测试

只要当前页面中有 WebView,它就会显示出来,有 2 个就会显示 2 个。如图片中这个例子中只有一个 Webview,因此它只显示一个 WebView。

这就是context上下文。

只有这种状况下须要切换,其它状况下都是原生控件就不须要切换,不用管它,一旦有 html 页面就须要考虑这些事情了。

3、上下文切换

可用的上下文(Contexts)

列出全部可用的上下文(contexts)

driver.contexts

driver.window_handles 获取全部窗口的 handle,返回 list 列表。

当前上下文(context):列出当前的上下文(context)

driver.current_context

切换至默认的上下文(context)

切换回默认的上下文(context)。(译者注:通常就是原生上下文 “NATIVE_APP”)

driver.switch_to.context(None)

当前 Activity:获取当前的 Acticity。仅支持 Android。

driver.current_activity

当前包名(package):获取当前包名(package)。仅支持 Android 。

driver.current_package

上下文的操做方式在这里,和 Windows 窗口是如出一辙的。和 Web 自动化中所谓的窗口是同样的。

首先列出全部可用的上下文。就像列出目前全部打开的窗口是同样的。

这个上下文,有 WebView 的时候,也是在执行代码的时候,它进入了有 WebView 的页面当中,才会有多个,没有进入有 WebView 的页面当中只有一个 WebView 的(至关于一个大箱子,箱子打开后有多个)。

列出全部可用的上下文,再去切换至须要的上下文。怎么切换呢?他们获得的结果也是个列表啊。

列表当中放的值呢,不是原生控件就是 WebView。因此它也有下标。若是要切换的话就是driver.switch_to.context(None)

None 表示什么呢?

表示切换回默认的上下文,按照 Web 自动化的讲法就是默认的窗口,在咱们这里就是默认的原生控件里面。

若是你想切换到 WebView 的话,driver.contexts返回值 0,列表取下标 1,2,3,4 都是能够取得。也能够将你获得的 Web 名称放在driver.switch_to.context(None)中替换 None 就能够了。

driver.switch_to.context(None)能够切进去,也能够切出来。若是你想获取当前的窗口,当前的上下文,叫作driver.current_context

它的作法与窗口是如出一辙的。Web 自动化中叫作窗口,这里叫作上下文。 其它的时候不须要切换,可是有窗口须要交替的时候就必需要切换。有 iframe,须要更换 html 页面的时候就须要切换,其它状况下就不切换。

如今在这个地方已经等到了这个全部的 WebView 出现了,因此接下来这样作:

button[@class="bottom-btn buy"]

至关于 App 自动化和 Web 自动化组合起来用了,无缝切换,不须要改什么,照着套路用就行了:

# 切换以后:当前的操做对象:html页面。
# 等待元素可见
# 由于是通用的,因此接下来的代码是web自动化的代码
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.XPATH,'//button[@class="bottom-btn buy"]')))
# 这个用Mobileby或者By都无所谓。
driver.find_element_by_xpath('//button[@class="bottom-btn buy"]').click()

列出了当前的上下文:

['NATIVE_APP', 'WEBVIEW_com.tencent.mobileqq:mini', 'WEBVIEW_com.保密']

NATIVE_APP 是当前的原生控件,按照 web 自动化来讲,是默认的主窗口。

是由于这段代码:

# 一、先列出全部的context
cons=driver.contexts  #列表
#也是按照出现的前后顺序,WebView是操做过程当中才出现的,因此它确定排队。
print(cons)

必定要开启 webview debug 属性,若是你没有开启它,那么这 2 项,在这里获取的时候是看不到的:

就只有一个了,就是 NATIVE_APP。只能看到 NATIVE_APP 是切换不到 WebView 的。必定要保证可以识别获得,才可以去切换。

技巧: 报错的时候先看第一行代码,看看在你本身当前脚本当中究竟是哪一行出错了。

4、样例代码

手机设置中开启着显示布局边界的状况下,而后 run 代码。由于 App 界面有变动,因此代码和现有界面不一致,即当即购买如今成了报名截止并跳转至 QQ 界面。代码提示找不到元素请不要奇怪,由于为了便于理解,放的元素仍是当即购买的元素。

此代码只是样例,不必定保证在你的电脑上就能运行成功,请根据实际状况修改。

from appium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium.webdriver.common.mobileby import MobileBy


desired_caps={}
# 平台类型
desired_caps["platformName"]="Android"
# 平台版本号
desired_caps["platformVersion"]="10"
# 设备名称
desired_caps["deviceName"]="2NSDU20410017297"
# app 包名
desired_caps["appPackage"]="输入appPackage"
# app 入口 acitivity
desired_caps["appActivity"]="输入appActivity"


# 链接Appium server。前提:appium desktop要启动。有监听端口。
# 将desired_caps发送给appium server。打开app
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)

loc='new UiSelector().text("全程班")'
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.ANDROID_UIAUTOMATOR,loc)))
driver.find_element_by_android_uiautomator(loc).click()



# 等待Web View元素出现  -Web View里面放的是Html
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.CLASS_NAME,'android.webkit.WebView')))
# 由于只是等它这个元素出现了,至于里面的html有没有加载完成,并非很肯定。
time.sleep(1)#为了稳定起见,稍微sleep 1秒,确保里面的Html,全部的都能加载完成。

# 前提:能够识别到WebView,
# 这个识别不是肉眼识别,而是经过调用代码的时候能够识别。须要开启app的webview debug调试属性,对外可见。

# context  #原生控件 #webview

# 一、先列出全部的context
cons=driver.contexts  #列表
#也是按照出现的前后顺序,WebView是操做过程当中才出现的,因此它确定排队。
print(cons)

# 二、切换至WebView,要确保chromedriver的版本要与webView的版本匹配。也要放置在对应的位置。
driver.switch_to.context(cons[-1])#这个地方没有给你提示,不表明你错了,照着操做就行了。
# 先写个-1,由于如今不知道WebView的名字。可是知道WebView必定是出如今最后的就能够了。

# 三、切换以后:当前的操做对象:html页面。
# 等待元素可见
# 由于是通用的,因此接下来的代码是web自动化的代码
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.XPATH,'//button[@class="bottom-btn buy"]')))
# 这个用Mobileby或者By都无所谓。
driver.find_element_by_xpath('//button[@class="bottom-btn buy"]').click()
# 这里为何用MobileBy.XPATH而不是By.XPATH?
# MobileBy这个类继承了By,因此这个用Mobileby或者By都无所谓。
# 原理:你们背后走的都是同一套逻辑,同一段请求,同一种命令。都是find_element
# 只不过咱们查找元素的方式不同。因此它只是一个外部的形式而已,在内部也是同样的。
# 即使用Selenium Webdriver 写代码,也能够把MobileBy引进来,只要我不去用移动端的定位方式,都是能够作的。

遇到的问题

appium 报错 session not created: This version of ChromeDriver only supports Chrome version 84

靠谱连接: https://www.codenong.com/jsb8d9e8746809/

舒适提示: 若是你的代码没问题,还报错,那么就换 Appium 版本吧,Appium 的 bug 不少。

上篇文章 中此处代码错了,应该改为这样:


公众号 清菡软件测试 首发,更多原创文章:清菡软件测试 95+原创文章,欢迎关注、交流,禁止第三方擅自转载。

相关文章
相关标签/搜索