前言
本章主要讲述针对【企业微信App】进行AppUI自动化测试框架的搭建
- ps:这里底层用的是Appnium,另外写了一下底层Uiautomator2的简单搭建
- UIautomator2框架搭建实战:
https://blog.csdn.net/Makasa/article/details/124358921
基础环境搭建(环境这part我就不多介绍了,大家可以翻看我以前的相关博客)
-
Appnuim v1.15.1:
https://blog.csdn.net/Makasa/article/details/121287286 -
android-sdk
https://www.cnblogs.com/ycl-2021/p/15355386.html -
jdk1.8 (blog第二部分):
https://blog.csdn.net/Makasa/article/details/107558070 -
python 3
-
pyCharm开发工具
一、整体框架介绍
base包:封装基础类
case包:封装测试用例类
datas包:参数化数据(excel 或者 yml...)
logs包:封装日志
page包:封装所有的页面
utils包:工具包,例如读取参数化数据
二、框架搭建
Base包:
1、先创建一个BasePage.py
- 为什么要单独封装一个BasePage呢?如果说以后我们不用webdriver这个框架了,我们只需要更改BasePage即可,不会影响到其他类的代码,从某种程度上来说也就是进行解耦
"""
基类,大概率不变的东西放在基类
例如,框架本身的东西,driver,find,click,send,swipe_find
"""
from appium.webdriver.webdriver import WebDriver
class BasePage:
def __init__(self, driver: WebDriver = None):
self.driver = driver
def find(self, by, locator):
return self.driver.find_element(by, locator)
def finds(self, by, locator):
return self.driver.find_elements(by, locator)
def find_click(self, by, locator):
# 找到只会完成点击操作
self.find(by, locator).click()
def find_send_keys(self, by, locator, value):
# 找到只会完成发送操作
self.find(by, locator).send_keys(value)
def back(self, num=3):
# 返回
for i in range(num):
self.driver.back()
2、创建一个WeWorkApp.py,继承BasePage
- 由于以后可能又去测试其他的App,所以我们这边就单独再创建一个WeWorkApp的类继承BasePage,为了区分App
"""
企业微信相关的操作
"""
from appium import webdriver
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.base.base_page import BasePage
class WeWorkApp(BasePage):
# 启动
def start(self):
# 如果BasePage那边传进来的webdriver是为None的,则创建driver
if self.driver == None:
caps = {}
caps["platformName"] = "Android"
caps["platformVersions"] = "6.0.1"
caps["deviceName"] = "ALP_AL00"
caps["appPackage"] = "com.tencent.wework"
# caps["appActivity"] = ".launch.WwMainActivity"
caps["appActivity"] = ".launch.LaunchSplashActivity"
caps["noResrt"] = True
caps['settings[waitForIdleTimeout]'] = 0 # 等待页面空闲的时间,如果是动态页面默认要加载10s
caps['skipServerInstallation'] = "true" # 跳过uiautomator2 sever的安装
caps['skipDeviceInitialization'] = "true" # 跳过设备初始化
caps['dontStopAppOnReset'] = "true" # 启动之前不停止app
# 与远程服务建立连接,返回一个session对象
self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
# 在调用find_element()时,会每隔0.5s查找一次元素,隐士等待
self.driver.implicitly_wait(5)
else:
print("driver不为None")
# 若存在,则直接启动app
# 启动desire里面设置的activity
self.driver.launch_app()
# 若要启动给定的activity
# self.driver.start_activity(app_package,app_activity)
return self
# 重启
def restart(self):
pass
# 停止
def stop(self):
self.driver.quit()
def goto_main(self):
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.page.main_page import MainPage
# 入口
return MainPage(self.driver)
Page包:
- 这里封装企业微信所有要测试的页面
- 思路:一个页面封装为一个类,页面上的每个功能封装为一个方法
- 另外所有元素的查找我这边建议使用:Xpath定位,因为id可能不是唯一的,是动态生成的,换一台设备后,原代码可能就会因为找不到id而无法运行。
为了提高代码设计的兼容性,我们尽量考虑到以后前端元素变更又或者测试设备更换的情况
1、创建首页,MainPage.py
"""
企业微信首页
"""
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.base.wework_app import WeWorkApp
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.page.addresslist_page import AddressListPage
class MainPage(WeWorkApp):
# 私有变量定义,前面加个_
_addresslist_element = (MobileBy.XPATH, "//*[@text='通讯录']")
# python 类型提示
def __init__(self, driver: WebDriver):
# 拿到上个页面的driver
self.driver = driver
"""
跳转到通讯录页面
"""
def goto_addresslist(self):
# click 通讯录
# self前面加个*,是由于传递过来的是个元祖,进行解元祖
# 先继承,但不改find方法
self.driver.find_element(*self._addresslist_element).click()
return AddressListPage(self.driver)
2、创建通讯录页面,AddressListPage.py
"""
企业微信通讯录页面
"""
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.base.wework_app import WeWorkApp
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.page.add_member_page import AddMemberPage
class AddressListPage(WeWorkApp):
# python 类型提示
def __init__(self, driver: WebDriver):
# 拿到上个页面的driver
self.driver = driver
def click_addmember(self):
# click 添加成员
self.driver.find_element(MobileBy.XPATH, "//*[@text='添加成员']").click()
return AddMemberPage(self.driver)
3、创建添加好友页面,AddMemberPage.py
"""
企业微信添加成员页
"""
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.base.wework_app import WeWorkApp
class AddMemberPage(WeWorkApp):
# python 类型提示
def __init__(self, driver: WebDriver):
# 拿到上个页面的driver
self.driver = driver
def click_addbymenual(self):
# click 手动输入添加
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.page.edit_member_page import EditMemberPage
self.driver.find_element(MobileBy.XPATH, "//*[@text='手动输入添加']").click()
return EditMemberPage(self.driver)
def get_result(self):
# 拿到toast文本内容
element_toast = self.find(MobileBy.XPATH, "//*[@class='android.widget.Toast']")
result = element_toast.get_attribute("text")
return result
4、创建编辑成员页面,EditMemberPage.py
"""
企业微信编辑成员页
"""
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.base.wework_app import WeWorkApp
class EditMemberPage(WeWorkApp):
# python 类型提示
def __init__(self, driver: WebDriver):
# 拿到上个页面的driver
self.driver = driver
def edit_member(self, name, phone):
# input name
# input phonenum
# click 保存
# // *[contains( @ text, "姓名")] /../ *[ @ text = "必填"]
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.page.add_member_page import AddMemberPage
self.driver.find_element(MobileBy.XPATH, "//*[contains(@text,'姓名')]/../*[@text='必填']").send_keys(name)
self.driver.find_element(MobileBy.XPATH, "//*[contains(@text,'手机')]/..//*[@text='必填']").send_keys(phone)
self.driver.find_element(MobileBy.XPATH, "//*[@text='保存']").click()
return AddMemberPage()
case包:
- 封装测试用例类
1、test_contact.py
"""
企业微信成员操作相关的测试用例
"""
from mikasa_script.mikasa_ceshiren.appnium_study.app_po_auto.base.wework_app import WeWorkApp
class TestContack:
def setup(self):
# 每个用例开始之前,启动企业微信
self.app = WeWorkApp()
# 默认进入到首页
self.main = self.app.start().goto_main()
def teardown(self):
# 每个用例执行完成后,就默认返回到首页
self.app.back()
def teardown_class(self):
# 所有用例都结束后,则关闭企业微信
self.app.stop()
# 用例一、添加成员
def test_addcontack1(self):
name = "mikasa1"
phone = "19974857591"
result = self.main.goto_addresslist().click_addmember().click_addbymenual(). \
edit_member().get_result(name, phone)
assert "添加成功" == result