一:
POM
及
POM
设计原理
POM(page object model)
页面对象模型,主要应用于
UI
自动化测试框架的搭建,主流设计模式之
一,页面对象模型:结合面向对象编程思路:把项目的每个页面当做一个对象进行编程
python
基础:什么是对象?
python
中对象
=
属性
+
行为 通过类定义
=
具有相同属性
+
相同行为对象集合
二:
POM
一版分为四层
第一层
:basepage
层
:
描述每个页面相同的属性及行为
第二层:
pageobject
层
(
每个的独有特征及独有的行为
)
第三层:
testcase
层
(
用例层,描述项目业务流程
)
第四层:
testdata(
数据层
)
三
:
代码实现
3.1
:非
po
模型
(
夜神中
qq
登录
)
from appium import webdriver
caps = {}
caps["platformName"] = "Android"
caps["deviceName"] = "127.0.0.1:62001"
caps["appPackage"] = "com.tencent.mobileqq"
caps["appActivity"] = "com.tencent.mobileqq.activity.LoginActivity"
driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
driver.implicitly_wait(30)
el2 = driver.find_element_by_id("com.tencent.mobileqq:id/btn_login")
el2.click()
el3 = driver.find_element_by_accessibility_id("请输入QQ号码或手机或邮箱")
el3.clear() el3.send_keys("2697854965")
el4 = driver.find_element_by_accessibility_id("密码 安全")
el4.clear() el4.send_keys("2697854965")
el5 = driver.find_element_by_accessibility_id("登 录")
el5.click()
3.2
:
po
模型操作
3.2.1
:
basepage(
封装公共的属性和行为
)
class BasePages:
def init (self,driver): self.driver = driver
#元素定位
def locator(self,*loc):
return self.driver.find_element(*loc) #清空
def clear(self,*loc): self.locator(*loc).clear()
#输入
def input(self,test,*loc): self.locator(*loc).send_keys(test)
#点击
def click(self,*loc): self.locator(*loc).click()
#滑动(上下左右滑动)
def swipe(self,start_x,start_y,end_x,end_y,duration=0): #获取屏幕的尺寸
window_size = self.driver.get_window_size()
x = window_size["width"]
y = window_size["height"]
self.driver.swipe(start_x=x*start_x,
start_y=y*start_y,
end_x= x*end_x,
end_y=y*end_y,
duration=duration)
3.2.2:
业务页代码
3.2.2.1:daohang_page.py(
导航模块
)
from app_pom.base.basepage import BasePages
from appium.webdriver.common.mobileby import MobileBy
class DaoHang(BasePages):
def __init__(self, driver):
BasePages.__init__(self, driver)
def click_login(self):
self.click(MobileBy.ID, "com.tencent.mobileqq:id/btn_login")
3.2.2.2:login_page.py(
登录模块
)
from app_pom.base.basepage import BasePages
from appium.webdriver.common.mobileby import MobileBy
class Login(BasePages):
def __init__(self,driver):
BasePages.__init__(self,driver)
def send_zh(self,text):
BasePages.input(text,MobileBy.ACCESSIBILITY_ID,"请输入QQ号码或手机或邮箱")
def send_pw(self,text):
BasePages.input(text,MobileBy.ACCESSIBILITY_ID,"密码 安全")
def click_login(self):
BasePages.input(MobileBy.ID,"登 录")
3.2.3:
单元测试模块
import unittest
from appium import webdriver
from app_pom.pages.daohang_page import DaoHang
from app_pom.pages.login_page import Login
import time
class TestClass(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
caps = {}
caps["platformName"] = "Android"
caps["deviceName"] = "127.0.0.1:62001"
caps["platformVersion"] = "5.1.1"
caps["appPackage"] = "com.tencent.mobileqq"
caps["appActivity"] = "com.tencent.mobileqq.activity.LoginActivity"
cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
cls.driver.implicitly_wait(30)
def test_daohang(self):
dh =DaoHang(self.driver)
dh.click_login()
def test_login(self):
l = Login(self.driver)
l.send_zh("2697854965")
l.send_pw("***********")
l.click_login()
@classmethod
def tearDownClass(cls) -> None:
time.sleep(20)
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
四:引入
yuml
文件
yaml
文件:数据层次清晰,可以跨平台,支持多种语言使用
(
可以适用于别的
app)
优化代码:提取
basepage
中的配置客户端数据(将配置的数据放在
yaml
中)
创建
config--
config.yaml
caps:
platformName: Android
deviceName: 127.0.0.1:62001
appPackage: com.tencent.mobileqq
appActivity: com.tencent.mobileqq.activity.LoginActivity
platformVersion: 5.1.1
调用
yaml
文件,需要导入
pip install pyYAML
创建
common--read
yaml.py
import yaml,os
def readYaml(path):
with open(path,"r",encoding="utf-8") as file:
data = yaml.load(stream=file,Loader=yaml.FullLoader)
return data
print(os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))),"data/config.yaml"))
修改单元测试模块代码
import unittest
from appium import webdriver
from app_pom.pages.daohang_page import DaoHang
from app_pom.pages.login_page import Login
from app_pom.common.read_yaml import readYaml
import os
import time
class TestClass(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
# caps = {}
# caps["platformName"] = "Android"
# caps["deviceName"] = "127.0.0.1:62001"
# caps["platformVersion"] = "5.1.1"
# caps["appPackage"] = "com.tencent.mobileqq"
# caps["appActivity"] = "com.tencent.mobileqq.activity.LoginActivity"
data = readYaml(os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))),"data/config.yaml"))
cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", data["caps"])
cls.driver.implicitly_wait(30)
def test_daohang(self):
dh =DaoHang(self.driver)
dh.click_login()
def test_login(self):
l = Login(self.driver)
l.send_zh("2697854965")
l.send_pw("************")
l.click_login()
@classmethod
def tearDownClass(cls) -> None:
time.sleep(20)
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
五:数据驱动
在
pytest
中使用
@pytest.mark.parametrize()
修饰器
另外跳转到新闻页面
import pytest, os
from appium import webdriver
from app_pom.pages.daohang_page import DaoHang
from app_pom.pages.login_page import Login
from app_pom.pages.xinwen import XinWen
from app_pom.common.read_yaml import readYaml
import time
class TestClass():
@classmethod
def setup_class(cls) -> None:
# caps = {}
# caps["platformName"] = "Android"
# caps["deviceName"] = "127.0.0.1:62001"
# caps["platformVersion"] = "5.1.1"
# caps["appPackage"] = "com.tencent.mobileqq"
# caps["appActivity"] = "com.tencent.mobileqq.activity.LoginActivity"
data = readYaml(os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))), "data/config.yaml"))
cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", data["caps"])
cls.driver.implicitly_wait(30)
def test_daohang(self):
dh = DaoHang(self.driver)
dh.click_login()
@pytest.mark.parametrize("username,password", [("2697854965", "***********")])
def test_login(self, username, password):
l = Login(self.driver)
l.send_zh(username)
l.send_pw(password)
l.click_login_button()
def test_xinwen(self):
x = XinWen(self.driver)
x.click_xinwen()
@classmethod
def teardown_class(cls) -> None:
time.sleep(20)
if __name__ == '__main__':
pytest.main()