0


一篇学会Selenium

一篇学会Selenium 4.0

一、认识Selenium

1. 什么是Selenium

​ Selenium是一个用于Web应用程序自动化测试的工具,它可以模拟用户在浏览器中的操作,如点击、输入等,以检测应用程序的功能和性能。

2. Selenium的发展

​ Selenium起源于2004年,ThoughtWorks为了快速测试Web应用程序而开发的一款工具,这个工具是Selenium。

​ 早期Selenium是一个基于JavaScript的测试工具,被称为Selenium Core。它可以嵌入到浏览器中,通过JavaScript来操作Web页面并验证其功能。后来,Selenium RC(Remote Control)诞生了,它允许测试人员使用自己熟悉的编程语言(如Java、Python等)来编写测试脚本,并通过Selenium RC来控制浏览器执行测试。

​ 2009年,Selenium RC与WebDriver项目合并,形成了Selenium 2,也被称为Selenium WebDriver。WebDriver是一个更现代的浏览器自动化框架,它提供了更简洁、更易用的API,并支持更多的浏览器和操作系统。合并后的Selenium 2结合了Selenium RC和WebDriver的优点,成为了一个更强大、更灵活的Web应用程序测试工具。

​ 随着技术的发展和用户需求的变化,Selenium也在不断改进和升级,最新的Selenium版本是Selenium 4,它在Selenium 3的基础上进行了许多改进和优化。

二、为什么学习Selenium

​ 从2012年到2024年这12年里面,互联网得发展以及人们对于产品质量的要求越来越高,对于测试工程师(Quality Assurance Engineer)的要求从原来的“点点点”到能够使用开发技术进行辅助完成测试,其中开发技术辅助完成测试中,很重要的一环,便是回归测试环节。

​ 随着产品人员的不断迭代,回归测试任务变的越来越重,那么老功能的产品质量,聪明的测试工程师想到了自动化,针对Web UI自动化方面,绝大多数的测试选用了Selenium。

那么Selenium具备哪些优点:

  • 开源免费:Selenium是一个开源项目,用户可以免费使用和定制,这大大降低了测试成本。
  • 多浏览器支持:Selenium支持多种浏览器,如Chrome、Firefox、Safari等,甚至可以支持手机端的浏览器和原生应用程序,覆盖了大部分主流浏览器,可以满足不同需求。
  • 多语言支持:Selenium支持多种编程语言,如Java、Python、Ruby、C#等,方便开发人员使用自己熟悉的语言进行测试开发。
  • 灵活性高:Selenium提供了丰富的API和工具,可以模拟人类操作浏览器,实现点击、输入、滚动等操作,同时也支持各种断言和验证方式,可以灵活地定制测试脚本和测试流程。
  • 跨平台支持:Selenium可以在Windows、Linux和Mac OS等操作系统上运行,方便不同平台之间的协作和测试。
  • 易于使用:Selenium的API设计简单、易懂,同时提供了完善的开发文档,新手能够快速上手。
  • 插件丰富:Selenium有大量的插件和扩展,如WebDriverManager、TestNG、JUnit、pytest等,可以方便地扩展自己的测试用例。
  • 提高测试质量:Selenium可以保证测试环境的一致性和可重复性,有效避免了人为错误,提高测试的准确性和覆盖范围。
  • 支持并行测试:Selenium Grid允许测试人员在多台机器上并行执行测试,以提高测试效率。

三、环境搭建

1. Python虚拟环境管理

在这里插入图片描述

  • 将%ANACONDA%加入到PATH中

在这里插入图片描述

  • 新打开一个CMD,输入conda -V,如果看到了版本号,说明已经配置成功。

在这里插入图片描述

  • 创建虚拟环境 : - 命令行的方式 conda create -n myenv- 打开Anaconda的客户端,进入到客户端中创建虚拟环境
  • 查看虚拟环境列表:conda env list
  • 进入到虚拟环境中:conda activate myenv

在这里插入图片描述

  • 虚拟环境中,输入:pip list,可以查看出当前python所安装的全部包
  • 在虚拟环境中安装依赖包:pip install selenium -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com- -i 命令后面跟的为指定镜像源,因为国外镜像源下载比较慢,所以需要指定一个国内的镜像源,国内常用镜像源:http://pypi.douban.com/simple/ 豆瓣http://mirrors.aliyun.com/pypi/simple/ 阿里http://pypi.hustunique.com/simple/ 华中理工大学http://pypi.sdutlinux.org/simple/ 山东理工大学http://pypi.mirrors.ustc.edu.cn/simple/ 中国科学技术大学

2. 安装IDE

3. 配置虚拟环境

  • 安装完毕后,打开pycharm
  • ctrl + alt +s,打开看Setting页面在这里插入图片描述
  • 添加配置好的虚拟环境在这里插入图片描述
  • 配置创建的虚拟环境在这里插入图片描述
  • 设置完毕后,若是没有看到自己导入的包,点击使用conda的环境在这里插入图片描述

4. 安装Chromedriver

在这里插入图片描述

到这里,环境变量已经全部配置完毕了。

四、Selenium学习

学习大纲

在这里插入图片描述

1. 打开浏览器(Webdriver)

from selenium import webdriver

# webdriver.Chrome() 打开的为谷歌浏览器
driver = webdriver.Chrome()

在这里插入图片描述

  • 我们打开浏览器成功,但是发现当前存在两个小问题(1)显示【正受到自动化测试软件的控制】(2)浏览器仅打开一半,并未自动最大浏览器窗口
  • 去掉【正受到自动化测试软件的控制】options = webdriver.ChromeOptions()options.add_experimental_option('excludeSwitches',['enable-automation'])
  • 窗口默认最大化driver.maximize_window()
  • 其他chrome options 实验性控制参数解释-enable-automation通知用户他们的浏览器是由自动测试控制的-enable-logging控制是否启用控制台日志记录,并可选择配置其路由的位置其他实验的控制:https://blog.csdn.net/ASAS1314/article/details/85059896
  • 浏览器常规一些控制# 无界面模式options.add_argument('headless')# 指定用户客户端-模拟手机浏览options.add_argument('user-agent="MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"')# 禁用图片加载options.add_argument('blink-settings=imagesEnabled=false')# 隐身模式options.add_argument('incognito')# 自动打开开发者工具options.add_argument("auto-open-devtools-for-tabs")# 设置窗口尺寸,注意宽高之间使用逗号而不是xoptions.add_argument('window-size=300,600')# 设置窗口启动位置(左上角坐标)options.add_argument('window-position=120,0')# 禁用gpu渲染options.add_argument('disable-gpu')# 全屏启动options.add_argument('start-fullscreen')# 全屏启动,无地址栏options.add_argument('kiosk')# 启动时,不激活(前置)窗口options.add_argument('no-startup-window')

2. 打开指定网站

url ='指定的网站地址,如(http://www.baidu.com)'
driver.get(url)

3. 元素定位

方法描述By.ID通过元素id进行定位By.CLASS_NAME通过元素class进行定位By.NAME通过元素name进行定位By.TAG_NAME通过元素标签进行定位By.LINK_TEXT通过元素超链接文本全称进行定位By.PARTIAL_LINK_TEXT通过元素超链接文本部分文本进行定位By.XPATH通过元素的xpath路径进行定位(万能定位)By.CSS_SELECTOR通过元素的css selector进行定位(万能定位且定位速度高于xpath)

(1)By.ID

在这里插入图片描述

SEARCH_BOX =(By.ID,'kw')
element = driver.find_element(*SEARCH_BOX)
element.send_keys('By.ID')

结果

在这里插入图片描述

(2)By.CLASS_NAME

在这里插入图片描述

SEARCH_PICTURE_BTN =(By.CLASS_NAME,'soutu-btn')
element = driver.find_element(*SEARCH_PICTURE_BTN)
element.click()

结果

在这里插入图片描述

(3)By.Name

在这里插入图片描述

SEARCH_BOX =(By.NAME,'wd')
element = driver.find_element(*SEARCH_BOX)
element.send_keys('By.NAME')
(4)By.TAG_NAME

在这里插入图片描述

SEARCH_BOX =(By.TAG_NAME,'form')
element = driver.find_element(*SEARCH_BOX)
element = element.find_element(By.CLASS_NAME,'s_ipt')
element.send_keys('By.TAG_NAME')
(5)By.LINK_TEXT

在这里插入图片描述

VIDEO_BTN =(By.LINK_TEXT,'视频')
element = driver.find_element(*VIDEO_BTN)
element.click()
(6)By.PARTIAL_LINK_TEXT
VIDEO_BTN =(By.PARTIAL_LINK_TEXT,'视')
element = driver.find_element(*VIDEO_BTN)
element.click()
(7)By.XPATH

在这里插入图片描述

SEARCH_BOX =(By.XPATH,'//input[@id="kw"]')
element = driver.find_element(*SEARCH_BOX)
element.send_keys('By.XPATH')
(8)By.CSS_SELECTOR

在这里插入图片描述

SEARCH_BOX =(By.CSS_SELECTOR,'#kw')
element = driver.find_element(*SEARCH_BOX)
element.send_keys('By.CSS_SELECTOR')
(9)复族举例:XPATH

在这里插入图片描述

LINKS =(By.XPATH,"//a[@class='s-news-item-title c-link c-font-big  title-clamp-2  has-tts']")
elements = driver.find_elements(*LINKS)print(elements)# 打印出来为一个LINK List,根据自己需要点击哪一个,可以指定索引进行点击
elements[1].click()

4. 操作元素

(1)常见操作

方法描述send_keys(‘要输入的文本’)输入文本方法click()点击操作text获取元素文本is_displayed元素的显示状态

(2)链式操作
  • 操作方式
from selenium.webdriver.common.action_chains import ActionChains

action = ActionChains(driver)# 移动到指定元素上
action2 = action.move_to_element(element)# 执行双击操作
action2.double_click()
  • 常见链式操作
    方法描述move_to_element()鼠标移动到指定元素drag_and_drop(source_element, target_element)将元素拖拽到指定元素drag_and_drop_by_offset(from_a, to_b)将元素拖拽到指定坐标move_by_offset(from_a, to_b)鼠标移动到指定坐标move_to_element_with_offset()鼠标移动到指定坐标key_up()键盘弹起key_down()键盘按下double_click()双击鼠标左键
    (3)Selenium操作浏览器的原理

在这里插入图片描述

​ 我们可以通过driver.get(‘url’)

在这里插入图片描述

在这里插入图片描述

最后执行结果打印:

在这里插入图片描述

(4)其他操作
a. 切换浏览器窗口
# 获取全部窗口的session_id
handles = driver.window_handles
# 获取当前浏览器所处窗口session_id
current_handle = driver.current_window_handle
# 切换至最新的浏览器窗口if current_handle != handles[-1]:
    driver.switch_to.window(handles[-1])
b. 先定位iframe内嵌网页
# 先定位iframe内嵌网页元素
iframe = driver.find_element(By.TAG_NAME,'iframe')# 切换至iframe内嵌网页元素
driver.switch_to.frame(iframe)#若是定位完iframe中元素后,需要执行回到上一个iframe或者主文档# driver.switch_to.default_content()# driver.switch_to.parent_frame()
c. alert 弹框处理
alert = driver.switch_to.alert

# 确认
alert.accept()# 取消
alert.dismiss()# 获取文本
alert.text

5. 等待

(1)强制等待
import time

print(time.time.time())
time.sleep(1)print(time.time.time())
  • 强制等待,顾名思义,需要强制睡眠到指定时间后,才会运行等待时间之后的代码,在selenium脚本中需尽量少用该等待方式,因为强制等待会明显拖慢脚本的执行效率。
  • 三种等待方式中的优先级:最高
(2)隐式等待
driver.implicitly_wait(30)
  • 针对全部元素设置的等待时间
  • 三种等待方式中的优先级:最低
(3)显示等待
# 显示等待方法from selenium.webdriver.support.wait import WebDriverWait
# 期待条件from selenium.webdriver.support import expected_conditions

element = WebDriverWait(driver, timeout=30).until(expected_conditions.visibility_of_element_located())
  • 显示等待,针对指定元素进行等待,当指定元素出现后,便会执行下一步操作
  • 显示等待,默认条件下0.5秒刷新一次当前元素的状态,poll_frequency = 0.5s
  • 三种等待方式中的优先级:

总结:显示等待与隐式等待时间不会叠加,仅会取时间最长的时间进行等待。

五、基于Selenium Web UI自动化测试框架搭建

​ 以上我们已经了解过Selenium基本的用法,已经元素定位的方法,但是直接拿来做为我们UI自动化的测试框架依然不够,我们需要添加更多内容,来丰富充实我们的自动化测试框架,本UP会以5个模块的丰富,来构建我们UI自动化测试框架。

在这里插入图片描述

1. Selenium二次封装

​ 我们通过等待时间以及对于我们UI自动化测试中的元素,有了一定了解后,为了能够更好的定位页面元素以及提高UI自动化测试效率,我们将尽可能元素定位的地方采用显示等待,其次,为了我们方便定位问题,我应该在元素定位的地方能够给予日志。

  • 元素定位显示等待的封装
  • 元素定位中插入日志
(1)元素定位显示等待的封装

以下为一个简单例子:

Common/locator.py

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.remote.webelement import WebElement

classLocator:def__init__(self, driver):

        self.driver = driver
        self.timeout =5defvisible_element(self, locator)-> WebElement:

        element = WebDriverWait(
            driver=self.driver,
            timeout=self.timeout
        ).until(
            expected_conditions.visibility_of_element_located(*locator
            ))return element

下面例子中实现插入日志,需要引入日志包

(2)日志包Loguru引入
pip install loguru -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

在Common文件夹下,创建logging.py的文件

Common/logging.py

from loguru import logger

# 定义日志文件file='log.log'

Logger = logger

# 添加日志输出的文件,已经文件大小,日志保存最大日期7天
Logger.add(file,
    level='INFO',
    rotation='100 MB',
    retention='7 days')
  • 关于add()的参数 - sink:输出目的地,可以是一个文件路径(字符串)、一个文件对象、标准输出 sys.stdout、标准错误 sys.stderr 或者是一个自定义的处理器函数。- level:要捕获的最低日志级别,如 "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"。- format:日志消息的格式字符串。可以使用 {time}, {level}, {message}, {name}, {module}, {file}, {line}, {function}, {exception} 等占位符来自定义格式。- filter:一个函数,用于过滤日志记录。它应该接收一个字典(包含所有日志记录属性,如 "module", "level", "message" 等)并返回一个布尔值,以确定是否应该处理该日志记录。- rotation:日志文件的轮转策略。可以是 "x MB", "x bytes", "x days", "x:00", "weekday x", "monthly" 等。- retention:保留旧日志文件的策略。可以是 "x days", "x weeks", "x months", "x years" 或者一个整数,表示保留的日志文件数量。- compress:是否压缩/归档旧的日志文件。可以是布尔值或者压缩格式的字符串(如 "zip")。- enqueue:是否异步记录日志。如果为 True,则日志消息将首先被添加到一个队列中,然后在后台线程中异步写入。- backtrace:是否显示异常的回溯信息。默认为 True。- diagnose:是否显示日志系统的内部错误和异常。默认为 True。- colorize:是否使用颜色输出日志。默认为 True,但仅在输出到控制台时有效。- serialize:是否将日志记录序列化为 JSON 格式。默认为 False

完善我们封装的selenium元素定位文件里的内容:

classLocator:def__init__(self, driver):

        self.driver = driver
        self.timeout =5defvisible_element(self, locator)-> WebElement:
        Logger.info(f'元素定位方法{locator[0]}, 元素的位置{locator[1]}')try:
            element = WebDriverWait(
                driver=self.driver,
                timeout=self.timeout
            ).until(
                expected_conditions.visibility_of_element_located(*locator
                ))
            Logger.info(f'元素定位方法{locator[0]}, 元素的位置{locator[1]}:元素定位成功')return element
        except Exception as e:
            Logger.error(f'元素定位方法{locator[0]}, 元素的位置{locator[1]}:元素定位失败')raise Exception('元素定位失败:'+str(e))

2. PO设计模型引入

PO(Page Object)设计模型是一种在自动化测试中使用的设计模式,特别是在使用Selenium等Web自动化测试工具时。它主要是为了解决自动化测试中代码量增加、难以维护的问题,通过分层设计来提高测试用例的可读性和可维护性。

PO设计模型的核心思想是将页面定位和业务操作分开,也就是把对象的定位和测试脚本分开。每个页面都被抽象为一个Page类,这个类包含了该页面上的所有元素对象定位和对元素对象的操作。这样,测试用例只需要关注业务流程,而不需要关心具体的元素定位和操作细节。

PO设计模型有以下几个优点:

  1. 代码复用:通过将页面元素和操作封装在Page类中,可以在多个测试用例中复用这些代码,避免了重复编写相同的定位和操作代码。
  2. 可读性强:测试用例只关注业务流程,代码更加简洁、清晰,易于阅读和理解。
  3. 可维护性强:如果页面元素发生变化,只需要修改对应的Page类中的元素定位代码,而不需要修改大量的测试用例。这大大减少了维护成本。
  4. 分层设计:PO设计模型实现了分离解耦,不同的模块使用不同的包来管理,使其关联性降低,更加灵活和可扩展。

在实施PO设计模型时,通常需要遵循以下步骤:

  1. 抽象封装一个BasePage类,这个基类拥有一些指向Webdriver实例的属性,以及一些公共的方法(如打开页面、关闭页面等)。
  2. 对于每个页面,创建一个继承自BasePage的Page类。在这个类中,定义页面上的元素对象(使用适当的选择器进行定位)和对元素对象的操作(如点击、输入等)。
  3. 在测试用例中,使用Page类来执行测试。首先实例化对应的Page类,然后调用其方法来执行测试步骤。

通过遵循PO设计模型,可以大大提高自动化测试的效率和质量,降低维护成本。

简单来说,一个元素可以对应多个操作,所以我们在维护一个元素所有操作的时候,可以仅维护一个元素就可以了。

在这里插入图片描述

从代码角度进行分层展示

  • 目录设置:Pages
  • 每个Page结构如下:
classHomePage(Parent):
    
    element1 =(By.ID,'example 1')
    
    element2 =(By.XPATH,'//*[@class="example 2"]')defexample1_action1(self):
        
        self.visible_element(self.element1).click()defexample1_action2(self):return self.visible_element(self.element1).text
    
    defexample2_action1(self, value):
        
        self.visible_element(self.element2).send_keys(value)defexample2_action2(self):return self.visible_element(self.element2).text

3. 单元测试框架的使用

  • unittest
  • pytest
(1)unittest
  • 优点- 自动化测试:unittest可以自动运行测试用例,无需人工介入,提高了测试效率。- 精准测试:unittest可以对代码进行精细化测试,针对函数、方法等小粒度进行测试,确保每个部分都能正常工作。- 易于组织:unittest提供了测试套件(test suite)的概念,可以将多个测试用例组织在一起,方便管理和执行。- 断言丰富:unittest提供了丰富的断言方法,可以对测试结果进行各种判断,确保测试结果的准确性。- 灵活性强:unittest支持测试夹具(test fixture)的设置和清理,可以在测试用例执行前后进行必要的准备工作和清理工作。此外,还支持跳过测试、预期失败等功能,使得测试更加灵活。- 集成方便:unittest可以与其他自动化测试工具或持续集成工具进行集成,实现自动化测试流程的整合。- 可扩展性:unittest的设计具有良好的扩展性,可以通过编写自定义的测试运行器、结果输出器等来扩展其功能。
  • 缺点- 用例编写繁琐:unittest的测试用例编写相对繁琐,需要编写大量的setUp和tearDown方法来进行测试环境的搭建和清理。虽然提供了测试夹具(test fixture)的概念来简化这部分工作,但在某些情况下仍然显得不够灵活和高效。- 不支持测试用例分组:在unittest中,测试用例是按照定义的顺序线性执行的,不支持根据需要对测试用例进行分组执行。这可能导致在执行大量测试用例时,无法灵活地选择需要执行的测试用例子集。- 报告功能有限:unittest自带的测试报告功能相对简单,只能提供基本的测试结果信息,如测试用例的执行结果(成功或失败)和执行时间等。对于需要更详细的测试报告或者自定义报告格式的情况,可能需要额外的工具或者自定义代码来实现。- 不支持并发执行:unittest默认是顺序执行测试用例的,不支持并发执行。这在执行大量测试用例时可能会成为性能瓶颈,因为无法充分利用计算机的多核性能来加速测试执行。- 断言方法不够丰富:虽然unittest提供了一些基本的断言方法来进行测试结果判断,但在某些复杂的测试场景下可能显得不够灵活和强大。例如,对于需要判断数据结构相似性或者进行复杂逻辑判断的情况,可能需要编写额外的断言代码或者使用第三方断言库来实现。- 与第三方库集成有限:虽然unittest可以与一些自动化测试工具或持续集成工具进行集成,但与一些特定的第三方库的集成可能相对有限。这可能导致在使用某些特定的测试工具或框架时需要额外的配置工作或者无法直接利用unittest的全部功能。
  • 示例当使用unittest编写自动化测试时,你通常会遵循以下步骤:- 导入unittest模块。- 创建一个测试类,该类继承自unittest.TestCase。- 在测试类中,编写以test_开头的方法作为测试用例。- 在测试用例中使用断言方法来验证测试结果。import unittest # 被测试的函数 defadd(a, b):return a + b # 测试类 classTestAddFunction(unittest.TestCase):# 测试用例:验证两个正数相加 deftest_add_positive_numbers(self): result = add(2,3) self.assertEqual(result,5,"两个正数相加的结果不正确")# 测试用例:验证正数与零相加 deftest_add_positive_with_zero(self): result = add(2,0) self.assertEqual(result,2,"正数与零相加的结果不正确")# 测试用例:验证两个负数相加 deftest_add_negative_numbers(self): result = add(-2,-3) self.assertEqual(result,-5,"两个负数相加的结果不正确")# 运行测试 if __name__ =='__main__': unittest.main()
(2)pytest

安装

pip install pytest -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
  • 优点- 简单灵活,容易上手:pytest的语法非常简洁明了,测试函数的编写和执行都很直观,使得入门非常简单。同时,它也支持复杂的测试场景,可以通过简单的配置和装饰器实现丰富的测试功能。- 支持参数化:pytest允许你对测试用例进行参数化,这意味着你可以使用不同的输入数据来运行同一个测试用例,以确保代码在各种情况下都能正常工作。- 能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests):pytest的灵活性使得它可以满足各种类型的测试需求,无论是单元测试还是功能测试,甚至是自动化测试和接口测试,都可以通过pytest来实现。- 具有很多第三方插件,并且可以自定义扩展:pytest的生态系统非常丰富,有大量的第三方插件可以使用。这些插件可以帮助你实现各种测试需求,比如生成测试报告、并发执行测试用例、失败重试等。同时,pytest也支持自定义扩展,你可以根据自己的需求编写插件来扩展pytest的功能。- 测试用例的skip和xfail处理:pytest允许你标记某些测试用例为跳过或者预期失败,这使得你可以灵活地控制测试用例的执行。比如,在某些特定的环境下跳过某些测试用例,或者在某个功能还没有完全实现时将其标记为预期失败。- 可以很好的和Jenkins集成:pytest可以与持续集成工具Jenkins进行集成,实现自动化测试与持续集成的结合。这样,你可以在代码提交后自动运行测试用例,确保代码的质量。- 报告框架----allure 也支持了pytest:allure是一个强大的测试报告工具,它可以生成详细的、可视化的测试报告。pytest支持allure报告框架,你可以使用allure来生成pytest的测试报告,使得测试结果更加直观、易于理解。- 在编写测试用例类的时候不需要继承其他类,也不需要写init方法:这使得测试用例的编写更加简洁、灵活。你不需要继承任何特定的类或实现任何特定的方法,只需要编写测试函数并使用pytest提供的断言方法即可。
  • 缺点- 固定的表格编写形式:pytest在某些情况下可能使得简单的语法变得复杂化,并且不支持更复杂的语法结构,这可能会降低测试人员的代码编写能力,并导致编写疲劳。- 测试数据和测试代码紧耦合:在pytest中,测试数据和测试代码通常写在同一个文件或同一个方法中,这种紧耦合的方式可能会在修改测试数据或测试代码时相互影响,从而增加了维护的难度。- 对于大型项目可能不够高效:随着业务量的增加和迭代次数的增多,pytest的测试用例可能会变得难以维护。特别是当项目规模很大时,可能需要花费更多的时间来管理和执行测试用例。- 某些高级功能可能需要额外学习:虽然pytest本身易于上手,但其一些高级功能(如参数化测试、fixtures、插件等)可能需要额外的学习和理解才能充分利用。- 社区支持和文档可能有限:与一些更主流的测试框架相比,pytest的社区支持和官方文档可能相对较少。这可能会在查找解决方案或解决问题时造成一定的困难。- 与某些工具集成可能有限:虽然pytest可以与许多流行的工具和框架集成(如Jenkins、allure等),但与某些特定工具或框架的集成可能受到限制或需要额外的配置工作
  • 示例conftest.py文件的编写import pytestfrom selenium import webdriverfrom Pages.home_page import HomePageclassWebObject:[email protected](scope='class')definit(): options = webdriver.ChromeOptions() options.add_experimental_option('excludeSwitches',['enable-automation']) driver = webdriver.Chrome(options=options) driver.maximize_window() Home = HomePage(driver)setattr(WebObject,'Home', Home)yield WebObject driver.quit()test_01_homepage.py文件的编写import pytestimport inspectfrom logging import [email protected]:deftest_01_example1(self, init): Logger.info(inspect.stack()[0][3]) action_result_1 = init.Home.example1_action1() action_result_2 = init.Home.example1_action2()assert action_result_1 != action_result_2,'执行失败'

4. 报告

  • 原生报告
  • Allure报告
(1)原生报告
pip install pytest-html -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

代码编写:

main.py

if __name__ =='__main__':
    pytest.main(['--html','report.html'])

自动会运行项目中有所test_开头或 _test.py结尾的文件。

(2)Allure报告

​ Allure报告是一个灵活、轻量级的开源测试报告生成框架,它支持绝大多数测试框架,如TestNG、Pytest、JUnit等。Allure报告提供了清晰的测试结果可视化,包括测试用例的状态、执行时间、错误信息等,以及丰富的交互功能,如筛选、排序、搜索等,使得测试结果更加直观、易于理解和分析。

​ 在pytest中使用Allure报告生成器,可以方便地生成美观的测试报告。首先,需要安装Allure命令行工具,并将其添加到系统的环境变量中。然后,在pytest测试代码中添加Allure相关的装饰器和注解,以便记录测试用例的元数据和执行信息。最后,通过命令行执行pytest测试,并指定Allure报告的生成方式和输出目录。

Allure报告的特点包括:

  • 可扩展性:Allure报告支持自定义插件和扩展,可以根据项目需求进行定制和扩展。
  • 交互性:Allure报告提供了丰富的交互功能,如筛选、排序、搜索等,方便用户对测试结果进行查看和分析。
  • 可视化:Allure报告以清晰的图表和表格展示测试结果,使得测试结果更加直观、易于理解。
  • 灵活性:Allure报告支持多种测试框架和语言,可以方便地集成到现有的测试体系中。

​ 需要注意的是,为了生成Allure报告,需要在测试执行过程中收集测试数据,并将其保存为Allure可以解析的格式(如XML)。这通常可以通过在测试框架中集成Allure适配器或使用Allure命令行工具来实现。在生成报告之前,还需要确保已经安装了Allure命令行工具,并将其添加到系统的环境变量中。

安装地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/

  1. 先安装java jdk,因为allure是一个java程序
  2. 安装allure-commandline,将它解压后,需要将其配置到环境变量中
  3. 安装allure-pytest
pip install allure-pytest -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

Allure报告生成器,可以方便地生成美观的测试报告。首先,需要安装Allure命令行工具,并将其添加到系统的环境变量中。然后,在pytest测试代码中添加Allure相关的装饰器和注解,以便记录测试用例的元数据和执行信息。最后,通过命令行执行pytest测试,并指定Allure报告的生成方式和输出目录。

Allure报告的特点包括:

  • 可扩展性:Allure报告支持自定义插件和扩展,可以根据项目需求进行定制和扩展。
  • 交互性:Allure报告提供了丰富的交互功能,如筛选、排序、搜索等,方便用户对测试结果进行查看和分析。
  • 可视化:Allure报告以清晰的图表和表格展示测试结果,使得测试结果更加直观、易于理解。
  • 灵活性:Allure报告支持多种测试框架和语言,可以方便地集成到现有的测试体系中。

​ 需要注意的是,为了生成Allure报告,需要在测试执行过程中收集测试数据,并将其保存为Allure可以解析的格式(如XML)。这通常可以通过在测试框架中集成Allure适配器或使用Allure命令行工具来实现。在生成报告之前,还需要确保已经安装了Allure命令行工具,并将其添加到系统的环境变量中。

安装地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/

  1. 先安装java jdk,因为allure是一个java程序
  2. 安装allure-commandline,将它解压后,需要将其配置到环境变量中
  3. 安装allure-pytest
pip install allure-pytest -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

示例,对于test_01_homepage.py文件的编写示例改写

import pytest
import inspect
from logging import Logger
import allure

@allure.feature('Home Page')@pytest.mark.usefixturesclassTestHomepage:@allure.story('example 1的简单使用')@allure.title('校验example1的示例1')@allure.severity(allure.severity_level.NORMAL)deftest_01_example1(self, init):
        Logger.info(inspect.stack()[0][3])with allure.step('步骤1'):
            action_result_1 = init.Home.example1_action1()with allure.step('步骤2'):
            action_result_2 = init.Home.example1_action2()assert action_result_1 != action_result_2,'执行失败'@allure.story('example 1的简单使用')@allure.title('校验example1的示例2')@allure.severity(allure.severity_level.NORMAL)deftest_01_example2(self, init):
        Logger.info(inspect.stack()[0][3])with allure.step('步骤1'):
            action_result_1 = init.Home.example1_action1()with allure.step('步骤2'):
            action_result_2 = init.Home.example1_action2()assert action_result_1 != action_result_2,'执行失败'if __name__ =='__main__':# report_data是一个文件夹,并指定执行目标文件test_01_homepage.py
    pytest.main(['--alluredir', report_data,'test_01_homepage.py'])# cmd到report_data的目录
    os.system('allure serve %s' report_data)

以下是一些

allure-pytest

中常用的装饰器:

  1. @allure.title() - 设置测试用例的标题。
  2. @allure.description() - 添加测试用例的描述。
  3. @allure.story() - 将测试用例关联到一个或多个故事(或特性、需求)。
  4. @allure.severity() - 设置测试用例的严重性等级(如阻塞、严重、正常、轻微、微不足道)。
  5. @allure.tag() - 为测试用例添加标签,可以用于过滤和分组。
  6. @allure.feature() - 定义测试用例所属的功能模块。
  7. @allure.link() - 添加与测试用例相关的链接。
  8. @allure.issue() - 关联测试用例与问题跟踪系统中的问题。
  9. @allure.testcase() - 关联测试用例与测试管理系统中的测试用例。

完整项目框架示例

gitee地址:https://gitee.com/liu-shaoqing-hacker/selenium_web/tree/master/pythonProject

有疑问的地方可以进群
在这里插入图片描述


本文转载自: https://blog.csdn.net/weixin_46198734/article/details/136263502
版权归原作者 刘少卿L 所有, 如有侵权,请联系我们删除。

“一篇学会Selenium”的评论:

还没有评论