相信曾经了解过、学习过或者使用过的童鞋都有过这样的苦恼,尤其是在面试自动化测试岗位的时候:你们的框架是怎么样的?是你搭建的吗?你搭建了哪些东西呢?一连三问,一脸懵逼。我也遇到过,今天我就斗胆将我的学习过程记录分享,让大家参考指正。废话不多说,先上目录架构。
PageObject简称PO,表示页面对象。即将页面当成对象,页面元素即是对象的属性,元素操作即是对象的方法。因此PO设计模式实现了代码的分层设计,将页面元素、元素操作和页面业务进行分离,减少代码维护量、提高测试用例的可读性。
1.基础层:(common层)封装基础类BasePage,基础类可以包含WebDriver实例的属性,如驱动的定义、对元素定位的二次封装等。
2.页面层:(page层)每一个页面类都要继承基础类BasePage,并将页面元素的操作封装成一个个的方法。
3.用例层:(testcase层)用例类必须继承unitest.Testcase类,并调用page类的方法实现相应测试步骤和用例的断言。
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
class BasePage:
# 定义项目地址和浏览器驱动
def __init__(self, url, driver):
self.url = url
self.driver = driver
# 重写find_element方法,添加元素是否存在判断
def find_element(self, *locator):
try:
WebDriverWait(self.driver, 20).until(expected_conditions.visibility_of_element_located(locator))
# 使用find_element(by, loc)定位法
return self.driver.find_element(*locator)
except:
print(*locator)
个人习惯将元素定位和页面类分开
from selenium.webdriver.common.by import By
class LoginPageLocator:
# 用户名框定位
username_loc = (By.XPATH, '//input[@autocomplete=\'username\']')
# 密码框定位
password_loc = (By.XPATH, "//input[@autocomplete=\'current-password\']")
# 登录按钮定位
loginBtn_loc = (By.XPATH, '//button[text()="登录"]')
# 密码登录方式定位
loginType_loc = (By.XPATH, '//span[text()="密码登录"]')
from PO.common.BasePage import BasePage
from PO.locator.LoginPageLocator import LoginPageLocator
class LoginPage(BasePage, LoginPageLocator):
# 打开登录页面
def openLoginPage(self):
self.driver.get(self.url)
self.driver.refresh()
self.driver.maximize_window()
# 切换登录方式
def change_loginType(self):
self.find_element(*self.loginType_loc).click()
# 输入用户名
def input_username(self, username):
self.find_element(*self.username_loc).send_keys(username)
# 输入密码
def input_password(self, password):
self.find_element(*self.password_loc).send_keys(password)
# 单击‘登录’按钮
def click_loginBtn(self):
self.find_element(*self.loginBtn_loc).click()
import unittest
from time import sleep
from selenium import webdriver
from PO.locator.LoginPageLocator import LoginPageLocator
from PO.page.LoginPage import LoginPage
class TestLogin(unittest.TestCase):
def setUp(self):
self.url = 'https://passport.csdn.net/login?code=applets'
self.driver = webdriver.Chrome('D:\资料\自动化\浏览器及Driver\谷歌浏览器及Driver\chromedriver.exe')
self.loginpage = LoginPage(self.url, self.driver)
def tearDown(self):
self.driver.quit()
def testlogin(self):
self.loginpage.openLoginPage() # 打开登录页面
self.loginpage.change_loginType() # 选择密码登录
self.loginpage.input_username('1734765****') # 输入用户名
self.loginpage.input_password('csdn*****0201') # 输入密码
self.loginpage.click_loginBtn() # 点击登录按钮
sleep(5)
t = self.loginpage.find_element(LoginPageLocator.image_loc)
self.assertIsNotNone(t, "测试失败,检查登录步骤")
这里采用pandas来处理Excel数据,pandas默认依赖xlrd,所以先安装xlrd。安装命令:pip install xlrd==1.1.0。安装pandas:pip install pandas
*安装xlrd时,指定版本1.1.0,太高版本处理Excel会报错
import os.path
import pandas
class ExcelHandler:
def readExcel(self, filename, row, col):
with open(self.dirname(filename), 'rb') as wk:
pd = pandas.read_excel(wk, sheet_name='Sheet1', nrows=row, usecols=[col, ], dtype=str)
return pd.values[0][0]
def dirname(self, filename, filepath='data'):
return os.path.join(os.path.dirname(os.path.dirname(__file__)), filepath, filename)
ExcelHandler类包含两个方法:readExcel和dirname,dirname方法返回Excel存储路径;readExcel方法通过传入filename(文件名)、row(行) 、col(列),返回该单元格(row,col)的值
import os.path
import time
class SaveImage:
def saveImage(self, driver, imageName):
savePath = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'image')
image = savePath + '\\' + time.strftime('%Y%m%d%H%M%S') + '_' + imageName
driver.get_screenshot_as_file(image)