Python_Selenium 之以login_page为例实现对basepage封装好的方法调用和对common中公共方法的调用
目的:简化代码,提供框架该有的东西
每一个函数 -提供了一个功能 - 公共的功能
有了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模块读取数据为字典形式。
Python_Selenium 之以login_page为例实现对basepage封装好的方法调用和对common中公共方法的调用的更多相关文章
- 实现对gridview删除行时弹出确认对话框的一种简单方法
在VS2008提供的GridView中我们可以直接添加一个CommandField删除列:<asp:CommandField ShowDeleteButton="True" ...
- JAVA-----基于POI实现对Excel导入
在日常项目开发中, 数据录入和导出是十分普遍的需求,因此,导入导出也成为了开发中一个经典的功能.数据导出的格式一般是excel或者pdf,而批量导入的信息一般是借助excel来减轻工作量,提高效率. ...
- JDOM方法实现对XML文件的解析
首先要下载JDOM.jar包,下载地址:http://download.csdn.net/detail/ww6055/8880371 下载到JDOM.jar包之后导入到工程中去. 实例程序: book ...
- WPF: 在 MVVM 设计中实现对 ListViewItem 双击事件的响应
ListView 控件最常用的事件是 SelectionChanged:如果采用 MVVM 模式来设计 WPF 应用,通常,我们可以使用行为(如 InvokeCommandAction)并结合命令来实 ...
- 在应用程序中实现对NandFlash的操作
以TC58NVG2S3ETA00 为例: 下面是它的一些物理参数: 图一 图二 图三 图四 图五 图6-0 图6-1 说明一下,在图6-1中中间的那个布局表可以看做是实际的NandFlash一页数据的 ...
- 51单片机实现对24C02进行页写、顺序读取并显示验证
//************************************************************************************* //**程序名称:51单 ...
- 【Struts2学习笔记(11)】对action的输入校验和XML配置方式实现对action的全部方法进行输入校验
在struts2中,我们能够实现对action的全部方法进行校验或者对action的指定方法进行校验. 对于输入校验struts2提供了两种实现方法: 1. 採用手工编写代码实现. 2. 基于XML配 ...
- Android平台中实现对XML的三种解析方式
本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...
- jmeter通过BeanShell 脚本,实现对http请求参数的加密
jmeter一直是一款很好的接口和性能测试工具,它是开源的,不需要为此支付任何费用,而且可以下载源码,可以在修改源代码并在此基础上拓展自己的功能或插件,它可以跟ant和jenkins结合起来搭建自己的 ...
随机推荐
- UVA11462年龄排序
题意: 给你200w个人的年龄,年龄的范围是1-100,然后让你从小到大排序输出所有人的年龄,题目还特意强调输入文件限制25MB,题目内存限制2MB. 思路: 比较经典又简单的一 ...
- Ubuntu Linux 学习篇 配置DHCP服务器
isc-dhcp-server 动态主机配置协议是一个局域网的网络协议.指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码.首先, DHCP服务器必须是 ...
- WSL2+Ubuntu配置Java Maven Hadoop Spark环境
所需文件: 更新日期为2021/5/8: Linux 内核更新包 JDK1.8 maven3.8.1 hadoop3.3.0 spark3.1.1 WSL?WSL2? WSL是适用于 Linux 的 ...
- surging 基于流媒体服务如何集群分流
前言 最近几年微服务可谓是大火,大家忙着建设微服务,学习微服务如何搭建,微服务技术体系的演变也使得企业公司能支持起灵活,多样化的业务需求和越来越多的访问量,有很多企业用户正在朝着业务中台,SAAS云平 ...
- Java筑基 - JNI到底是个啥
在前面介绍Unsafe的文章中,简单的提到了java中的本地方法(Native Method),它可以通过JNI(Java Native Interface)调用其他语言中的函数来实现一些相对底层的功 ...
- lombok,Invalid byte tag in constant pool: 19
今天偶到一个奇怪的问题: 三台生产服务器部署同样的代码,同样的tomcat ,jdk等环境. 其中有一台服务器启动时报lombok-1.18.6.jar! Invalid byte tag in ...
- ES6新增常用方法
字符串新增方法 padStart.padEnd 如果原字符串不够指定长度,则会在左侧(右侧)填充字符串,用以补全 padStart( length: number, fillStr?: string ...
- 附近的人?你zao吗?
前几天收到一个新的需求,需要实现类似"附近的人"的功能:根据自己当前的定位,获取距离范围内的所有任务地点.刚看到这个需求时有点懵逼,第一想到的就是要利用地球的半径公式去计算距离,也 ...
- 【BUAA软工】第一次团队作业——团队介绍
项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:团队介绍与采访往届团队 团队作业-团队介绍和采访 Part I 团队成员介绍 有图有真(jia)相 大名 个人介绍 角色意向 李PX 来 ...
- Debian 16.04 配置双网卡绑定bond
Debian 16.04 配置双网卡绑定bond Debian 16.04 bonding多网卡配置 安装负载均衡软件 fenslave root@ubuntu:~# apt-get install ...
