目的:簡化代碼,提供框架該有的東西
每一個函數 -提供了一個功能 - 公共的功能
有了basepage,在PageObjects當中直接調用元素操作。
以下以login_page 為例,實現從配置文件中讀取基礎信息,日志模塊,公共方法login.py的封裝,從Excel中讀取元素信息,login_page.py 調用basepage中公共操作方法操作。
一、basepage類代碼如下:
#coding=gbk
import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By #導入by方法
from selenium.webdriver.support.wait import WebDriverWait #隱式等待
from common.log_utils import logger #導入日志模塊
class BasePage(object):
def __init__(self,driver):
self.driver=driver
# ----------瀏覽器操作封裝-------
#打開網頁
def open_url(self,url):
self.driver.get(url)
logger.info('打開URL地址%s;'%url)
def set_browser_max(self):
self.driver.maximize_window()
logger.info("設置瀏覽器的最大化")
# -------- 元素識別的封裝--------
def find_element(self,element_info):
locator_type_name=element_info['locator_type']
locator_value_info=element_info['locator_value']
locator_timeout=element_info['timeout']
if locator_type_name =='id':
locator_type=By.ID
elif locator_type_name=='class':
locator_type=By.CLASS_NAME
elif locator_type_name=='xpath':
locator_type=By.XPATH
#識別元素
element=WebDriverWait(self.driver,locator_timeout)\
.until(lambda x:x.find_element(locator_type,locator_value_info))
#在basepage中添加日志打印,這樣就能實現每一個調用該方法的元素打印該日志,且日志記錄清晰明了,不需要再在每一個UIpage 中增加日志。
logger.info('[%s]元素識別成功'%element_info['element_name'])
return element
#元素鼠標操作封裝:點擊
def click(self,element_info):
element=self.find_element(element_info)
logger.info('[%s]元素進行點擊操作'%element_info['element_name'])
element.click()
# #鍵盤事件操作封裝:輸入內容
def input(self,element_info,content):
element=self.find_element(element_info)
element.send_keys(content)
logger.info('[%s]元素輸入內容:%s'%(element_info['element_name'],content))
--日志打印模塊 log_utils.py(目前簡單封裝)
import os
import logging
current_path = os.path.dirname(__file__)
log_path = os.path.join( current_path ,'../logs/test.log' )
class LogUtils:
def __init__(self,logfile_path = log_path ):
self.logfile_path = logfile_path
self.logger = logging.getLogger('Logger')
self.logger.setLevel(level=logging.INFO)
file_log = logging.FileHandler(self.logfile_path)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_log.setFormatter(formatter)
self.logger.addHandler(file_log)
def info(self,message):
self.logger.info( message )
def error(self,message):
self.logger.error(message)
logger = LogUtils()
if __name__=='__main__':
log_utils = LogUtils()
log_utils.info( '測試打印輸出' )
二、調用如下(以登錄頁面login_page.py 例):
(1)login_page.py 主代碼如下:
#coding=gbk
import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from common.log_utils import logger
from common.base_page import BasePage
from common.config_utils import config
from common import login
from common.set_driver import set_driver
from common.element_data_utils import ElementdataUtils
from common.element_yamldate_utils import ElementdataYamlUtils
class LoginPage(BasePage):
def __init__(self,driver):
super().__init__(driver)
####-----------------第一種方式,直接寫字典形式---------------------####
# self.username_inputbox = {'element_name':'用戶名輸入框',
# 'locator_type':'xpath',
# 'locator_value':'//input[@name="account"]',
# 'timeout': 5 }
# self.password_inputbox = {'element_name': '密碼輸入框',
# 'locator_type': 'xpath',
# 'locator_value': '//input[@name="password"]',
# 'timeout': 4}
# self.login_button = {'element_name': '登錄按鈕',
# 'locator_type': 'xpath',
# 'locator_value': '//button[@id="submit"]',
# 'timeout': 2}
####-----------------第二種方式,使用excecl讀取---------------------####
elements=ElementdataUtils('login_page').get_element_info()
#####公共####
self.username_inputbox =elements['username_inputbox']
self.password_inputbox=elements['password_inputbox']
self.login_button=elements['login_button']
self.change_language=elements['change_language']
def input_username(self,username): #方法 == 》控件的操作
self.input( self.username_inputbox , username )
def input_password(self,password):
self.input( self.password_inputbox , password )
def click_login(self):
self.click( self.login_button )
if __name__=="__main__":
from common.base_page import BasePage
driver=set_driver()
login_page = LoginPage(driver)
login.test_login(config.get_url,config.get_user_name,config.get_password,driver) ##因為封裝了登錄方法,直接調用即可
(2)公共方法:登錄login.py封裝
from selenium import webdriver
from element_infos.login_page import LoginPage
from common.config_utils import config
from common.set_driver import set_driver
def test_login(url, username, password, driver):
driver.get(url)
login = LoginPage(driver)
login.input_username(username)
login.input_password(password)
login.click_login()
(3)公共方法:config_utils.py 配置信息封裝
import os
import configparser
current_path = os.path.dirname(__file__)
cfgpath = os.path.join(current_path, "../conf/local_config.ini")
print(cfgpath)
class ConfigUtils:
def __init__(self,config_path=cfgpath):
self.__conf=configparser.ConfigParser() ##做成私有實例屬性,僅在類的內部使用,外部不可訪問,也提高使用的簡潔度
self.__conf.read(config_path, encoding="utf-8")
def read_ini(self,sec,option):
value=self.__conf.get(sec,option)
return value
@property #添加這個可將該類的這個方法變成一個類屬性,直接調用類的屬性就可以
def get_url(self):
value=self.read_ini('default','url')
return value
@property #添加這個可將該類的這個方法變成一個類屬性,直接調用類的屬性就可以
def get_user_name(self):
value=self.read_ini('user','user_name')
return value
@property
def get_password(self):
value = self.read_ini('user', 'password')
return value
@property
def get_error_user_name(self):
value=self.read_ini('user','error_user_name')
return value
@property
def get_error_password(self):
value = self.read_ini('user', 'error_password')
return value
config=ConfigUtils() #直接定義一個方法,在外部直接調用該方法就可以,不需要再每次都創建一個對象
if __name__=='__main__':
current_path = os.path.dirname(__file__)
cfgpath = os.path.join(current_path, "../conf/local_config.ini")
config_u=ConfigUtils()
print(config_u.get_url)
print(config_u.get_user_name)
print(config_u.get_password)
local_config.ini配置如下:
[default]
url=http://127.0.0.1/zentao/user-login-L3plbnRhby9teS5odG1s.html
[user]
user_name = admin
password = XXXXXXX
(4)公共方法:element_data_utils.py 配置信息封裝
import os
import xlrd
current_path=os.path.dirname(__file__)
excel_path=os.path.join(current_path,'../element_info_datas/element_infos.xlsx')
class ElementdataUtils:
def __init__(self,page_name,element_path=excel_path):
self.element_path=element_path
self.workbook = xlrd.open_workbook(excel_path)
self.sheet = self.workbook.sheet_by_name(page_name)
self.row_count=self.sheet.nrows
def get_element_info(self):
element_infos = {}
for i in range(1, self.sheet.nrows):
element_info = {}
element_info['element_name'] = self.sheet.cell_value(i, 1)
element_info['locator_type'] = self.sheet.cell_value(i, 3) ##所屬頁面不要取值
element_info['locator_value'] = self.sheet.cell_value(i, 4)
element_info['timeout'] = self.sheet.cell_value(i, 5)
element_infos[self.sheet.cell_value(i, 0)] = element_info
return element_infos
if __name__ == '__main__':
print(ElementdataUtils('login_page').get_element_info())
print(ElementdataUtils('main_page').get_element_info()
元素Excel信息配置:
(4)公共方法:set_driver.py 瀏覽器簡單封裝
from selenium import webdriver
def set_driver():
driver = webdriver.Chrome()
driver.maximize_window()
return driver
if __name__ == '__main__':
set_driver()
結論:
一、在login_page.py 中,引入basepage,定義元素字典信息(字典信息在Excel中存放),定義當前login頁面的元素操作(loginpage對元素操作此處調用basepage中公共的元素操作方法--->basepage內部再去調用basepage中的元素識別和元素操作),各個模塊方法組合調用,PO模式實現登錄。
二、將常用的方法做成公共方法,方便調用,比如對元素信息的讀取,登錄方法login.py,配置文件的讀取等。
三、測試數據和代碼分離,方便維護,比如excecl存放元素信息,采用xlrd模塊讀取數據為字典形式。

