Selenium自动化测试框架(超详细总结分享)

设计思路

本文整理归纳以往的工作中用到的东西,现汇总成基础测试框架提供分享。

框架采用python3 + selenium3 + PO + yaml + ddt + unittest等技术编写成基础测试框架,能适应日常测试工作需要。

1、使用Page Object模式将页面定位和业务操作分开,分离测试对象(元素对象)和测试脚本(用例脚本),一个页面建一个对象类,提高用例的可维护性;

2、使用yaml管理页面控件元素数据和测试用例数据。例如元素ID等发生变化时,不需要去修改测试代码,只需要在对应的页面元素yaml文件中修改即可;

3、分模块管理,互不影响,随时组装,即拿即用。

GitHub项目地址:GitHub - yingoja/DemoUI: selenium UI自动化测试框架

测试框架分层设计

  • 把常见的操作和查找封装成基础类,不管是什么产品,可直接拿来复用
  • 业务层主要是封装对象页面类,一个页面建一个类,业务层页面继承基础层
  • 用例层针对产品页面功能进行构造摸拟执行测试
  • 框架层提供基础组件,支撑整个流程执行及功能扩展,给用例层提供各页面的元素数据、用例测试数据,测试报告输出等

测试框架目录结构


如下思维导图目录结构介绍:

在这我为大家准备了一份软件测试视频教程(含面试、接口、自动化、性能测试等),就在下方,需要的可以直接去观看,也可以直接【点击文末小卡片免费领取资料文档】

软件测试视频教程观看处:

软件测试工程师大忌!盲目自学软件测试真的会毁终生,能救一个是一个......

编写用例方法

 
 1 testinfo:
 2       - id: test_login001
 3         title: 登录测试
 4         info: 打开抽屉首页
 5 testcase:
 6       - element_info: login-link-a
 7         find_type: ID
 8         operate_type: click
 9         info: 打开登录对话框
10       - element_info: mobile
11         find_type: ID
12         operate_type: send_keys
13         info: 输入手机号
14       - element_info: mbpwd
15         find_type: ID
16         operate_type: send_keys
17         info: 输入密码
18       - element_info: //input[@class='keeplogin']
19         find_type: XPATH
20         operate_type: click
21         info: 单击取消自动登录单选框
22       - element_info: //span[text()='登录']
23         find_type: XPATH
24         operate_type: click
25         info: 单击登录按钮
26       - element_info: userProNick
27         find_type: ID
28         operate_type: perform
29         info: 鼠标悬停账户菜单
30       - element_info: //a[@class='logout']
31         find_type: XPATH
32         operate_type: click
33         info: 选择退出
34 check:
35       - element_info: //div[@class='box-mobilelogin']/div[1]/span
36         find_type: XPATH
37         info: 检查输入手机号或密码,登录异常提示
38       - element_info: userProNick
39         find_type: ID
40         info: 成功登录
41       - element_info: reg-link-a
42         find_type: ID
43         info: 检查退出登录是否成功

例如,我们要新增登录功能测试用例:首先,只需在testyaml目录下新增一个页面对象yaml文件,参考login.yaml格式编写即可。这些文件是提供给封装页面对象类调用并执行定位识别操作。

 
 1 -
 2   id: test_login001.1
 3   detail : 手机号和密码为空登录
 4   screenshot : phone_pawd_empty
 5   data:
 6     phone: ""
 7     password: ""
 8   check :
 9      - 手机号不能为空
10 -
11   id: test_login001.2
12   detail : 手机号为空登录
13   screenshot : phone_empty
14   data :
15     phone: ""
16     password : aa
17   check :
18     - 手机号不能为空
19 -
20   id: test_login001.3
21   detail : 密码为空登录
22   screenshot : pawd_empty
23   data :
24     phone : 13511112222
25     password: ""
26   check :
27     - 密码不能为空
28 -
29   id: test_login001.4
30   detail : 非法手机号登录
31   screenshot : phone_error
32   data :
33     phone : abc
34     password: aa
35   check :
36     - 手机号格式不对
37 -
38   id: test_login001.5
39   detail : 手机号或密码不匹配
40   screenshot : pawd_error
41   data :
42     phone : 13511112222
43     password: aa
44   check :
45     - 账号密码错误
46 -
47   id: test_login001.6
48   detail : 手机号和密码正确
49   screenshot : phone_pawd_success
50   data :
51     phone : 13865439800
52     password: ********
53   check :
54     - yingoja
55 
56 login_data.yaml

其次,在testdata目录下新增一个login_data.yaml文件提供给登录接口传参的测试数据,编写格式参考login_data.yaml文件。

 
  1 #!/usr/bin/env python
  2 # _*_ coding:utf-8 _*_
  3 __author__ = 'YinJia'
  4 
  5 import os,sys
  6 sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
  7 from config import setting
  8 from selenium.webdriver.support.select import Select
  9 from selenium.webdriver.common.action_chains import ActionChains
 10 from selenium.webdriver.common.by import By
 11 from public.page_obj.base import Page
 12 from time import sleep
 13 from public.models.GetYaml import getyaml
 14 
 15 testData = getyaml(setting.TEST_Element_YAML + '/' + 'login.yaml')
 16 
 17 class login(Page):
 18     """
 19     用户登录页面
 20     """
 21     url = '/'
 22     dig_login_button_loc = (By.ID, testData.get_elementinfo(0))
 23     def dig_login(self):
 24         """
 25         首页登录
 26         :return:
 27         """
 28         self.find_element(*self.dig_login_button_loc).click()
 29         sleep(1)
 30 
 31     # 定位器,通过元素属性定位元素对象
 32     # 手机号输入框
 33     login_phone_loc = (By.ID,testData.get_elementinfo(1))
 34     # 密码输入框
 35     login_password_loc = (By.ID,testData.get_elementinfo(2))
 36     # 取消自动登录
 37     keeplogin_button_loc = (By.XPATH,testData.get_elementinfo(3))
 38     # 单击登录
 39     login_user_loc = (By.XPATH,testData.get_elementinfo(4))
 40     # 退出登录
 41     login_exit_loc = (By.ID, testData.get_elementinfo(5))
 42     # 选择退出
 43     login_exit_button_loc = (By.XPATH,testData.get_elementinfo(6))
 44 
 45     def login_phone(self,phone):
 46         """
 47         登录手机号
 48         :param username:
 49         :return:
 50         """
 51         self.find_element(*self.login_phone_loc).send_keys(phone)
 52 
 53     def login_password(self,password):
 54         """
 55         登录密码
 56         :param password:
 57         :return:
 58         """
 59         self.find_element(*self.login_password_loc).send_keys(password)
 60 
 61     def keeplogin(self):
 62         """
 63         取消单选自动登录
 64         :return:
 65         """
 66         self.find_element(*self.keeplogin_button_loc).click()
 67 
 68     def login_button(self):
 69         """
 70         登录按钮
 71         :return:
 72         """
 73         self.find_element(*self.login_user_loc).click()
 74 
 75     def login_exit(self):
 76         """
 77         退出系统
 78         :return:
 79         """
 80         above = self.find_element(*self.login_exit_loc)
 81         ActionChains(self.driver).move_to_element(above).perform()
 82         sleep(2)
 83         self.find_element(*self.login_exit_button_loc).click()
 84 
 85     def user_login(self,phone,password):
 86         """
 87         登录入口
 88         :param username: 用户名
 89         :param password: 密码
 90         :return:
 91         """
 92         self.open()
 93         self.dig_login()
 94         self.login_phone(phone)
 95         self.login_password(password)
 96         sleep(1)
 97         self.keeplogin()
 98         sleep(1)
 99         self.login_button()
100         sleep(1)
101 
102     phone_pawd_error_hint_loc = (By.XPATH,testData.get_CheckElementinfo(0))
103     user_login_success_loc = (By.ID,testData.get_CheckElementinfo(1))
104     exit_login_success_loc = (By.ID,testData.get_CheckElementinfo(2))
105 
106     # 手机号或密码错误提示
107     def phone_pawd_error_hint(self):
108         return self.find_element(*self.phone_pawd_error_hint_loc).text
109 
110     # 登录成功用户名
111     def user_login_success_hint(self):
112         return self.find_element(*self.user_login_success_loc).text
113 
114     # 退出登录
115     def exit_login_success_hint(self):
116         return self.find_element(*self.exit_login_success_loc).text

然后,在page_obj目录下新增一个loginPage.py文件,是用来封装登录页面对象类,执行登录测试流程操作。

 
 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'YinJia'
 4 
 5 
 6 import os,sys
 7 sys.path.append(os.path.dirname(os.path.dirname(__file__)))
 8 import unittest,ddt,yaml
 9 from config import setting
10 from public.models import myunit,screenshot
11 from public.page_obj.loginPage import login
12 from public.models.log import Log
13 
14 try:
15     f =open(setting.TEST_DATA_YAML + '/' + 'login_data.yaml',encoding='utf-8')
16     testData = yaml.load(f)
17 except FileNotFoundError as file:
18     log = Log()
19     log.error("文件不存在:{0}".format(file))
20 
21 @ddt.ddt
22 class Demo_UI(myunit.MyTest):
23     """抽屉新热榜登录测试"""
24     def user_login_verify(self,phone,password):
25         """
26         用户登录
27         :param phone: 手机号
28         :param password: 密码
29         :return:
30         """
31         login(self.driver).user_login(phone,password)
32 
33     def exit_login_check(self):
34         """
35         退出登录
36         :return:
37         """
38         login(self.driver).login_exit()
39 
40     @ddt.data(*testData)
41     def test_login(self,datayaml):
42         """
43         登录测试
44         :param datayaml: 加载login_data登录测试数据
45         :return:
46         """
47         log = Log()
48         log.info("当前执行测试用例ID-> {0} ; 测试点-> {1}".format(datayaml['id'],datayaml['detail']))
49         # 调用登录方法
50         self.user_login_verify(datayaml['data']['phone'],datayaml['data']['password'])
51         po = login(self.driver)
52         if datayaml['screenshot'] == 'phone_pawd_success':
53             log.info("检查点-> {0}".format(po.user_login_success_hint()))
54             self.assertEqual(po.user_login_success_hint(), datayaml['check'][0], "成功登录,返回实际结果是->: {0}".format(po.user_login_success_hint()))
55             log.info("成功登录,返回实际结果是->: {0}".format(po.user_login_success_hint()))
56             screenshot.insert_img(self.driver, datayaml['screenshot'] + '.jpg')
57             log.info("-----> 开始执行退出流程操作")
58             self.exit_login_check()
59             po_exit = login(self.driver)
60             log.info("检查点-> 找到{0}元素,表示退出成功!".format(po_exit.exit_login_success_hint()))
61             self.assertEqual(po_exit.exit_login_success_hint(), '注册',"退出登录,返回实际结果是->: {0}".format(po_exit.exit_login_success_hint()))
62             log.info("退出登录,返回实际结果是->: {0}".format(po_exit.exit_login_success_hint()))
63         else:
64             log.info("检查点-> {0}".format(po.phone_pawd_error_hint()))
65             self.assertEqual(po.phone_pawd_error_hint(),datayaml['check'][0] , "异常登录,返回实际结果是->: {0}".format(po.phone_pawd_error_hint()))
66             log.info("异常登录,返回实际结果是->: {0}".format(po.phone_pawd_error_hint()))
67             screenshot.insert_img(self.driver,datayaml['screenshot'] + '.jpg')
68 
69 if __name__=='__main__':
70     unittest.main()

最后,在testcase目录下创建测试用例文件login_sta.py,采用ddt数据驱动读取yaml测试数据文件

综上所述,编写用例方法只需要按以上四个步骤创建->编写即可。执行如下主程序,可看输出的实际结果。

 
 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'YinJia'
 4 
 5 import os,sys
 6 sys.path.append(os.path.dirname(__file__))
 7 from config import setting
 8 import unittest,time
 9 from package.HTMLTestRunner import HTMLTestRunner
10 from public.models.newReport import new_report
11 from public.models.sendmail import send_mail
12 
13 # 测试报告存放文件夹,如不存在,则自动创建一个report目录
14 if not os.path.exists(setting.TEST_REPORT):os.makedirs(setting.TEST_REPORT + '/' + "screenshot")
15 
16 def add_case(test_path=setting.TEST_DIR):
17     """加载所有的测试用例"""
18     discover = unittest.defaultTestLoader.discover(test_path, pattern='*_sta.py')
19     return discover
20 
21 def run_case(all_case,result_path=setting.TEST_REPORT):
22     """执行所有的测试用例"""
23     now = time.strftime("%Y-%m-%d %H_%M_%S")
24     filename =  result_path + '/' + now + 'result.html'
25     fp = open(filename,'wb')
26     runner = HTMLTestRunner(stream=fp,title='抽屉新热榜UI自动化测试报告',
27                             description='环境:windows 7 浏览器:chrome',
28                             tester='Jason')
29     runner.run(all_case)
30     fp.close()
31     report = new_report(setting.TEST_REPORT) #调用模块生成最新的报告
32     send_mail(report) #调用发送邮件模块
33 
34 if __name__ =="__main__":
35     cases = add_case()
36     run_case(cases)

测试结果展示

HTML报告日志

HTML报告点击截图,弹出截图

测试报告通过的日志

自动截图存放指定的目录

邮件测试报告

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/256655.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SecureCRT for Mac/win强大安全的终端SSH工具,SecureCRT助您网络连接无忧

在当今数字化时代,网络连接已成为生活和工作中不可或缺的一部分。而对于需要进行远程访问和管理的用户来说,一个稳定、安全的终端SSH工具是至关重要的。SecureCRT作为一款强大的终端SSH工具,为用户提供了安全、高效的远程连接解决方案。 首先…

如何压缩视频发邮件?帮你整理了几个必备的!

不同邮件附件上限大小有所不同,QQ邮箱的附件大小限制为2GB,这意味着用户可以发送最大为2GB的视频文件;Gmail邮箱的附件大小限制为25MB;163邮箱的附件大小限制为2GB,但是为了保证文件传输的成功率,建议最好不…

SpringBoot 多环境开发配置文件

在开发过程中,往往开发环境和生产环境需要不同的配置。为了兼容两种运行环境,提高开发效率,可以使用多环境开发配置文件。 配置文件结构大概是这样: application.yml -主启动配置文件(用于控制使用哪种环境配…

金和OA jc6 clobfield接口存在SQL注入漏洞

文章目录 产品简介漏洞概述指纹识别漏洞利用修复建议 产品简介 金和OA协同办公管理系统j6软件是一种综合性的协同办公解决方案,旨在提高企业内部的协作效率和工作效率。它提供了一系列功能和工具,帮助组织进行任务管理、日程安排、文件共享、团队协作和…

关于腾讯位置服务路线规划-微信小程序-插件未授权使用

我们点击添加插件会发现添加错误,主要是因为他说不开放给个人用户. 这是我们可以进入微信服务市场直接搜索腾讯位置服务路线规划 | 微信服务市场 (qq.com)点击添加插件即可完成

实战|Smartbi---意外的福利

目录 漏洞描述 影响版本 fofa语法 漏洞复现 构造poc 修复建议 本文由掌控安全学院 - beize 投稿 漏洞描述 Smartbi在安装时会内置几个用户,在使用特定接口时,可绕过用户身份认证机制获取其身份凭证,随后可使用获取的身份凭证调用后台…

统计分析绘图软件 GraphPad Prism 10 mac功能介绍

GraphPad Prism mac是一款专业的统计和绘图软件,主要用于生物医学研究、实验设计和数据分析。 GraphPad Prism mac功能和特点 数据导入和整理:GraphPad Prism 可以导入各种数据格式,并提供直观的界面用于整理、编辑和管理数据。用户可以轻松地…

三菱PLC FX3U滑动平均值滤波

三菱PLC滑动平均值滤波其它相关写法,请参考下面文章链接: https://rxxw-control.blog.csdn.net/article/details/125044013https://rxxw-control.blog.csdn.net/article/details/125044013滑动平均值滤波程序总共分为三部分,第一步为:滑动采样。 第二步为:队列求和,第三…

TypeScript 中的高级类型(联合、交叉、泛型、映射类型)

文章目录 一、联合类型(Union Types)二、交叉类型(Intersection Types)三、泛型3.1 泛型结合extends3.2 泛型结合 keyof3.3 extends keyof 和 in keyof 的区别 四、条件类型(Conditional Types) TypeScript…

德人合科技 | 公司电脑文件加密系统

公司电脑文件加密系统是一种可以对电脑文件进行加密的保护机制。它使用驱动层透明加密技术,能够在用户无感知的情况下对文件进行加密,从源头上保障数据安全和使用安全。 PC端访问地址: www.drhchina.com 此类系统主要有以下几个特点和功能&a…

k8s链接数据库故障Waiting for table metadata lock

场景:早上来发现一个程序,链接mysql数据库有点问题,随后排查,因为容器在k8s里面。所以尝试重启了pod没有效果 一、重启pod: 这里是几种在Kubernetes中重启Pod的方法: 删除Pod,利用Deployment重建 kubectl delete pod mypodDepl…

NPDP证书含金量高吗?跟PMP相比含金量怎么样?

两个证方向不太一样,含金量都挺高的,具体怎么选呢?接着往下看~ PS:不想看长篇大论的,来找我,直接把你的经历甩出来,我帮你判断~ 一、产品经理跟项目经理的区别 表面上,项目经理和产…

第十三章 SpringCloud Alibaba 实现 Seata--分布式事务

分布式事务基础 事务 事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作 都成功,要么所有的操作都被撤销。简单地说,事务提供一种“要么什么都不做,要么做全套”机制。 本地事…

AI日报:OpenAI扩大创业基金计划

欢迎订阅专栏 《AI日报》 获取人工智能邻域最新资讯 文章目录 OpenAI拓宽Converge启动程序变压器模型背后的思想建立启动融资新闻AutoGen AI支点其他 OpenAI拓宽Converge启动程序 ChatGPT制造商OpenAI正在扩大其Converge AI创业计划。 OpenAI的Converge产品于2022年12月首次…

【微服务】springboot整合minio详解

目录 一、前言 二、Minio 概述 2.1 Minio简介 2.1 Minio特点 三、Minio 环境搭建 3.1 部署过程 3.1.1 拉取镜像 3.1.2 启动容器 3.1.3 访问web页面 四、Minio基本使用 4.1 基本概念 4.2 上传文件演示 4.3 用户管理 4.4 Java操作Minio 4.4.1 导入依赖 4.4.2 上传…

docker-compose安装nacos和msql

docker-compose安装nacos和msql 前言前提已经安装docker-compose,如果没有安装,则可以查看上面系列文章中的安装教程。并且文章中使用的是mobaxterm连接虚拟机。 1、下载2、创建并运行 前言 前提已经安装docker-compose,如果没有安装&#x…

三十、鼠标及键盘事件

三十、鼠标及键盘事件 30.1 鼠标事件QMouseEvent 发生鼠标事件,当在 Widget 内按下 (或释放) 鼠标按钮 (或移动鼠标光标) 时。 才发生鼠标移动事件当按下鼠标按钮时,除非启用鼠标跟踪采用 QWidget&#…

亚马逊,速卖通,shein卖家如何准确有效的测评补单

一、合理规划测评时间和数量 卖家需要合理规划测评的时间和数量。如果卖家过于频繁地进行测评,或者在短时间内进行大量的测评,这可能会被视为恶意行为,从而触犯风控机制。因此,卖家需要根据自己的销售情况和市场需求,…

02.微服务组件 Eureka注册中心

1.Eureka注册中心 服务提供者与消费者: 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)一个服务是消费者还是提供者&#xff…

性能测试什么时候开始?性能测试流程介绍

性能测试什么时候开始? 一般在系统功能稳定没有大的缺陷之后开始执行。但前期准备工作可以从系统需求分析时就开始:性能目标制定、场景获取、环境申请等。 一、制定性能测试目标 在特定的并发用户数下测试特定场景的响应时间 在一定的响应时间的要求下来测试特…