python3+selenium自动化测试框架详解


Posted in Python onMarch 17, 2019

背景

为了更好的发展自身的测试技能,应对测试行业以及互联网行业的迭代变化。自学python以及自动化测试。

虽然在2017年已经开始接触了selenium,期间是断断续续执行自动化测试,因为还有其他测试任务,培训任务要执行…
前期建议大家能够学习python基本语法(python基础教程)

任务

搭建自动化测试框架,并能有效方便的进行测试,维护成本也要考虑其中。

过程

我的自动化框架可能不成熟,因为是自学的。请多包涵。也请大佬指导~

python3+selenium自动化测试框架详解

common

包含:基本的公共方法类,比如HTML报告、Log处理、发送邮件、基本页面对象等

其中pageObject里面是对各个测试系统操作页面的一个封装,以后用例的方法直接继承即可。可多次调用,维护起来比较方便。

conf

基本的系统参数配置信息,可以包含url,正确用户的信息,简单日志级别,某些输出位置,邮件信息等

data

对于数据驱动或者其他测试用例中需要测试的数据,之后测试用例流程不变,可以直接在文档中进行测试数据的修改。暂时采用excel。也可以采用csv,xml等等方法

log

日志输出,暂时包括了 log输出,htmlreport输出以及img的保存。

test

其中包含testcase以及testsuite两个模块

testcase 负责编写测试用例如果某个功能有多个py文件编写可以再新建一个目录。
testsuite 就是测试套件,可以按需求进行选择需要的测试项(包含测试用例以及测试类)
注意:使用ddt则不可以再使用addTest方式单独添加测试用例了。

1

代码部分

- common中的BasePage

class BasePage():
 global logg
 logg = LogHandler().logger
 def __init__(self,driver,url=None):
  self.wd = driver
  self.wd.implicitly_wait(5)
  self.actions = ActionChains(self.wd)
  if url :
   self.url = url
  else:
   self.url = self.server_url_conf()
 #浏览器行为的一些方法
 def get_conf_url(self):
		self.wd.get(self.url)
  self.wd.maximize_window()
  logg.debug("enter conf_url : " + str(self.url))
 def brower_close(self):
  return self.wd.close()
 def brower_quit_all(self):
  return self.wd.quit()
... 	下面还有刷新,前进后退等

 #定位 这里通过 By.xx 方法
 def find_web_element(self,*loc):
  #self.wd.find_element(*loc)
  return self.wd.find_element(*loc)

 #元素操作
 def type_text(self,loc,text):
  return self.wd.find_element(*loc).send_keys(text)
  
 def clear_text(self,*loc):
  return self.wd.find_element(*loc).clear()
  
 def submit_func(self,*loc):
  return self.wd.find_element(*loc).submit()

 def click_btn(self,*loc):
  return self.wd.find_element(*loc).click()
  
	#鼠标相关
 def mouse_move_to_element(self,*loc):
  elem = self.find_web_element(*loc)
  self.actions.move_to_element(elem).perform()
... 下面还有点击,双击,右击的一些方法  

 #获取信息行为
 def get_web_url(self):
  return self.wd.current_url
 def get_title(self):
  return self.wd.title
 def get_element_text(self,*loc):
  return self.find_web_element(*loc).text

 #元素是否存在 是 True
 def check_element_isexist(self,loc):
  isexist = False
  try:
   EC.presence_of_element_located(loc)(self.wd)
   isexist = True
  except Exception as e:
   isexist = False
   logg.debug(' isexist or not :',exc_info = True)
  return isexist
 def check_element_has_text(self,loc,text):
		pass #省略
 
 def check_element_isdisplayed(self,*loc):
  	pass #省略
  	
 #生成图
 def __inser_img(self,passorfailed,imgname):
  time_loc = time.strftime("%m%d_%H%M%S",time.localtime())
  file_path = os.path.abspath(__file__)
  file_path = os.path.join(file_path+"/../../log/%s_%s.png" %(imgname,time_loc))
  self.wd.get_screenshot_as_file(file_path)
  logg.debug('insert_%s_img %s ' %(passorfailed,(file_path)))

 def insert_error_img(self,imgname):
  self.__inser_img("error",imgname)
 def insert_success_img(self,imgname):
  self.__inser_img("success",imgname)
 def insert_debug_img(self,imgname):
  self.__inser_img("debug",imgname)


 def server_url_conf(self):
  self.host = readconfig.ReadConfig().getserver('host')
  self.port = readconfig.ReadConfig().getserver('port')
  urlvalue = self.host + ":" + self.port

  return urlvalue

if __name__ == '__main__':
 test = BasePage(webdriver.Chrome())
 test.get_conf_url()

common中登录页的页面对象

包含了页面的一些方法比如

输入用户名,输入密码,点击登录

test中的 logintestcase

则直接使用 登录页面对象的 输入用户名,输入密码,点击登录即可

后期维护,如果元素变动,则只需要修改页面对象代码而对用例则无需修正

class AioLogin(BasePage):
 global logg
 logg = LogHandler().getlog()
 username_loc = (By.NAME, "username")
 password_loc = (By.CSS_SELECTOR, "input[type='password']")
 login_loc = (By.CLASS_NAME, "login-btn")
 login_loc_oem = (By.ID,"submit")
 check_login_loc = (By.CLASS_NAME,"error-tip")
 elements = [username_loc,password_loc,login_loc,check_login_loc]
 log_menu = (By.CSS_SELECTOR,"[name='log']")
 logg.debug(elements)
 
 def set_username(self,username):
  self.clear_text(*self.username_loc) #直接使用BasePage的方法
  self.type_text(self.username_loc,username)
  logg.info('Enter username: ' + username)
  sleep(0.1)
... 其他

logintest

这里使用了ddt数据驱动方法

from ddt import data,ddt,unpack

@ddt
class TestLogin(unittest.TestCase):
 global logg
 logg = LogHandler().getlog()
 
 @classmethod  #该类方法,执行中只会启动一次。区别于setUp的 每个用例都执行一遍
 def setUpClass(cls):
  cls.test = aiologinpage.AioLogin(webdriver.Chrome())
  cls.test.get_conf_url()
  # print('start TestSearch')
  
 @classmethod
 def tearDownClass(cls):
  # TestLogin().logg.info("brower quit")
  TestLogin().test.brower_close()
  pass
 logindata = ReadExcel().getValue('login')
 
 @data(*logindata)
 @unpack  #当有多组数据时,需要unpack
 def testcase2(self,username,passwd,result):
  logg.info(username+" " + passwd +" " +str(result))
  self.test.set_username(username) #用例直接使用登录页面对象,后期除了修改测试用例,否则无需变动
  self.test.set_password(passwd)
  self.test.type_login_btn()
  
  # 断言登录结果和预期结果是否一致
  self.assertTrue(self.test.check_login_result(result),
      msg="\r login_test fail \r username :%s \r passwd : %s " %(username,passwd))

if __name__ == '__main__':
 unittest.main()

其他页面

比如我有个 创建设备分组的页面

我必须要先登录才可以执行下面的操作

此时,可以从conf中获取成功登录的用户名和密码,把correct_login方法写在登录页面对象中。

def correct_login(self):
  self.get_conf_url()
  self.userpasswd = self.correct_userpasswd_conf()
  self.set_username(self.userpasswd[0])
  self.set_password(self.userpasswd[1])
  self.type_login_btn()

之后,其他页面初始化时候直接调用这个correct_login即可登录

测试套件添加方法
TestSuite方法
#添加一个类
st1 = unittest.makeSuite(TestLogin)
#单独添加多个用例
st = unittest.TestSuite(map(TestClassName,[‘testcase1',‘testcase2']))
st = unittest.TestSuite(TestClaseeName(‘testcase1'))

#添加一个或者多个测试用例
st2 = unittest.TestSuite()
st2.addTests(map(TestCaseClassName,[‘testcase2',‘testcase1']))
st2.addTest(TestCaseClassName(‘testcase1'))
#添加一个类
st2.addTest(unittest.makeSuite(TestClassName))

TestLoader 方法
discovery 发现脚本
st = unittest.TestLoader().discovery(“dir_path”,pattern=“a*.py”)

#loadTestFromTestCase 加载 测试类
st1 = unittest.TestLoader().loadTestsFromTestCase(TestLoginCheck)
st2 = unittest.TestLoader().loadTestsFromTestCase(TestLogin)
stt = unittest.TestSuite()
stt.addTests([st1,st2])

Python 相关文章推荐
python实现倒计时的示例
Feb 14 Python
Django实现自定义404,500页面教程
Mar 26 Python
利用Python3分析sitemap.xml并抓取导出全站链接详解
Jul 04 Python
关于Python如何避免循环导入问题详解
Sep 14 Python
Python标准模块--ContextManager上下文管理器的具体用法
Nov 27 Python
python打包压缩、读取指定目录下的指定类型文件
Apr 12 Python
每天迁移MySQL历史数据到历史库Python脚本
Apr 13 Python
python3.6.3安装图文教程 TensorFlow安装配置方法
Jun 24 Python
python二进制文件的转译详解
Jul 03 Python
matplotlib相关系统目录获取方式小结
Feb 03 Python
pytorch中的model=model.to(device)使用说明
May 24 Python
这样写python注释让代码更加的优雅
Jun 02 Python
Django 中间键和上下文处理器的使用
Mar 17 #Python
Python时间和字符串转换操作实例分析
Mar 16 #Python
Python中numpy模块常见用法demo实例小结
Mar 16 #Python
Python常见的pandas用法demo示例
Mar 16 #Python
详解python中list的使用
Mar 15 #Python
详解Python_shutil模块
Mar 15 #Python
python批量修改文件夹及其子文件夹下的文件内容
Mar 15 #Python
You might like
php+oracle 分页类
2006/10/09 PHP
php下过滤html代码的函数 提高程序安全性
2010/03/02 PHP
php使用NumberFormatter格式化货币的方法
2015/03/21 PHP
PHP学习笔记(三):数据类型转换与常量介绍
2015/04/17 PHP
使用图灵api创建微信聊天机器人
2015/07/23 PHP
Linux下从零开始安装配置Nginx服务器+PHP开发环境
2015/12/21 PHP
php $_SESSION会员登录实例分享
2021/01/19 PHP
PHP CURL采集百度搜寻结果图片不显示问题的解决方法
2017/02/03 PHP
一文掌握PHP Xdebug 本地与远程调试(小结)
2019/04/23 PHP
用js+xml自动生成表格的东西
2006/12/21 Javascript
JavaScript中也使用$美元符号来代替document.getElementById
2010/06/19 Javascript
JS获取iframe中longdesc属性的方法
2015/04/01 Javascript
实现前后端数据交互方法汇总
2015/04/07 Javascript
Bootstrap零基础入门教程(二)
2016/07/18 Javascript
微信小程序支付之c#后台实现方法
2017/10/19 Javascript
JS拖拽排序插件Sortable.js用法实例分析
2019/02/20 Javascript
node.js ws模块搭建websocket服务端的方法示例
2019/04/25 Javascript
微信小程序左右滚动公告栏效果代码实例
2019/09/16 Javascript
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
2017/10/20 Python
解决项目pycharm能运行,在终端却无法运行的问题
2019/01/19 Python
python快速编写单行注释多行注释的方法
2019/07/31 Python
python sqlite的Row对象操作示例
2019/09/11 Python
python dict乱码如何解决
2020/06/07 Python
Python3爬虫关于代理池的维护详解
2020/07/30 Python
戴尔美国官网:Dell
2016/08/31 全球购物
Mistine官方海外旗舰店:泰国国民彩妆品牌
2016/12/28 全球购物
建筑班组长岗位职责
2014/01/02 职场文书
新店开张活动方案
2014/08/24 职场文书
护士节活动总结
2014/08/29 职场文书
小学生安全教育广播稿
2014/10/20 职场文书
2015年元旦晚会活动总结(学生会)
2014/11/28 职场文书
2014年网管工作总结
2014/12/11 职场文书
倡议书范文大全
2015/04/28 职场文书
2015年学校安全管理工作总结
2015/05/11 职场文书
小学三年级作文之写景
2019/11/05 职场文书
PyTorch dropout设置训练和测试模式的实现
2021/05/27 Python