POM(page object model)页面对象模型,主要应用于UI自动化测试框架的搭建, 主流设计模式之一,页面对象模型:结合面向对象编程思路:把项目的每个页面当做一个对象进行编程POM 一般分为四层
第一层:basepage层:描述每个页面相同的属性及行为 第二层:pageobject层(每个的独有特征及独有的行为) 第三层:testcase层(用例层,描述项目业务流程) 第四层:testdata(数据层)代码实现 非 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) el1 = driver.find_element_by_id("com.tencent.mobileqq:id/btn_login") el1.click() el2 = driver.find_element_by_accessibility_id("请输入QQ号码或手机或邮箱") el2.send_keys("QQ账号")#输入自己的QQ账号 el3 = driver.find_element_by_accessibility_id("密码 安全") el3.send_keys("QQ密码")#输入QQ密码 el4 = driver.find_element_by_accessibility_id("登 录") el4.click() el5 = driver.find_element_by_accessibility_id("同意") el5.click() el6 = driver.find_element_by_accessibility_id("登 录") el6.click()
po模型 *** 作
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)
业务页代码
page_01.py(导航模块)
from lzwifi.base.basepage import basePages # 导入basePages from appium.webdriver.common.mobileby import MobileBy class DaoHangPage(basePages): def __init__(self, driver): basePages.__init__(self, driver) # 点击登录 *** 作 def click_login(self): self.click(MobileBy.ID, "com.tencent.mobileqq:id/btn_login")
page_02.py(登录模块)
from lzwifi.base.basepage import basePages from appium.webdriver.common.mobileby import MobileBy class LoginPage(basePages): def __init__(self, driver): basePages.__init__(self, driver) # 清空账号框 *** 作 def clear_zh(self): self.clear(MobileBy.ACCESSIBILITY_ID, "请输入QQ号码或手机或邮箱") # 输入QQ账号 *** 作 def input_zh(self, test): self.input(test, MobileBy.ACCESSIBILITY_ID, "请输入QQ号码或手机或邮箱") # 清空密码框 *** 作 def clear_mm(self): self.clear(MobileBy.ACCESSIBILITY_ID, "密码 安全") # 输入QQ密码 *** 作 def input_mm(self, test): self.input(test, MobileBy.ACCESSIBILITY_ID, "密码 安全") # 点击登录 *** 作 def click_dl(self): self.click(MobileBy.ACCESSIBILITY_ID, "登 录") # 同意条款 def click_ty(self): self.click(MobileBy.ACCESSIBILITY_ID, "同意") # 再次登录 def click_rdl(self): self.click(MobileBy.ACCESSIBILITY_ID, "登 录")
单元测试模块
unittest实现
import unittest import time from appium import webdriver from lzwifi.pages.page_01 import DaoHangPage from lzwifi.pages.page_02 import LoginPage class TestClass(unittest.TestCase): @classmethod def setUpClass(cls) -> None: caps = {} caps["platformName"] = "Android" caps["deviceName"] = "127.0.0.1:62001" 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_01(self): dh = DaoHangPage(self.driver) dh.click_login() def test_02(self): dl = LoginPage(self.driver) dl.clear_zh() dl.input_zh("QQ账号") # 输入自己的QQ账号 dl.clear_mm() dl.input_mm("QQ密码") # 输入自己的QQ密码 dl.click_dl() dl.click_ty() dl.click_rdl() @classmethod def tearDownClass(cls) -> None: time.sleep(20) cls.driver.quit() if __name__ == '__main__': unittest.main()
pytest 实现 (需要导入 pip install pytest)
import pytest import time from appium import webdriver from lzwifi.pages.page_01 import DaoHangPage from lzwifi.pages.page_02 import LoginPage class TestClass(): @classmethod def setup_class(cls) -> None: caps = {} caps["platformName"] = "Android" caps["deviceName"] = "127.0.0.1:62001" 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_01(self): dh = DaoHangPage(self.driver) dh.click_login() def test_02(self): dl = LoginPage(self.driver) dl.clear_zh() dl.input_zh("QQ账号") dl.clear_mm() dl.input_mm("QQ密码") dl.click_dl() dl.click_ty() dl.click_rdl() @classmethod def teardown_class(cls) -> None: time.sleep(20) cls.driver.quit() if __name__ == '__main__': pytest.main()
引入yaml文件
yaml文件:数据层次清晰,可以跨平台,支持多种语言使用(可以适用于别的app) 优化代码:提取basepage中的配置客户端数据(将配置的数据放在yaml中) 创建config.yaml
caps: platformName: Android deviceName: 127.0.0.1:62001 appPackage: com.tencent.mobileqq appActivity: com.tencent.mobileqq.activity.LoginActivity调用yaml文件,需要导入 pip install pyYAML
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 if __name__ == '__main__': # os.path.dirname(__file__)当前文件的上一级目录 # os.path.abspath(path)找到路径的绝对路径 rootpath = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) dd = os.path.join(rootpath, "datademoconfig.yaml") print(dd) print(readYaml(dd))
修改单元测试模块代码
import pytest import time,os from lzwifi.common.read_yaml import readYaml from appium import webdriver from lzwifi.pages.page_01 import DaoHangPage from lzwifi.pages.page_02 import LoginPage class TestClass(): @classmethod def setup_class(cls) -> None: # caps = {} # caps["platformName"] = "Android" # caps["deviceName"] = "127.0.0.1:62001" # caps["appPackage"] = "com.tencent.mobileqq" # caps["appActivity"] = "com.tencent.mobileqq.activity.LoginActivity" rootpath = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) dd = os.path.join(rootpath, "datademoconfig.yaml") data = readYaml(dd) cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", data["caps"]) cls.driver.implicitly_wait(30) def test_01(self): dh = DaoHangPage(self.driver) dh.click_login() def test_02(self): dl = LoginPage(self.driver) dl.clear_zh() dl.input_zh("QQ账号") dl.clear_mm() dl.input_mm("QQ密码") dl.click_dl() dl.click_ty() dl.click_rdl() @classmethod def teardown_class(cls) -> None: time.sleep(20) cls.driver.quit() if __name__ == '__main__': pytest.main()
数据驱动
在 pytest 中使用 @pytest.mark.parametrize() 修饰器@pytest.mark.parametrize("user,password", [("QQ账号", "QQ密码")]) def test_02(self, user, password): dl = LoginPage(self.driver) dl.clear_zh() dl.input_zh(user) dl.clear_mm() dl.input_mm(password) dl.click_dl() dl.click_ty() dl.click_rdl()
生成测试报告
unittest实现(首先需要切换到unittest单元测试模块)
导入HTMLTestRunner.py
testhtml.py
import unittest from lzwifi.datademo.HTMLTestRunner import HTMLTestRunner # 导入HTMLTestRunner from lzwifi.test.test_qq import TestClass # 导入单元测试类 class HtmlClass(): def htmlMethod(self): suite = unittest.TestSuite() lists = ['test_01', 'test_02'] # 测试用例 for i in lists: suite.addTest(TestClass(i)) # 测试报告生成路径 with open("../unittesthtml.html", "wb") as f: HTMLTestRunner( stream=f, title="测试数据", description="测试一期", verbosity=2 ).run(suite) h = HtmlClass() h.htmlMethod()生成html测试报告
pytest实现(首先需要切换到pytest单元测试模块)
需要导入pip install pytest-html、pip install allure-pytest
修改单元测试模块代码
import pytest import time,os,allure from lzwifi.common.read_yaml import readYaml from appium import webdriver from lzwifi.pages.page_01 import DaoHangPage from lzwifi.pages.page_02 import LoginPage class TestClass(): @classmethod def setup_class(cls) -> None: # caps = {} # caps["platformName"] = "Android" # caps["deviceName"] = "127.0.0.1:62001" # caps["appPackage"] = "com.tencent.mobileqq" # caps["appActivity"] = "com.tencent.mobileqq.activity.LoginActivity" rootpath = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) dd = os.path.join(rootpath, "datademoconfig.yaml") data = readYaml(dd) cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", data["caps"]) cls.driver.implicitly_wait(30) def test_01(self): dh = DaoHangPage(self.driver) dh.click_login() @pytest.mark.parametrize("user,password", [("QQ账号", "QQ密码")]) def test_02(self, user, password): dl = LoginPage(self.driver) dl.clear_zh() dl.input_zh(user) dl.clear_mm() dl.input_mm(password) dl.click_dl() dl.click_ty() dl.click_rdl() @classmethod def teardown_class(cls) -> None: time.sleep(20) cls.driver.quit() if __name__ == '__main__': pytest.main(['--alluredir', 'report/result', 'test_qq.py']) split = 'allure ' + 'generate ' + './report/result ' + '-o ' + './report/html ' + '--clean' os.system(split)
生成html测试报告
最终框架展示
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)