当前位置: 首页 > news >正文

【web自动化】-5- fixture集中管理和项目重构

一、投标用例设计 

# 定义让前台页面保持自动登录的fixture
@pytest.fixture()
def user_driver():driver = webdriver.Chrome()driver.get("http://47.107.116.139/fangwei/")driver.maximize_window()# 创建页面类对象page = ReceptionLoginPage(driver)# 通过页面类对象调用方法执行脚本msg = page.login("admin", "msjy123")# 断言实际结果print(msg)assert msg == "成功登录"return driver
  • 如何绕过登录执行投标用例流程,包括投标的正例和反例
  • 在浏览器的驱动第一次执行前台页面登录之后,保持登录状态,在第二次及以上的用例执行投标
定义一个 fixture
  • 完成第一次登录之后进行清除页面缓存
@pytest.fixture()
# 清除缓存的夹具,可以结合第一次登录成功之后的夹具一起结合使用
def clear_deal_page(user_driver):user_driver.get("http://47.107.116.139/fangwei/index.php?ctl=deal&id=25070")
  • 在投标用例中使用清除缓存的 fixture

出现的问题:可以正常流程去登录,但是定位点击马上投标的元素超时

  • 元素找不到
  • 问题出现原因:登录成功之后,界面没有立马出现马上投标元素
def test_user_deal_ok(user_driver, clear_deal_page):# 投标用例执行page = ReceptionLoginPage(user_driver)msg = page.pay("msjy123")print(msg)assert msg == "投标成功!"def test_user_deal_ok2(user_driver, clear_deal_page):# 投标用例执行page = ReceptionLoginPage(user_driver)msg = page.pay("msjy123")print(msg)assert msg == "投标成功!"def test_user_deal_fail(user_driver, clear_deal_page):# 投标用例执行page = ReceptionLoginPage(user_driver)msg = page.pay("msjy1234")print(msg)assert msg == "支付密码错误"

 

  • 由于直接进入投标界面可以实现流程用例执行
  • 解决方案:
    • 由于登录成功之后自动跳转立即投资界面

    • 所以注释点击马上投标的元素

    • 保持登录的夹具: user_driver 作用域改成 session 级别,保持整个页面的自动登录状态

最终结果:

  • 实现投标用例在第一次登录成功之后,不需要继续进行登录,直接执行投标流程用例即可
  • 作用:保持第一次之后的登录状态来完成投标流程用例执行
# 定义用例脚本执行投标步骤:
def pay(self, password):# - 点击马上投标按钮# self.find_element(*self.btn_deal_submit).click()# - 点击立即投资self.find_element(*self.btn_money).click()# - 输入支付密码self.find_element(*self.ipt_pay_password).send_keys(password)# - 点击确定按钮self.find_element(*self.btn_pay_submit).click()# 获取提示信息的实际结果断言预期结果msg = self.find_element(*self.pay_msg, need_wait=True).text# - 关闭提示信息弹框self.find_element(*self.txt_deal_msg).click()# 返回用例执行结果msgreturn msg

1. Fixture 作用域控制(scope="session"

如果 user_driver Fixture 定义时指定了 scope="session"(需补充代码确认,但从场景推断是关键),它会在整个测试会话期间只执行一次

@pytest.fixture(scope="session")  # 关键:作用域为 session,全局共享
def user_driver():driver = webdriver.Chrome()# 登录逻辑...return driver

  • scope="session" 意味着:整个测试运行中,user_driver 只会初始化一次浏览器、执行一次登录,所有依赖它的用例共享同一个浏览器实例,不会重复打开新窗口。

2. 保持登录状态(Cookie/Session 复用)

Web 登录本质是通过 Cookie 或 Session 维持状态:

  • 首次用例执行时,user_driver 完成登录,浏览器会缓存登录态 Cookie。
  • 后续用例复用同一个 driver 实例时,浏览器自带已登录的 Cookie,访问系统时会自动识别登录状态,无需重复登录。

3. 用例依赖共享实例

测试用例通过参数注入 user_driver,所有用例拿到的是同一个浏览器对象

def test_bid_2(user_driver, clear_deal_page):# 复用已登录的 user_driver,无需重新打开窗口/登录page = ReceptionLoginPage(user_driver)  page.pay(...)

因为浏览器实例没销毁,登录状态、页面上下文都被保留,自然 “跳过登录、不新开窗口”。

关键总结

  • Fixture 作用域(session 让浏览器实例全局复用,避免重复初始化。
  • Cookie 持久化 让登录状态在同浏览器实例内自动延续。
  • 最终实现 “一次登录、多例复用”,跳过重复登录和窗口打开流程。

 

在自动化测试流程里,user_driver 结合 clear_deal_page 主要是为了 解决 “登录后页面状态残留” 导致的用例干扰问题

1. 「页面缓存 / 残留状态」的干扰问题

登录后执行投标用例时,页面可能残留上一次操作的状态(比如弹窗未关闭、按钮状态异常、缓存数据未清空):

  • 示例:第一次投标后,页面可能停留在 “支付成功” 提示页,或某些按钮因状态变更无法点击。
  • 影响:后续用例执行时,元素定位会失败(如提示弹窗遮挡按钮),或流程因残留状态报错,导致测试不稳定。

2. clear_deal_page 的核心作用

clear_deal_page 本质是 **“重置页面环境” 的 Fixture**,通常做这些事:

@pytest.fixture()
def clear_deal_page(user_driver):# 1. 跳转到统一的“投标初始化页面”user_driver.get("http://.../deal?reset=1")  # 2. 可能包含清理弹窗、重置按钮状态等操作user_driver.execute_script("window.localStorage.clear();")  # 清理本地缓存return user_driver

  • 重置页面上下文:强制跳转到一个 “干净” 的投标初始页,确保每次用例执行前,页面状态一致(没有残留弹窗、按钮可点击)。
  • 清理缓存 / 状态:通过 JS 清理 localStoragesessionStorage,或关闭残留提示框,避免上一次用例的缓存数据干扰当前用例。

3. 结合 user_driver 的必要性

user_driver 负责维持登录态(共享浏览器实例、保留 Cookie),但无法解决 “页面级的残留状态”:

  • 只靠 user_driver:登录态是保留了,但页面可能因上一次用例操作变得 “不干净”(比如弹窗未关),导致后续用例定位元素超时 / 失败。
  • 结合 clear_deal_page:在保留登录态的基础上,强制重置页面环境,让每个用例都在 “登录且页面干净” 的状态下执行,既复用了登录(提升效率),又避免了页面残留的干扰(保证稳定)。

二、fixture集中管理 

fixture 的使用形式

  • 用例可以直接调用
  • fixture 夹具之间可以进行关联使用
  • fixture 夹具可以完成任意测试用例脚本的前后置编写
  • 一般情况下不同的用例使用自定义的 fixture 进行使用

为了降低用例脚本和 fixture 夹具的耦合性,将 fixture 进行集中管理

fixture 一般统一管理放置项目中固定 conftest.py 文件中

 

fixture 定位顺序:

  • 先从当前运行的 py 文件开始定位 fixture
  • 其次从同级目录的 py 文件中定位 fixture
  • 再从项目包的目录中开始定位定位 fixture
  • 然后从 conftest.py 文件中开始定位 fixture
  • 最后会从项目所有根目录定位 fixture
  • 以上查找定位 fixture 如果没有对应的夹具,那么程序会报错

三、项目重构

对框架代码进行规划和分类

在项目重构的过程中,之前导入的路径使用的模块,会随着目录结构发生变化而变化,不需要手动修改导包路径

  • testcases
    • 封装完成的用例脚本集中管理
  • commons
    • 项目公共模块集中使用包
  • script
    • 用例的线性脚本
  • data
    • 数据文件相关内容
  • log
    • 日志信息相关内容
  • report
    • 缺陷报告记录的内容
  • conftest.py
    • 存放 fixture 夹具的集中管理

 

 

四、统一管理项目驱动

目的:为了方便后期做兼容性测试,使用不同的浏览器来设计驱动获取

from selenium.webdriver import Chrome, Firefox, Ie, Edge, Safari
自定义函数获取对应的浏览器驱动
def get_webdriver(name: str = "chrome"):# 根据调用获取浏览器的实参来返回对应的驱动# 将具体浏览器实参名字进行整理# 将所有浏览器的名字转化为小写# 将所有浏览器的名字中空格去除# 再返回驱动的驱动name = name.lower()name = name.replace(" ", "")# print(name)# 第一种格式:# if name == "chrome":#     return Chrome()# elif name == "firefox":#     return Firefox()# 使用match和case关键字匹配驱动match name:case "chrome":return Chrome()case "firefox":return Firefox()case "ie":return Ie()case "edge":return Edge()

# get_webdriver("C hrome")
# get_webdriver("C H  ro  ME")

自定义获取驱动方式重写之后
  • 需要再创建驱动的地方,调用自定义的get_webdriver ("对应浏览器的名字")

五、后台登录的驱动

# 后台登录页面的驱动
@pytest.fixture(scope="session")
def admin_driver():driver = get_webdriver()driver.get("http://47.107.116.139/fangwei/m.php?m=Public&a=login&")# 使用cookie信息load_cookies(driver)# 如果第一次登录:没有cookie信息那么正常流程登录if is_login(driver):# 验证码处理code = save_code_img(driver)# 完成正常登录流程:使用 POM 封装调用脚本执行page = BackgroundLoginPage(driver)page.login("admin", "msjy123", code)yield driver# 第一次正常登录之后,用例执行结束之后,完成后置保持 cookie 信息save_cookies(driver)

1. 装饰器与 fixture 作用域
@pytest.fixture(scope="session")

  • scope="session":表示该 fixture 的作用域是整个测试会话(session)。也就是说,在一次 pytest 测试运行过程中,这个 admin_driver 夹具只会被初始化一次,然后在所有需要它的测试用例中复用,测试会话结束时才会执行其后置清理逻辑(yield 之后的代码)。这样可以提升测试效率,比如这里用于保持后台登录状态,避免重复登录操作。

 

2. 驱动初始化与页面访问

driver = get_webdriver()
driver.get("http://47.107.116.139/fangwei/m.php?m=Public&a=login&")

  • get_webdriver():调用了一个自定义的函数(这个函数用于根据配置获取对应的浏览器驱动实例,比如 Chrome、Firefox 等浏览器的驱动,方便进行兼容性测试 ),获取到浏览器驱动对象 driver,后续用这个驱动来操作浏览器。
  • driver.get(...):使用获取到的浏览器驱动,打开指定的后台登录页面 URL,让浏览器跳转到对应的登录界面,为后续登录操作做准备。

 

3. Cookie 相关操作

# 使用 cookie 信息
load_cookies(driver)

  • load_cookies(driver):调用自定义函数 load_cookies,作用是尝试从某个地方加载之前保存的 Cookie 信息,并将其注入到当前的浏览器驱动 driver 中。这样做的目的是,如果之前有成功登录过并保存了 Cookie,那么通过加载这些 Cookie,可以直接保持登录状态,无需再次输入账号密码等进行登录,提升测试执行效率。

 

4. 登录流程处理(条件判断)

# 如果第一次登录:没有 cookie 信息那么正常流程登录
if is_login(driver):# 验证码处理code = save_code_img(driver)# 完成正常登录流程:使用 POM 封装调用脚本执行page = BackgroundLoginPage(driver)page.login("admin", "msjy123", code)

  • is_login(driver):调用自定义函数 is_login,用于判断当前浏览器驱动 driver 对应的页面是否处于已登录状态。可能的实现逻辑比如检查页面中是否存在登录后的特定元素(如用户名显示、登录状态标识等 ),或者根据 Cookie 信息判断会话是否有效。如果返回 True,说明需要执行正常的登录流程(一般是首次登录或者 Cookie 失效等情况 )。
  • save_code_img(driver):调用自定义函数 save_code_img,用于处理登录页面的验证码。可能的操作包括截取验证码图片、识别验证码内容(如果结合了验证码识别技术,比如 OCR 等 ),并返回验证码的文本内容 code,以便后续登录时使用。
  • BackgroundLoginPage(driver):这里使用了页面对象模型(POM,Page Object Model )的设计模式,创建一个 BackgroundLoginPage 类的实例 page,并将浏览器驱动 driver 传入。POM 模式把页面的元素定位和操作方法封装到对应的页面类中,便于代码维护和复用。
  • page.login("admin", "msjy123", code):调用 BackgroundLoginPage 类中封装的 login 方法,传入用户名 admin、密码 msjy123 和前面获取到的验证码 code,执行实际的登录操作,模拟用户在页面上输入账号、密码、验证码并提交登录的流程。

 

5. fixture 的 yield 关键字

yield driver

  • yield 是 pytest fixture 中用于分隔前置操作和后置操作的关键字。yield 之前的代码属于前置准备逻辑,执行到 yield 时,会暂停当前 fixture 的执行,将 driver 对象返回给调用它的测试用例使用。当所有依赖该 fixture 的测试用例执行完毕后,会回到这个 fixture,继续执行 yield 之后的代码,也就是后置清理 / 保存操作。

 

6. 后置保存 Cookie 操作

# 第一次正常登录之后,用例执行结束之后,完成后置保持 cookie 信息
save_cookies(driver)

  • save_cookies(driver):调用自定义函数 save_cookies,在测试用例执行完毕后,将当前浏览器驱动 driver 中的 Cookie 信息保存起来(比如保存到文件、数据库等 )。这样,下次再执行测试时,就可以通过前面的 load_cookies 函数加载这些 Cookie,实现免登录或者保持登录状态的效果,提升后续测试的效率,也能模拟实际用户的会话保持场景。

 

http://www.xdnf.cn/news/1162531.html

相关文章:

  • MTSC2025参会感悟:大模型 + CV 重构全终端 UI 检测技术体系
  • OR条件拆分:避免索引失效的查询重构技巧
  • 计算机网络第四章(3)——网络层《IPV4(子网划分、子网掩码)》
  • 模型系列(篇一)-Bert
  • Python Locust库详解:从入门到分布式压力测试实战
  • 5道挑战题writup
  • 跨端分栏布局:从手机到Pad的优雅切换
  • 将 RustFS 用作 GitLab 对象存储后端
  • 前后端分离项目进阶1---前端
  • Ubuntu 22.04 使用 Docker 安装 Redis 5 (安装包形式)
  • 设备虚拟化技术-IRF
  • 电子数据取证领域的双轮驱动——手工分析 vs 自动化分析
  • SpringSecurity 详细介绍(认证和授权)
  • 复制docker根目录遇到的权限问题
  • C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(二)
  • docker磁盘空间不足解决办法
  • MongoDB 查询时区问题
  • linux定时器使用
  • 3、Spring AI_DeepSeek模型-多轮对话
  • 江苏思必驰科技25Java实习面经
  • HTTP,HTTPS
  • 服务器系统时间不准确怎么办?
  • 图论基本算法
  • 部署Zabbix企业级分布式监控
  • 【Unity基础】Unity中2D和3D项目开发流程对比
  • Unity 插件Resize Pro 最快的 Texture2D 调整大小工具
  • Elasticsearch 是 NVIDIA Enterprise AI Factory 验证设计中推荐的向量数据库
  • 数据结构堆的实现(C语言)
  • Web3.0 能为你带来哪些实质性的 改变与突破
  • Vue 脚手架——render函数