侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   193

背景

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

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

任务

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

过程

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

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 urlvalueif __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

@ddtclass 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时间和字符串转换操作实例分析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客