目的:简化代码,提供框架该有的东西
每一个函数 -提供了一个功能 - 公共的功能
有了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中公共方法的调用的更多相关文章

  1. 实现对gridview删除行时弹出确认对话框的一种简单方法

    在VS2008提供的GridView中我们可以直接添加一个CommandField删除列:<asp:CommandField ShowDeleteButton="True" ...

  2. JAVA-----基于POI实现对Excel导入

    在日常项目开发中, 数据录入和导出是十分普遍的需求,因此,导入导出也成为了开发中一个经典的功能.数据导出的格式一般是excel或者pdf,而批量导入的信息一般是借助excel来减轻工作量,提高效率. ...

  3. JDOM方法实现对XML文件的解析

    首先要下载JDOM.jar包,下载地址:http://download.csdn.net/detail/ww6055/8880371 下载到JDOM.jar包之后导入到工程中去. 实例程序: book ...

  4. WPF: 在 MVVM 设计中实现对 ListViewItem 双击事件的响应

    ListView 控件最常用的事件是 SelectionChanged:如果采用 MVVM 模式来设计 WPF 应用,通常,我们可以使用行为(如 InvokeCommandAction)并结合命令来实 ...

  5. 在应用程序中实现对NandFlash的操作

    以TC58NVG2S3ETA00 为例: 下面是它的一些物理参数: 图一 图二 图三 图四 图五 图6-0 图6-1 说明一下,在图6-1中中间的那个布局表可以看做是实际的NandFlash一页数据的 ...

  6. 51单片机实现对24C02进行页写、顺序读取并显示验证

    //************************************************************************************* //**程序名称:51单 ...

  7. 【Struts2学习笔记(11)】对action的输入校验和XML配置方式实现对action的全部方法进行输入校验

    在struts2中,我们能够实现对action的全部方法进行校验或者对action的指定方法进行校验. 对于输入校验struts2提供了两种实现方法: 1. 採用手工编写代码实现. 2. 基于XML配 ...

  8. Android平台中实现对XML的三种解析方式

    本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...

  9. jmeter通过BeanShell 脚本,实现对http请求参数的加密

    jmeter一直是一款很好的接口和性能测试工具,它是开源的,不需要为此支付任何费用,而且可以下载源码,可以在修改源代码并在此基础上拓展自己的功能或插件,它可以跟ant和jenkins结合起来搭建自己的 ...

随机推荐

  1. POJ2391 Floyd+离散化+二分+DINIC

    题意:       有n个猪圈,每个猪圈里面都有一定数量的猪(可能大于当前猪圈的数量),每个猪圈都有自己的容量,猪圈与猪圈之间给出了距离,然后突然下雨了,问多久之后所有的猪都能进圈. 思路:     ...

  2. docker文件系统分层存储原理

    一,前言 众所周知,docker镜像技术的基础是联合文件系统(UnionFS),其文件系统是分层的,那它的分层机制是什么样的呢?共分为几种层呢?又是怎么工作的呢? 目前docker支持的联合文件系统有 ...

  3. Object划分

    Object划分 1.PO(persistantobject)持久对象 PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合.PO中应该不包 含任何对数据库的操作. 2.DO(Domain ...

  4. 截取字符串长度,超出部分用省略号代替 PHP

    function subText($text, $length){ if (mb_strlen($text, 'utf8') > $length) { return mb_substr($tex ...

  5. CDH安装步骤

    Six Steps to CDH Installation There are many options and potential paths that make each CDH cluster ...

  6. 变分贝叶斯学习(variational bayesian learning)及重参数技巧(reparameterization trick)

    摘要:常规的神经网络权重是一个确定的值,贝叶斯神经网络(BNN)中,将权重视为一个概率分布.BNN的优化常常依赖于重参数技巧(reparameterization trick),本文对该优化方法进行概 ...

  7. Spring Security 入门(基本使用)

    Spring Security 入门(基本使用) 这几天看了下b站关于 spring security 的学习视频,不得不说 spring security 有点复杂,脑袋有点懵懵的,在此整理下学习内 ...

  8. Educational Codeforces Round 96 (Rated for Div. 2)

    A. Number of Apartments 题意:求方程的解 思路:直接模拟就行 代码: #include<iostream> #include<cstdio> #incl ...

  9. 黄衫女子,黄衫好.png

    正想着团队项目中数据该如何解析,就收到了来自软工课程组的一件小黄衫,真是意外之喜.详问其来源,竟是因结对项目做的"较好"而来,顿感受之有愧. 结对项目是两人对文件系统的一个小模拟, ...

  10. Java开发人员最容易出现的几类错误

    一.把数组转成ArrayList List<String> list = Arrays.asList(arr); //以下带伪代码来自Arrays类中public static <T ...