1)webView结构和原理:
以下是三种app框架,从左到右是:原生(find_element)、webview、h5
webview: Android系统中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装为一个叫做 WebView 组件,属于前端(与用户打交道的都叫前端)
模拟器上的测试:
webview控件会被映射为原生控件,类型为view,其中的文本内容会变成content-desc或者text,content-desc对应的属性是accessibility-id
android6.0会把webview中的控件变成一个带有content.desc属性的view控件
android9.0会把webview中的控件变成一个带有text属性的view控件
真机:
如果app未开启webview的调试属性,是无法分析内部的控件的
个别手机可能会默认打开此属性,所以默认可能也能访问h5内部的控件
如果还是访问不到,此时需要让研发人员配合打开webview的调试属性
webview测试用例:
不要css定位,直接使用(accessibility-id或者xpath直接定位)
如果需要css定位及其它的js执行功能:contexts api
contexts api+selenium css定位
webview在APP中的体现:webkit.WebView就是个webview组件
2)webview技术原理
(1)adb -s 设备编号 shell cat /proc/net/unix | grep webview #查找所有的webview进程,设备编号是指adb devices命令查出来的编号
(2)adb -s 设备编号 forwad tcp:7777 localabstract:webview_devtools_remote_25352 #执行该命令的意思:访问本机777端口相当于访问webview_devtools_remote_25352
(3)adb forward --list
(4)curl http://127.0.0.1/json/version
3)显示等待:
#显示等待需要的库
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#代码段1
WebDriverWait(cls.driver,20).until(EC.presence_of_element_located((MobileBy.XPATH,"//*[@text='交易']")))
cls.driver.find_element_by_xpath("//*[@text='交易']").click()
#代码段2
element1=self.driver.find_element_by_accessibility_id("立即开户")
WebDriverWait(self.driver,10).until(EC.presence_of_element_located((MobileBy.ACCESSIBILITY_ID,"立即开户")))
示例代码:
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#
class Testxueqiuan(object):
driver = WebDriver # 不写这句,识别不出find方法
@classmethod
def setup_class(cls): # 整体初始化
print('setup class在当前class中只执行一次')
# cls.driver = cls.installapp() # 加上cls变成类变量
# el1 = cls.driver.find_element_by_id("com.xueqiu.android:id/user_profile_icon")
# el1.click() # 到点击登陆的页面
cls.driver=cls.restartapp()
WebDriverWait(cls.driver,20).until(EC.presence_of_element_located((MobileBy.XPATH,"//*[@text='交易']")))
cls.driver.find_element_by_xpath("//*[@text='交易']").click()
def setup_method(self): # 每一个方法
print('setup method在每个方法执行前中执行一次')
self.driver = Testxueqiuan.driver # 局部变量
self.driver.find_element_by_xpath("//*[@text='交易']").click()
"""
def test_login_weixn(self):
el3 = self.driver.find_element_by_id("rl_login_by_wx") # 选择登陆的页面
el3.click()
"""
def test_webview_a(self):
self.driver.find_element_by_accessibility_id("A股开户").click()
element1=self.driver.find_element_by_accessibility_id("立即开户")
#ef __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)
WebDriverWait(self.driver,10).until(EC.presence_of_element_located((MobileBy.ACCESSIBILITY_ID,"立即开户")))
@classmethod
def installapp(cls) -> WebDriver:
caps = {}
# caps['app']='' #安装apk
caps["platformName"] = "android"
caps["deviceName"] = "demo"
caps["app"] = "com.xueqiu.android"
caps["appActivity"] = "view.WelcomeActivityAlias"
#caps["udid"] = "*****"
# 解决第一次启动时赋值权限
caps["autoGrantPermissions"] = "true"
driver = webdriver.Remote("http://localhost:5723/wd/hub", caps)
driver.implicitly_wait(10) # 隐式等待
return driver
@classmethod
def restartapp(cls) -> WebDriver:
caps = {}
caps["platformName"] = "android"
caps["deviceName"] = "demo"
caps["app"] = "com.xueqiu.android"
caps["appActivity"] = "view.WelcomeActivityAlias"
caps["autoGrantPermissions"] = "true"
caps['noreset'] = 'true' # 这个选项为true,保留之前的操作数据
driver = webdriver.Remote("http://localhost:5723/wd/hub", caps)
driver.implicitly_wait(10) # 隐式等待
return driver
def teardown_method(self):
self.driver.back()