webUI自动化测试框架

 🔥 交流讨论:欢迎加入我们一起学习!

🔥 资源分享耗时200+小时精选的「软件测试」资料包

🔥 教程推荐:火遍全网的《软件测试》教程  

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

一、设计思路

框架采用python3+yaml+po+unittest+HTMLTestRunner等技术编写的UI自动化测试框架
1.使用Page Object模式将页面定位和业务操作分开,分离测试对象(元素对象)和测试脚本(用例脚本),一个页面建一个对象类,提高用例的可维护性;
2.使用yaml管理页面空间元素和测试用例数据。例如一个页面元素发生变化时,不需要去修改代码,只需要在对应的页面元素yaml文件中修改即可。
3.以每个页面作为模块管理,随时组装,互不影响。

二、测试框架分层

1.框架层:基础组件封装,支撑整个框架的流程执行及功能扩展
2.用例层:根据用例场景构造test测试方法
3.业务层:封装页面对象类,一个页面建立一个类,业务层基础基础层page类
4.基础层:二次开发selenium的元素定位已经操作
 

三、编写用例方法

例如我需要新增百度搜索测试场景用例:

1.在testyaml目录下新增一个页面对象yaml文件,利用封装的yamlload方法将yaml文件中的dom元素读取出来,提供给封装页面对象类调用并定元素操作。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

testinfo:

      - id: test_login001

        title: 登录百度网页测试

        info: 打开百度首页

testcase:

      - element_info: s-usersetting-top

        find_type: ID

        operate_type: click

        info: 打开登录对话框

      - element_info: userName

        find_type: ID

        operate_type: send_keys

        info: 输入用户名称

      - element_info: TANGRAM__PSP_11__password

        find_type: ID

        operate_type: send_keys

        info: 输入密码

      - element_info: TANGRAM__PSP_11__submit

        find_type: ID

        operate_type: click

        info: 单击登录按钮

check:

      - element_info: //*[@id="user"]/span[2]

        find_type: XPATH

        info: 检查用户是否登录

  

2.在testdata目录下新增一个yaml文件提供给用例测试数据

1

2

3

4

5

6

7

8

9

-

  id: test_login001.1

  detail : 验证登录成功

  screenshot : phone_pawd_empty

  data:

    username: 13501198450

    password: Han520520

  check :

     - hhil833

3.在page_obj目录编写百度搜索场景的页面对象类封装

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

testData = getyaml(setting.TEST_Element_YAML + '/' + 'baidu_login.yaml')

class baidu_login(Page):

    def  open_login(self,username,pwd):

        """

              :return:

              """

        dig_login_button_loc = (By.ID, testData.get_elementinfo(0))

        self.find_element(*dig_login_button_loc).click()

        sleep(1)

    def go_login(self,username,pwd):

        self.find_element(By.ID, testData.get_elementinfo(1)).send_keys(username)

        sleep(1)

        self.find_element(By.ID, testData.get_elementinfo(2)).send_keys(pwd)

        sleep(1)

        self.find_element(By.ID, testData.get_elementinfo(3)).click()

    def user_login(self, username, pwd):

        self.go_login(username,pwd)

        sleep(1)

        check = (By.ID, By.ID,testData.get_CheckElementinfo(0))

        return  self.find_element(*check).text

4.在testcase目录编写测试用例文件,采用ddt数据驱动读取yaml测试数据源文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

@ddt.data(*testData)

def user_login_verify(self, username, password):

    """

           用户登录

           :param phone: 手机号

           :param password: 密码

           :return:

           """

    baidu_login(self.driver).user_login(username,password)

def test_login(self,datayaml):

    """

            登录测试

            :param datayaml: 加载login_data登录测试数据

            :return:

            """

    self.log.info("当前执行测试用例ID-> {0} ; 测试点-> {1}".format(datayaml['id'],datayaml['detail']))

    # c = self.user_login_verify(datayaml["username"],datayaml["password"])

    # log.info("检查点-> {0}".format(c))

    # self.assertEqual(c, datayaml['check'][0],

    #                  "成功登录,返回实际结果是->: {0}".format(c))

5.通过多线程将驱动传给执行方法,并行开启多个浏览器执行测试

1

2

3

4

5

6

7

8

9

10

11

12

def run_case(self,function,name):

    thread_list=[]

    for in range(1):

        appium_server = threading.Thread(target=function,args=(name,))

        thread_list.append(appium_server)

        for in thread_list:

            j.start()

def run_casea(self):

    name = ["chrome""chrome"]

    for in name:

        self.run_case(self.test_baidu,i)

  

6.操作元素封装

1

2

3

4

5

6

7

8

9

10

11

12

13

def get_element(self, find_type, element=""):

    # getdata = getyaml(file)

    # type = getdata.get_find_type(find_type_index)

    if find_type == "id" or find_type == "ID":

        print(1111111111111111111111)

        return self.driver.find_element_by_id(element)

    elif find_type == "xpath" or find_type == "XPATH":

        return self.driver.find_element_by_xpath(element)

    elif find_type == "name" or find_type == "NAME":

        return self.driver.find_element_by_name(element)

    else:

        raise Exception("错误!")

7.浏览器驱动封装

from typing import Union, Type
from selenium.webdriver import *
from selenium.webdriver.opera.options import Options as OperaOptions
from selenium.webdriver.edge.options import Options as EdgeOptions
from setting import *BROWSERS = (Chrome, Ie, Firefox, Edge, Opera, PhantomJS)
OPTIONS = (ChromeOptions, IeOptions, FirefoxOptions, EdgeOptions, OperaOptions)class BROWSER:CHROME_DRIVER_PATH = CHROME_DRIVER_PATH# 使用32位ie驱动解决文本输入缓慢的问题IE_DRIVER_PATH = IE_DRIVER_PATHFIREFOX_DRIVER_PATH = FIREFOX_DRIVER_PATHEDGE_DRIVER_PATH = EDGE_DRIVER_PATHOPERA_DRIVER_PATH = OPERA_DRIVER_PATHHEADLESS = HEADLESS# IMPLICITLY WAITING TIME METHODIMPLICITLY_WAIT_TIME = 10# PAGE SOURCE LOAD TIME METHODPAGE_LOAD_TIME = 10# the script should wait during an# execute_async_script call before throwing an errorSCRIPT_TIMEOUT = 0# SET WINDOW SIZE METHODWINDOWS_SIZE = (1024, 900)def __init__(self, browser_type: Type[Union[Chrome, Ie, Firefox, Edge, Opera, PhantomJS, Remote]] = Chrome,option_type: Type[Union[FirefoxOptions, ChromeOptions, IeOptions, EdgeOptions, OperaOptions]] = ChromeOptions,driver_path: str = CHROME_DRIVER_PATH):if not issubclass(browser_type, BROWSERS):raise TypeErrorif not issubclass(option_type, OPTIONS):raise TypeErrorif not isinstance(driver_path, str):raise TypeErrorself._driver = browser_typeself._option = option_typeself._path = driver_path@propertydef browser(self):"""subclass should implement this methodreturn the instance of WebDriver:return:"""return@propertydef _options(self):"""subclass should implement this methodreturn instance of the Option Type like ChromeOptions:return:"""returnclass CHROME(BROWSER):METHOD_MARK = TrueIMPLICITLY_WAIT_TIME = 30PAGE_LOAD_TIME = 20SCRIPT_TIMEOUT = 10# HEADLESS MODEL OPTIONHEADLESS = FalseOPTION_MARK = True# EXPERIMENTAL OPTIONEXPERIMENTAL = {# 'mobileEmulation': {'deviceName': 'iPhone 6'},  #以移动格式现实启动页面做h5时候会用到'excludeSwitches': ['enable-automation'] #浏览器启动时左上角提示正在运行自动化}# WINDOW SIZE OPTIONWINDOW_SIZE = ''# WINDOW_SIZE = '--window-size=1920,1080'# START MAXIMIZED OPTIONSTART_MAXIMIZED = '--start-maximized'@propertydef _options(self):"""chrome浏览器特有的操作属性:return:"""if self.OPTION_MARK:chrome_option = self._option()chrome_option.headless = self.HEADLESSif self.WINDOW_SIZE:chrome_option.add_argument(self.WINDOW_SIZE)if self.START_MAXIMIZED:# chrome_option.add_argument(self.START_MAXIMIZED)chrome_option.add_argument('--headless')chrome_option.add_argument('--disable-gpu')for k, v in self.EXPERIMENTAL.items():chrome_option.add_experimental_option(k, v)return chrome_optionreturn None@propertydef browser(self):"""启动chrome浏览器并进行初始配置:return:"""if self._options:chrome = self._driver(self._path, options=self._options)else:chrome = self._driver(self._path)if self.METHOD_MARK:chrome.implicitly_wait(self.IMPLICITLY_WAIT_TIME)chrome.set_page_load_timeout(self.PAGE_LOAD_TIME)chrome.set_script_timeout(self.SCRIPT_TIMEOUT)return chromeclass IE(BROWSER):IMPLICITLY_WAIT_TIME = 20PAGE_LOAD_TIME = 10SCRIPT_TIMEOUT = 10WINDOWS_SIZE = (1600, 1024)CLEAN_SESSION = TrueATTACH_TIMEOUT = 10000MARK = Truedef __init__(self):super(IE, self).__init__(browser_type=Ie,option_type=IeOptions,driver_path=super().IE_DRIVER_PATH)@propertydef _options(self):"""ie浏览器特有的操作属性:return:"""ie_option = self._option()ie_option.browser_attach_timeout = self.ATTACH_TIMEOUTie_option.ensure_clean_session = self.CLEAN_SESSIONreturn ie_option@propertydef browser(self):"""启动ie浏览器并进行初始配置:return:"""if self.MARK:ie = self._driver(self._path, options=self._options)else:ie = self._driver(self._path)ie.implicitly_wait(self.IMPLICITLY_WAIT_TIME)ie.set_page_load_timeout(self.PAGE_LOAD_TIME)ie.set_script_timeout(self.SCRIPT_TIMEOUT)ie.set_window_size(*self.WINDOWS_SIZE)return ieclass FIREFOX(BROWSER):def __init__(self):super(FIREFOX, self).__init__(browser_type=Firefox,option_type=FirefoxOptions,driver_path=super().FIREFOX_DRIVER_PATH)@propertydef _options(self):returndef browser(self):return self._driver(self._path)class OPERA(BROWSER):def __init__(self):super(OPERA, self).__init__(browser_type=Opera,option_type=OperaOptions,driver_path=super().OPERA_DRIVER_PATH)@propertydef _options(self):returndef browser(self):return self._driver(self._path)

最后我邀请你进入我们的【软件测试学习交流群:785128166】, 大家可以一起探讨交流软件测试,共同学习软件测试技术、面试等软件测试方方面面,还会有免费直播课,收获更多测试技巧,我们一起进阶Python自动化测试/测试开发,走向高薪之路

作为一个软件测试的过来人,我想尽自己最大的努力,帮助每一个伙伴都能顺利找到工作。所以我整理了下面这份资源,现在免费分享给大家,有需要的小伙伴可以关注【公众号:程序员二黑】自提!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#中实现接口的一些小知识(C#用abstract或virtual来实现接口成员)

文章目录 不可用的修饰可用的修饰非抽象类实现接口抽象类实现接口抽象类与接口方法同名时一同实现 不可用的修饰 在C#中实现接口时,我们不能直接使用static或const来实现接口成员,因为接口中的成员默认都是实例成员,并且它们表示一种契约&am…

c++的STL(2)-- vector容器

目录 1. 默认构造 代码: 相关知识点: 2. 有参构造函数 以及 使用{}初始化对象 代码: 相关知识点: 3. vector容器在尾部添加和删除元素 代码: 使用push_back()和pop_back()进行尾部元素的添加和删除 相关知识点: 代码: 使用emplace_back在尾部添…

人工蜂群算法

人工蜂群算法 人工蜂群算法(Artificial Bee Colony Optimization,ABC)是一种基于蜜蜂觅食行为的优化算法,由土耳其学者Karaboga于2005年提出,算法模拟蜜蜂的采蜜行为对优化问题进行求解。 算法原理 ABC算法的核心思想是将优化问…

Mysql学习笔记之事务详解(读未提交、读以提交、可重复读、串行化读)

在这个博主的基础上,增加两种情况的对比:https://blog.csdn.net/llllllkkkkkooooo/article/details/108068919 可重复读中幻读现象(未使用MVCC) 设置可重复读的隔离级别 set global transaction isolation level repeatable read…

「解析文件流,Java之FileOutputStream助您轻松操作文件!」

🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!&#xf…

TCP重传机制、滑动窗口、拥塞控制

一、总述 TCP,Transmission Control Protocol,是一个面向连接、基于流式传输的可靠传输协议,考虑到的内容很多,比如数据包的丢失、损坏、分片和乱序等,TCP协议通过多种不同的机制来实现可靠传输。今天,重点…

复试人工智能前沿概念总结

1.大模型相关概念(了解即可) 1.1 GPT GPT,全称为Generative Pre-training Transformer,是OpenAI开发的一种基于Transformer的大规模自然语言生成模型。GPT模型采用了自监督学习的方式,首先在大量的无标签文本数据上进…

Android使用WebView打开内嵌H5网页

Android打开外部网页链接请参考上一篇文章 https://public.blog.csdn.net/article/details/136384559 继上篇,新建assets文章夹,将H5的网页资源放到此文件夹下 把H5的资源文件都拷进来 这个时候,将添加打开本地网页的代码: //打…

【活动】2024年AI辅助研发:深度变革与无限潜力

作为一名前端程序员,深入探讨2024年AI在软件研发领域的应用趋势及其影响,我们可以看到一场引人注目的转型正在发生。AI辅助研发对于前端开发而言,不仅意味着效率的飞跃,更是在用户体验设计、代码编写、性能优化、项目管理等诸多方…

Java零基础 - 数组的定义和声明

哈喽,各位小伙伴们,你们好呀,我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。 我是一名后…

httprunner用例结构(前后置)

说明:httprunner 结合 pytest 的前后置方式 1. 用例级别前后置 1.1. setup teardown class TestCaseRefTestcase(HttpRunner):# 用例级别前后置def setup(self):logger.warning("------用例级别前置")def teardown(self):logger.warning("------用…

在Vue中处理接口返回的二进制图片数据

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…

Android使用WebView打开外部网页链接

发布Android应用,除了用原生开发外,更多是采用内嵌H5网页的方式来做,便于更新以及多平台使用。 一、第一种方式是直接通过WebView打开外部H5链接。 新建Android工程 直接创建一个工程,点击运行就可以了,打开是个空页…

2024 批量下载公众号文章内容/阅读数/在看数/点赞数/留言数/粉丝数导出pdf文章备份(带留言):公众号记忆承载近1500篇历史文章在线查看,找文章方便了

关于公众号文章批量下载,我之前写过很多文章: 视频更新版:批量下载公众号文章内容/话题/图片/封面/音频/视频,导出html,pdf,excel包含阅读数/点赞数/留言数 2021陶博士2006/caoz的梦呓/刘备我祖/六神读金…

打造禹州中医药大模型,以AI驱动业务创新(内附孙思邈GPT内测版)

大禹智库 第78 期(总第409 期) 2024年 3 月 4 日 在中医药传承与发展的关键时期,结合许昌市的地域特色和产业优势,大禹智库提出“打造禹州中医药大模型,以AI驱动业务创新”的战略构想。本报告围绕构建禹州中医药现代化…

旅游陪同翻译,英译中需要具备什么能力!

随着中国旅游业的蓬勃发展,越来越多的外国游客选择踏足这片充满魅力的土地。然而,语言障碍常常成为他们探索中国文化的绊脚石。在这时,旅游陪同翻译应运而生,为游客提供了便捷的语言沟通服务,让他们的旅程更加顺畅和愉…

河北省国际光伏展览会

能源是国民经济发展的重要基础之一。随着国民经济的发展,能源的缺口增大,能源安全及能源在国民经济中的地位越显突出。我国是世界上少数几个能源结构以煤为INVITATION主的国家之一,也是世界上最大的煤炭消费国,燃煤造成的环境污染…

云轴科技ZStack荣获证券基金行业信息技术应用创新联盟年度优秀成员奖

近日,由中国证监会科技监管司、上海市经济和信息化委员会及上交所理事会科技发展委员会指导,证券基金行业信息技术应用创新联盟(简称信创联盟)主办的2023年年度工作会议在上海成功举办。会议汇聚了来自监管机构、政府机构、行业侧…

Spring Cloud Gateway自定义断言

问题:Spring Cloud Gateway自带的断言(Predicate)不满足业务怎么办?可以自定义断言! 先看Spring Cloud Gateway是如何实现断言的 Gateway中断言的整体架构如下: public abstract class AbstractRoutePred…