UI自动化测试实战之页面对象设计模式
po模式:page object
页面对象设计模式,它的优势具体可以总结为如下:
- 创建可以跨多个测试用例共享的代码
- 减少重复代码的数量
- 如果用户界面发生了维护,我们只需要维护一个地方,这样修改以及维护的成本相对而言是比较低
一、目录结构设计
首先创建一个项目,点击File下的New Project,再点击Attach,下面我们具体针对这部分的目录进行设计,具体的目录结构为:
每个目录的是干什么的,具体总结为如下:
- base的包下主要编写基础的代码,可以理解为基础层
- page包下主要存放对象层的代码,可以理解为对象层
- test包下主要存放编写的测试模块的代码,可以理解为测试层
- utils下存放的主要是工具类的代码,比如针对JSON文件,YAML文件的处理
- common下主要存放的是公共类的代码,比如文件目录的处理
- data主要存放测试过程中使用到的数据
- report主要存储的是测试报告这部分
二、页面对象设计模式
上面已经很详细的解释了页面对象设计模式它的优势,以及目录结构的设计,下面依次来实现各个部分的
代码。
2.1、基础层
下面主要实现基础层的代码,在base包下创建base.py的文件,还是以新浪邮箱为例:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.expected_conditions import NoSuchElementException#导入捕获异常的方法 import time as t class WebUI(object): def __init__(self,driver): self.driver = driver def findElement(self,*args): ''' 单个元素定位的方式 它是一个元组,需要带上具体的方式定位元素属性以及元素属性的值 ''' try: return self.driver.find_element(*args) except NoSuchElementException as e: return e.args[0] def findElements(self,*args,index): ''' 多个元素定位的方式 index:被定位的目标索引值 ''' try: return self.driver.find_elements(*args)[index] except NoSuchElementException as e: return e.args[0]
2.2 对象层
下面以sina的邮箱为案例来编写具体的代码,在page包下创建login.py的文件
from selenium.webdriver.common.by import By
from base.base import WebUI
import time as t
class Login(WebUI):
username=(By.ID,'freename')
password=(By.ID,'freepassword')
login=(By.CLASS_NAME,'loginBtn')
divText=(By.XPATH,'/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
def inputUserName(self,username):
t.sleep(2)#用户名输入框
self.findElement(*self.username).send_keys(username)
def inputPasswd(self,password):
t.sleep(2)#密码输入框
self.findElement(*self.password).send_keys(password)
def clickLogin(self):
self.findElement(*self.login).click()
t.sleep(2)#登录按钮
def getDivtext(self):#获取错误信息
return self.findElement(*self.divText).text
def singLogin(self,username,password):
self.inputUserName(username=username)
self.inputPasswd(password=password)
self.clickLogin()
2.3测试层:
在test包下创建创建test_login.py的模块
from selenium import webdriver
import unittest
from page.login import Login
import time as t
class LoginTest(unittest.TestCase,Login):
def setUp(self)->None:
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get('http://mail.sina.com.cn/')
self.driver.implicitly_wait(30)
def tearDown(self) -> None:
self.driver.quit()
def test_login_null(self):
#用户名密码为空的错误信息验证
self.singLogin(username='',password='')
self.assertEqual(self.getDivtext(),'请输入邮箱名')
def test_login_format(self):
#邮箱名格式不正确的错误信息验证
self.singLogin(username='hioh', password='123jjhu')
self.assertEqual(self.getDivtext(),'您输入的邮箱名格式不正确')
def test_login_error(self):
#用户名和密码不匹配的错误信息验证
self.singLogin(username='hjs@sina.com',password='134345')
self.assertEqual(self.getDivtext(), '登录名或密码错误')
if __name__ == '__main__':
unittest.main(verbosity=2)
2.4、公共方法
下来在common包下创建public.py的模块,里面主要编写针对文件路径的处理
import os def base_dir(): return os.path.dirname(os.path.dirname(__file__))
2.5、数据驱动
下来在data的文件夹下创建sina.json的文件,把登录使用到的数据分离到sina.json的文件里面
{ "null": "请输入邮箱名", "passwdnull": "请输入密码", "format": "您输入的邮箱名格式不正确", "error": "登录名或密码错误", "numbererror": "手机号码输入格式错误", "success": "您的邮件已发送", "notread": "35" }
2.6、工具类
下来在具体的工具类中编写针对JSON文件的处理,创建的模块名称为:operationJson.py,
import json import os from common.public import base_dir def readJson(): return json.load(open(file=os.path.join(base_dir(),'data','sina.json'),encoding="utf-8"))
2.7、测试固件分离
我们已经达到了数据驱动的分离,下来针对测试固件进行分离,在page包下创建init.py文件
import unittest from selenium import webdriver class Init(unittest.TestCase): def setUp(self)->None: self.driver=webdriver.Chrome() self.driver.maximize_window() self.driver.get('http://mail.sina.com.cn/') self.driver.implicitly_wait(30) def tearDown(self)->None: self.driver.quit()
2.8、完善测试层
已经针对测试固件和数据都做了分离,下来完善测试模块test_login.py里面的代码
from selenium import webdriver
import unittest
from page.login import Login
import time as t
from utils.operationJson import readJson
class TestSinaLogin(Init,Login):
def test_login_null(self):#验证用户名和密码为空的错误信息提示
self.singLogin(username='',password='')
self.assertEqual(self.getDivtext(),readJson()['null'])
def test_login_format(self):#验证用户名格式不正确的错误信息提示
self.singLogin(username='hioh', password='123jjhu')
self.assertEqual(self.getDivtext(),readJson()['format'])
def test_login_error(self):#验证用户名和密码不匹配的错误信息提示
self.singLogin(username='hjs@sina.com',password='134345')
self.assertEqual(self.getDivtext(), readJson()['error'])
if __name__ == '__main__':
unittest.main(verbosity=2)