npm install -g appium
(需要爬墙)npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install -g appium
cnpm install appium-docter
pip install appium-python-client
from appium.webdriver.webdriver import WebDriver
from appium.webdriver.common.touch_action import TouchAction
import yaml
import pytest
from time import sleep
'''创建一个基础页面类,用于封装公共模块的处理方法
和根据yaml配置文件进行案例的测试步骤'''
class BasePage:
_blackList = [] # 黑名单列表,用于处理再case运行过程中可能出现的未知弹窗
_errorCount = 0 # 定位元素的错误次数,元素定位中可能出现一次定位不到
_errorMax = 5 # 允许进行元素定位的最大错误次数
def __init__(self, driver: WebDriver = None): # 初始化driver
self._driver = driver
def find(self, by, locator): # $by>定位元素的方法,$locator>定位元素对应的所需value
try:
if isinstance(by, tuple): # 如果传入的定位是个元组形式,包括方法和locator,就进行解包的方式定位
element = self._driver.find_element(*by)
else:
element = self._driver.find_element(by, locator)
self._errorCount = 0 # 找到元素,错误次数为0
return element
except Exception as e:
self._errorCount += 1 # 未找到该元素,错误次数加1
if self._errorCount >= self._errorMax:
raise e # 错误次数大于设置的最大次数抛出异常
for black in self._blackList:
elements = self._driver.find_elements(*black) # 找到黑名单列表里的所有元素,[(by, locator),]的形式设置
if len(elements) > 0: # 出现弹框匹配黑名单列表大于0,即出现未知弹框
elements[0].click() # 点击过后就找不到该元素了,所以永远点击第一个找到的就可以了
return self.find(by, locator) # 点击后返回原方法,轮询去让定位可以继续执行
raise e # 没有找到,抛出异常
def send(self, by, locator, value): # 数据输入的方法
try:
self._driver.find(by, locator).send_keys(value) # 定位到输入的位置,输入值
self._errorCount = 0
except Exception as e:
self._errorCount += 1
if self._errorCount >= self._errorMax:
raise e # 大于错误次数,抛出异常
for black in self._blackList:
elements = self._driver.find_element(*black)
if len(elements) > 0:
elements[0].click()
return self.find(by, locator)
raise e
def steps(self, path): # 定义操作步骤的方法,用于通过编写配置文件,执行相关用例
with open(path, 'r', encoding='utf-8') as f:
steps: list[dict] = yaml.safe_load(f) # 操作步骤的数据类型为:[{},{}]
# 遍历操作步骤
for step in steps:
if 'by' in step.keys():
element = self.find(step['by'], step['locator']) # 定位到元素
# 要进行的动作操作
if 'action' in step.keys():
if 'click' == step['action']: # 点击操作
element.click()
if 'send' == step['action']:
element.send_keys(step['value'])
if 'TouchAction' in step['action']: # 滑动操作
action = TouchAction(self._driver)
action.press(x=step['value'][0]['x_start'], y=step['value'][0]['y_start']).wait(300)\
.move_to(x=step['value'][1]['x_end'], y=step['value'][1]['y_end']).release().perform()
# 断言
if 'assertion' in step.keys():
if "sleep" in step['assertion'].keys():
sleep(step['assertion']['sleep'])
element = self.find(step['assertion']['by'], step['assertion']['locator'])
attribute = element.get_attribute(step['assertion']['attribute'])
pytest.assume(attribute == step['assertion']['assert_info'])
if 'back' in step.keys():
self._driver.back()
from appium import webdriver
from Page.basepage import BasePage
from Page.main import Main
class App(BasePage):
# 启动app
def start(self):
_package = "com.netease.cloudmusic"
_activity = ".activity.LoadingActivity"
if self._driver is None:
desir_cap = {
"appPackage": _package,
"appActivity": _activity,
"platformName": "Android",
"platformVersion": "10",
"dontStopAppOnReset": "true",
"noReset": "true",
"deviceName": "6de9e7a2"
}
self._driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desir_cap)
self._driver.implicitly_wait(5) # 隐式等待5s
else:
self._driver.start_activity(_package, _activity)
return self
def main(self):
return Main(self._driver)
from Page.basepage import BasePage
# 发现page
class Discovery(BasePage):
def daily_recommendation(self):
self.steps("../TestData/discovery.yml")
from Page.basepage import BasePage
from Page.discovery import Discovery
# 该类为进入不同页面(对<我的,发现,云村,视频>四个页面建模page的调配page
class Main(BasePage):
def quit(self):
self._driver.quit()
def go_discover(self): # 进入发现页
self.steps('../TestData/main.yml')
return Discovery(self._driver)
from Page.app import App
import pytest
class TestDiscovery:
def setup_class(self):
self.testDriver = App().start().main()
def teardown_class(self):
self.testDriver.quit()
def test_daily_recommendation(self):
self.testDriver.go_discover().daily_recommendation()
-
by: accessibility id
locator: 我的推荐
discovery.yml
-
by: accessibility id
locator: 搜索
action: click
-
by: id
locator: com.netease.cloudmusic:id/search_src_text
action: send
value: 似是故人来
-
by: id
locator: com.netease.cloudmusic:id/adBannerView
action: click
到此一个简单的PO模式的UI自动化测试就完成了,后边的一些其他类型的操作验证可以结合自己项目自行进行添加改进,本主也会更新完善该网易云实例的各种操作;谢谢观看!!!
欢迎请喝咖啡
如对本文有疑问, 点击进行留言回复!!
Android安卓水滴屏适配状态栏图标(图标过多时显示一个点)
android studio使用Flutter创建web项目
android如何使用taskAffinity属性对任务栈操作控制
android对PDF文件的操作(上传、预览、下载和转存相册)
网友评论