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

Python+Playwright:编写自动化测试的避坑策略

Python+Playwright:编写自动化测试的避坑策略

  • 前言
    • 一、告别 `time.sleep()`,拥抱 Playwright 的智能等待
    • 二、选择健壮、面向用户的选择器,优先使用 `data-testid`
    • 三、严格管理环境与依赖,确保一致性
    • 四、分离测试数据与逻辑,灵活管理数据
    • 五、采用 POM 等设计模式,构建可维护的测试架构
    • 六、理解并适时利用 Playwright 的 Async API
    • 七、重视错误处理、日志和报告,尤其是 Trace Viewer
  • 结语

前言

  • 对于刚接触 Playwright 或自动化测试不久的新手而言,很容易因为一些常见的误区或不良实践,导致测试脚本脆弱、难以维护、执行效率低下,频繁出现不稳定的测试;
  • 今天,我将给大家梳理下,在使用 Python 结合 Playwright 进行自动化测试时,有哪些最常见的一些“坑点”。我们将深入分析这些坑点的成因,并结合 Playwright 的设计理念和最佳实践,提供切实可行的“避坑策略”。

一、告别 time.sleep(),拥抱 Playwright 的智能等待

这是自动化测试新手最容易犯的错误,也是导致测试不稳定的罪魁祸首之一。当页面元素尚未加载完成或某个动作尚未执行完毕时,为了“等待”,许多人会下意识地使用 time.sleep()

坑点分析:

  1. 效率低下: 如果元素提前加载完成,time.sleep() 仍然会强制等待固定时间,浪费宝贵的测试执行时间。
  2. 不可靠: 如果网络波动或系统负载导致元素加载时间超过预设的 sleep 时间,测试将直接失败。你无法预知一个精确的等待时间,只能不断尝试增加秒数,但这治标不治本。
  3. 掩盖问题: 有时,sleep 能够“碰巧”让测试通过,但这可能掩盖了潜在的性能问题或程序 Bug。

避坑策略:充分利用 Playwright 内置的等待机制

Playwright 的核心设计理念之一就是“自动等待”。这意味着大多数与页面交互的操作(如 click(), fill(), expect(locator).to_be_visible() 等)在执行前,都会自动等待目标元素达到可操作状态(如可见、稳定、启用等)。

除了自动等待,Playwright 还提供了丰富的显式等待 API,用于处理更复杂的同步场景:

  • page.wait_for_selector(selector, **kwargs): 等待指定的选择器匹配的元素出现在 DOM 中,并满足特定状态(如 state='visible', state='attached')。
    # 等待 ID 为 'submit-button' 的元素可见
    page.wait_for_selector("#submit-button", state="visible")
    page.click("#submit-button")
    
  • page.wait_for_load_state(state='load', **kwargs): 等待页面达到特定的加载状态,如 load (默认,window.load 事件触发), domcontentloaded (DOMContentLoaded 事件触发), networkidle (网络在一段时间内处于空闲状态)。
    # 等待页面加载完成且网络基本空闲
    page.wait_for_load_state("networkidle")
    
  • page.wait_for_url(url, **kwargs): 等待页面 URL 变为指定的 URL (可以是字符串、正则表达式或函数)。
    # 点击登录后,等待跳转到 dashboard 页面
    page.click("#login-button")
    page.wait_for_url("**/dashboard")
    
  • page.wait_for_event(event, **kwargs): 等待特定的事件触发,例如 popup, request, response 等。
    # 点击按钮预期会打开新标签页
    with page.context.expect_page() as new_page_info:page.click("#open-new-tab-button")
    new_page = new_page_info.value
    new_page.wait_for_load_state()
    print(f"New page URL: {new_page.url}")
    
  • expect(locator).to_be_visible(**kwargs) / to_be_enabled(**kwargs) / to_contain_text(**kwargs) 等断言: Playwright 的 expect 函数结合了断言和等待。它会在超时时间内不断轮询,直到条件满足或超时。这是编写健壮断言的首选方式。
    from playwright.sync_api import expect# 等待元素可见,并且包含文本 'Welcome'
    welcome_message = page.locator("#welcome-message")
    expect(welcome_message).to_be_visible(timeout=10000) # 设置10秒超时
    expect(welcome_message).to_contain_text("Welcome")
    

核心思想: 让 Playwright 去判断“何时准备好”,而不是我们去猜测“需要等多久”。

二、选择健壮、面向用户的选择器,优先使用 data-testid

选择器的稳定性直接关系到测试脚本的寿命。如果选择器过于依赖页面内部结构或动态生成的属性,那么前端代码的任何微小改动都可能导致测试失败。

坑点分析:

  1. 依赖动态 ID/Class: id="generated-123"class="item active state-xyz" 这种动态生成的属性极不可靠。
  2. 基于复杂 XPath/CSS 路径://div/div[3]/span/a[2] 这样的选择器,一旦 DOM 结构调整,立刻失效。
  3. 仅依赖文本内容: 虽然 text= 选择器很方便,但如果文本内容经常变更(如国际化、UI 调整),也会导致问题。

避坑策略:采用稳定且面向用户的定位策略

Playwright 提供了多种选择器引擎,建议按以下优先级选择:

  1. data-testid (最佳实践): 这是专门为测试设计的属性。与开发团队约定,在关键、需要交互或验证的元素上添加 data-testid="meaningful-name" 属性。

    • 优点: 与实现细节(CSS, JS 框架)解耦;明确测试意图;促进开发与测试协作。
    • 用法: page.locator('[data-testid="submit-button"]') 或更简洁的 page.get_by_test_id("submit-button")
    • 推动: 积极与开发团队沟通,将添加 data-testid 作为开发流程的一部分。
  2. 用户可见的角色、文本、标签等: 这些是用户实际与之交互的属性,相对稳定。

    • page.get_by_role(role, **kwargs): 基于 ARIA role 定位,如 button, link, textbox。可以结合 name (Accessible Name) 进一步精确。
      page.get_by_role("button", name="Login").click()
      
    • page.get_by_text(text, **kwargs): 定位包含特定文本的元素。注意区分大小写和精确匹配选项 (exact=True)。
      expect(page.get_by_text("Order received successfully")).to_be_visible()
      
    • page.get_by_label(text, **kwargs): 定位与给定标签文本关联的表单控件。
      page.get_by_label("Username").fill("myuser")
      
    • page.get_by_placeholder(text, **kwargs): 定位具有特定占位符文本的输入框。
      page.get_by_placeholder("Enter your email").fill("test@example.com")
      
    • page.get_by_alt_text(text, **kwargs): 定位具有特定 alt 文本的图片。
    • page.get_by_title(text, **kwargs): 定位具有特定 title 属性的元素。
  3. 稳定的 CSS 选择器: 如果以上都不可行,可以选择相对稳定的 CSS 选择器,如固定的 ID (#unique-id) 或组合的 Class (.form-control.required)。避免层级过深。

  4. XPath (谨慎使用): 尽量避免使用基于索引的 XPath。如果必须用,优先使用基于属性或文本内容的 XPath,如 //button[contains(text(), 'Submit')]//input[@name='quantity']

核心思想: 选择那些最不容易因代码重构或样式调整而改变的定位符,优先考虑为测试专门设计的属性。

三、严格管理环境与依赖,确保一致性

坑点分析:

  1. Python 版本差异: 不同 Python 版本可能导致语法不兼容或库行为差异。
  2. 依赖库版本冲突: 项目依赖的库(包括 Playwright 自身、测试框架如 Pytest、数据处理库等)版本不一致,可能引发各种奇怪的错误。
  3. 浏览器版本/驱动不匹配: Playwright 需要特定版本的浏览器二进制文件。手动管理容易出错或遗漏。
  4. 操作系统差异: 某些路径、权限、环境变量等问题可能与操作系统有关。

避坑策略:标准化与隔离

  1. 使用虚拟环境: 这是 Python 项目管理的基石。为每个项目创建独立的虚拟环境(如使用 venvconda),隔离项目依赖。

    # 使用 venv
    python -m venv .venv
    source .venv/bin/activate # Linux/macOS
    # .venv\Scripts\activate # Windows# 安装依赖
    pip install -r requirements.txt
    
  2. 固定依赖版本: 使用 requirements.txt 文件明确记录所有依赖及其精确版本。

    # 生成 requirements.txt
    pip freeze > requirements.txt# 安装指定版本的依赖
    pip install -r requirements.txt
    

    更现代化的方式是使用 PoetryPDM 等工具管理 pyproject.toml,它们能更好地处理依赖解析和锁定。

  3. 使用 Playwright 的浏览器管理: 不要手动下载浏览器。使用 Playwright 提供的命令行工具来安装和管理其支持的浏览器版本,确保与 Playwright 库版本兼容。

    # 安装 Playwright (会自动提示安装浏览器)
    pip install playwright# 手动安装所有支持的浏览器
    playwright install# 或者只安装特定浏览器
    playwright install chromium
    
  4. 考虑容器化 (Docker): 对于追求极致环境一致性的团队,尤其是在 CI/CD 环境中,使用 Docker 将整个测试环境(包括 OS、Python、依赖、浏览器)打包成镜像,是最佳解决方案。Playwright 官方也提供了 Docker 镜像。

核心思想: 让环境可复现、可预测,消除“本地可以,别处不行”的问题。

四、分离测试数据与逻辑,灵活管理数据

坑点分析:

  1. 难以维护: 当测试数据需要修改(如测试环境的用户名密码变更),你需要在多个脚本文件中查找和替换。
  2. 可读性差: 大量的硬编码数据掺杂在测试逻辑中,使得代码难以阅读和理解。
  3. 扩展性差: 难以实现数据驱动测试(用多组不同的数据运行同一个测试逻辑)。

避坑策略:数据驱动与外部化

  1. 将数据移至外部文件: 使用标准格式(如 JSON, YAML, CSV, Excel)存储测试数据。

    • JSON/YAML: 结构化数据,易于读写,适合配置类、对象类数据。
      # data.yaml
      login_credentials:valid:username: "testuser"password: "password123"invalid:username: "wronguser"password: "badpassword"
      
      import yamlwith open("data.yaml", 'r') as f:test_data = yaml.safe_load(f)valid_user = test_data['login_credentials']['valid']
      # ... 在测试中使用 valid_user['username'] ...
      
    • CSV/Excel: 表格数据,适合参数化测试,可以用多行数据驱动同一个测试用例。
  2. 利用测试框架的数据驱动特性: pytest 是 Python 测试生态中的佼佼者,其 parametrize 功能非常适合实现数据驱动。

    import pytest
    from playwright.sync_api import Page# 假设 login 函数接受 username, password, 预期结果
    @pytest.mark.parametrize("username, password, expected_outcome",[("testuser", "password123", "success"),("wronguser", "badpassword", "failure"),("testuser", "", "failure"), # 空密码]
    )
    def test_login(page: Page, username, password, expected_outcome):# ... 执行登录操作 ...# ... 断言结果与 expected_outcome 一致 ...pass
    
  3. 使用 Fixtures (尤其是 pytest Fixtures): 对于需要在多个测试用例中共享的、状态可能更复杂的“数据”(如已登录的用户对象、API 客户端实例),使用 Fixtures 是更好的选择。它们可以管理数据的设置和清理。

核心思想: 让测试逻辑关注“做什么”,让数据文件或参数化配置关注“用什么测”。

五、采用 POM 等设计模式,构建可维护的测试架构

随着测试用例数量的增长,如果所有操作和断言都堆砌在测试函数中,代码会变得冗长、重复且难以维护。

坑点分析:

  1. 代码重复: 同一个页面的元素定位和交互逻辑在多个测试用例中反复出现。
  2. 维护困难: 如果页面 UI 发生变化(如一个按钮的 ID 变了),需要修改所有用到该按钮的测试脚本。
  3. 可读性差: 测试脚本充斥着底层的定位和点击细节,掩盖了业务逻辑流程。

避坑策略:引入设计模式,提升抽象层次

Page Object Model (POM) 是 UI 自动化测试中最常用、最有效的设计模式之一。

  • 核心理念: 将每个页面(或页面上的一个重要组件)抽象成一个类(Page Object)。这个类封装了该页面的元素定位符和与这些元素交互的方法。测试脚本通过调用 Page Object 的方法来与页面交互,而不是直接操作 Playwright 的底层 API 和选择器。

  • 基本结构:

    # pages/login_page.py
    from playwright.sync_api import Page, Locatorclass LoginPage:def __init__(self, page: Page):self.page = pageself.username_input: Locator = page.locator("#username")self.password_input: Locator = page.locator("#password")self.login_button: Locator = page.get_by_role("button", name="Login")self.error_message: Locator = page.locator(".error-message")def navigate(self):self.page.goto("/login")def login(self, username, password):self.username_input.fill(username)self.password_input.fill(password)self.login_button.click()def get_error_message(self) -> str | None:if self.error_message.is_visible():return self.error_message.text_content()return None# tests/test_login.py
    from pages.login_page import LoginPage
    from playwright.sync_api import Page, expectdef test_successful_login(page: Page):login_page = LoginPage(page)login_page.navigate()login_page.login("testuser", "password123")# 断言跳转到了 dashboard 或出现欢迎信息expect(page).to_have_url("**/dashboard")# 或者 expect(page.locator("#welcome-message")).to_be_visible()def test_invalid_login(page: Page):login_page = LoginPage(page)login_page.navigate()login_page.login("wronguser", "badpassword")error_msg = login_page.get_error_message()expect(error_msg).to_contain("Invalid credentials")
    
  • 优点:

    • 提高可维护性: UI 变动时,只需修改对应的 Page Object 类。
    • 增强可读性: 测试脚本更侧重业务流程,易于理解。
    • 代码复用: 页面交互逻辑只需编写一次。
  • 其他模式: 除了 POM,还可以考虑结合 Action Classes (将复杂的用户行为封装成动作), Screenplay Pattern (更侧重用户目标和任务) 等模式,进一步优化架构。

核心思想: 通过抽象和封装,隐藏实现细节,让测试代码更清晰、更健壮、更易于维护。

六、理解并适时利用 Playwright 的 Async API

Playwright 底层是基于异步 I/O 构建的,它同时提供了同步(Sync)和异步(Async)两种 API。虽然 Sync API 对于许多测试场景来说足够简单方便,但在某些情况下,理解和使用 Async API 能带来显著优势。

坑点分析:

  1. 未使用 Async 导致性能瓶颈: 在需要高并发执行(如同时操作多个页面、并行运行测试)或处理大量网络事件时,Sync API 可能会阻塞,限制性能。
  2. 混合使用导致混淆: 不理解 Async/Await 机制,在 Sync 代码中错误地调用 Async 函数(反之亦然)会导致运行时错误或非预期行为。

避坑策略:按需选用,理解原理

  1. 何时使用 Async API?

    • 并行测试执行: 如果你希望使用 pytest-asyncio 或 Python 的 asyncio 库来并行运行多个测试用例或测试步骤,那么必须使用 Async API。
    • 同时与多个页面/上下文交互: 需要非阻塞地操作多个浏览器上下文或页面。
    • 复杂的事件处理: 需要同时监听和响应多个不同类型的事件(如网络请求、页面弹窗、WebSockets 消息)。
    • 与异步框架集成: 如果你的测试需要与基于 asyncio 的其他库(如异步 HTTP 客户端)进行交互。
  2. Async API 的基本用法:

    • 需要安装 playwright 的同时也要确保 asyncio 环境可用(Python 3.7+ 内置)。
    • 测试函数需要用 async def 定义。
    • 所有 Playwright 的异步操作前需要加 await 关键字。
    • 启动和关闭浏览器需要使用异步上下文管理器 async with async_playwright() as p:
    import pytest
    from playwright.async_api import async_playwright, Page, expect@pytest.mark.asyncio # 标记为异步测试 (需安装 pytest-asyncio)
    async def test_async_example():async with async_playwright() as p:browser = await p.chromium.launch()page = await browser.new_page()await page.goto("https://example.com")title = await page.title()print(f"Page title: {title}")await expect(page.locator("h1")).to_contain_text("Example Domain")await browser.close()
    
  3. 理解 async/await: 这是 Python 异步编程的核心。async 定义一个协程函数,await 暂停当前协程的执行,等待其后的异步操作完成,期间事件循环可以去执行其他任务。

核心思想: Sync API 入门简单,适用于大多数场景。当你遇到性能瓶颈或需要处理并发、复杂事件时,Async API 是你的利器,但需要对 Python 的 asyncio 有一定的理解。

七、重视错误处理、日志和报告,尤其是 Trace Viewer

测试会失败,这是不可避免的。关键在于失败后,我们能否快速、准确地定位问题所在。

坑点分析:

  1. 模糊的失败信息: 测试报告只显示“断言失败”或“元素未找到”,没有上下文信息。
  2. 缺乏调试手段: 难以复现失败场景,尤其是在 CI 环境中。
  3. 日志信息不足: 没有记录测试过程中的关键步骤和状态,不利于分析失败原因。

避坑策略:构建完善的诊断体系

  1. 精细化错误处理: 在测试代码中,可以使用 try...except 捕获预期的 Playwright 异常(如 TimeoutError),并提供更具体的错误信息或执行恢复逻辑(如重试)。但要避免过度使用,以免掩盖真实问题。

  2. 利用 pytest 的 Hooks 和 Fixtures 进行日志记录: 结合 Python 的 logging 模块,在测试开始、结束、关键步骤、失败时记录详细日志。pytest 提供了丰富的钩子函数(如 pytest_runtest_makereport)来自定义日志和报告行为。

  3. 生成清晰的测试报告: 使用 pytest-htmlAllure Report 等插件生成图文并茂的测试报告,展示测试结果、耗时、错误堆栈等。

  4. 拥抱 Playwright Trace Viewer (划重点!): 这是 Playwright 的一大杀器,一个革命性的调试工具。

    • 是什么? Trace Viewer 记录了测试执行期间的详细信息,包括:
      • 每个 Playwright Action 的执行过程和耗时。
      • Action 执行前后的 DOM 快照。
      • 完整的浏览器控制台日志 (console.log)。
      • 所有网络请求和响应详情。
      • 页面源代码。
    • 如何启用? 在创建浏览器上下文 (Context) 时开启追踪:
      # Sync API
      context = browser.new_context()
      context.tracing.start(screenshots=True, snapshots=True, sources=True)
      # ... 执行测试 ...
      context.tracing.stop(path="trace.zip") # 保存追踪文件
      context.close()# Async API
      context = await browser.new_context()
      await context.tracing.start(screenshots=True, snapshots=True, sources=True)
      # ... 执行测试 ...
      await context.tracing.stop(path="trace.zip")
      await context.close()
      
      通常建议只在测试失败时保存 Trace 文件,可以在 pytestpytest_runtest_makereport 钩子中实现。
    • 如何查看? 使用 Playwright CLI 打开 trace.zip 文件:
      playwright show-trace trace.zip
      
      这会启动一个本地 Web 服务,让你在浏览器中交互式地回溯整个测试过程。
    • 价值: Trace Viewer 极大地缩短了调试时间,尤其是对于 CI 环境中难以复现的测试。

核心思想: 让失败可追踪、可分析。

结语

行百里者半九十。掌握了 Playwright 的基本用法,仅仅是自动化测试征程的开始。真正的挑战在于如何持续构建和维护一个稳定、高效、易于扩展的测试体系。希望本文总结的这些经验能帮助你少走弯路。

相关文章:

Python+Playwright:编写自动化测试的避坑策略

PythonPlaywright:编写自动化测试的避坑策略 前言一、告别 time.sleep(),拥抱 Playwright 的智能等待二、选择健壮、面向用户的选择器,优先使用 data-testid三、严格管理环境与依赖,确保一致性四、分离测试数据与逻辑,…...

P12130 [蓝桥杯 2025 省 B] 移动距离

P12130 [蓝桥杯 2025 省 B] 移动距离 - 洛谷 题目描述 小明初始在二维平面的原点,他想前往坐标 (233, 666)。在移动过程中,他只能采用以下两种移动方式,并且这两种移动方式可以交替、不限次数地使用: 水平向右移动,…...

关于 人工智能(AI)发展简史 的详细梳理,按时间阶段划分,涵盖关键里程碑、技术突破、重要人物及挑战

以下是关于 人工智能(AI)发展简史 的详细梳理,按时间阶段划分,涵盖关键里程碑、技术突破、重要人物及挑战: 字数:约2500字 逻辑结构:时间线清晰,分阶段描述技术突破、关键事件与挑战…...

Formality:Bug记录

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 本文记录博主在使用Synopsys的形式验证工具Formality中遇到的几个Bug。 Bug复现 情况一 // 例1 module dff (input clk, input d_in, output d_out …...

react-07React提交表单数据调用同一方法(高阶函数,函数柯里化概念)

1.高阶函数与函数柯里化概念 高阶函数:符合其中之一,那该函数为高阶函数 1.A函数,接收的参数是一个函数,那么A就是高阶函数2.A函数,调用的返回值是一个函数,那么A就是高阶函数 常见的高阶函数&#xff1a…...

js ES6箭头函数的作用

前置知识 1、箭头函数语法简洁,相较于传统的函数表达式,箭头函数的语法更为简洁,尤其适用于简单的函数。 2、解决this取向问题,在传统函数中,this 的值取决于函数的调用方式,这可能会导致一些难以理解和调…...

淘宝商品数据高并发采集方案:API 接口限流机制与分布式调用实战

一、引言 在电商领域,对淘宝商品数据进行采集是一项常见且重要的任务。随着业务规模的扩大,高并发采集需求日益凸显。然而,淘宝 API 接口存在限流机制,为了高效且合规地完成数据采集,需要采用分布式调用的策略。本文将…...

python爬虫 线程,进程,协程

0x00 线程 线程是一个执行单位,是在一个进程里面的,是共享进程里面的提供的内存等资源,使用多个线程时和使用多个进程相比,多个线程使用的内存等资源较少。进程像一座“房子”(独立资源),线程是…...

《忘尘谷》音阶与调性解析

一、音高与音名的对应关系 根据搜索结果及音乐理论,结合《忘尘谷》的曲谱信息,其音阶与调性分析如下: 调性判定 原曲调性为 D调(原曲标注为D调),但曲谱编配时采用 C调指法,通过变调夹夹2品&…...

实验一 HDFS的Shell操作

一、实验目的 熟悉HDFS Shell的语法格式,完成对HDFS上文件和目录的一系列操作 二、实验要求 2.1 练习dfs常用的子命令 ① -ls ② -du ③ -mv ④ -cp ⑤ -rm ⑥ -put ⑦ -cat ⑧ -help ⑨ -mkdir ⑩ -get 2.2通过Shell脚本定时采集数据到HDFS 三、实…...

安装SQLServer管理工具

1.回到安装SQLServer的页面,选择安装SQLServer的管理工具2.跳转官网下载 3.安装SSMS 4.安装中5.安装成功以后打开软件,输入信息连接数据库 也可以在本机通过证书链接选择Windows身份验证,就不需要输入账号密码,但只能在安装sql…...

从JSON到SQL:基于业务场景的SQL生成器实战

引言 在数据驱动的业务场景中,将业务需求快速转化为SQL查询是常见需求。本文将通过一个轻量级的sql_json_to_sql函数,展示如何将JSON格式的查询描述转换为标准SQL语句,并结合实际业务场景验证其功能。 核心代码解析 1. 代码实现 def sql_j…...

记录鸿蒙应用上架应用未配置图标的前景图和后景图标准要求尺寸1024px*1024px和标准要求尺寸1024px*1024px

审核报错【①应用未配置图标的前景图和后景图,标准要求尺寸1024px*1024px且需下载HUAWEI DevEco Studio 5.0.5.315或以上版本进行图标再处理、②应用在展开状态下存在页面左边距过大的问题, 应用在展开状态下存在页面右边距过大的问题, 当前页面左边距: 504 px, 当前页面右边距…...

蓝桥杯嵌入式十六届赛前复习总结与准备

一.软件使用 赛点是没有网络的,要自己下载原件与数据包,这里给大家一个演示 在updater Settings这里设置文件存放位置,为了方便查找和提交文件,建议在桌面建立一个文件夹来存放。 把赛点的芯片包复制到创建的文件夹然后解压缩 之…...

了解一下Unity的RenderQueue

在Unity中,场景里的每个物体都需要通过渲染管线绘制到屏幕上。渲染管线处理光照、材质、纹理等信息,最终决定物体的显示效果。但当场景中有多个物体时,它们的绘制顺序会直接影响画面结果,尤其是在涉及透明物体或特效时。这时&…...

使用CS Roofline Toolkit测量带宽

使用CS Roofline Toolkit测量带宽 工程下载:使用CS Roofline Toolkit测量带宽-案例工程文件,也可以按照下面的说明使用git clone下载 目录 使用CS Roofline Toolkit测量带宽0、Roofline模型理解1、CS Roofline Toolkit下载1.1、设置代理1.2、git clone下…...

第三篇:深入 Framer Motion Variants:掌握组件动画编排的艺术

🎯 前言 在动态交互主导的现代前端开发中,优雅的动画效果已成为提升用户体验的重要元素。Framer Motion 的 Variants(动画变体)功能,通过状态化管理和动画编排能力,让复杂动效的实现变得前所未有的高效。本…...

狂神SQL学习笔记四:基本的命令行操作

注:所有语句用 ; 结尾,– 单行注释,/* 多行注释 */ 连接数据库 mysql -uroot -p123456 --连接数据库查看所有的数据库 切换数据库 查看数据库中所有的表 显示数据库中所有表的信息 创建一个数据库 退出连接...

架构思维:缓存层场景实战_读缓存(下)

文章目录 Pre业务场景缓存存储数据的时机与常见问题解决方案1. 缓存读取与存储逻辑2. 高并发下的缓存问题及解决方案3. 缓存预热(减少冷启动问题) 缓存更新策略(双写问题)1. 先更新缓存,再更新数据库(不推荐…...

软件架构设计:MVC、MVP、MVVM、RIA 四大风格优劣剖析

MVC、MVP、MVVM 和 RIA 都是软件架构中常见的设计风格,以下是对它们的详细介绍: 一、MVC 架构风格(Model - View - Controller) 1.简介:MVC 架构风格将软件应用程序分为三个核心部分,通过这种划分来分离不…...

java基础课程-springmvc课程

一. 回顾MVC: tomcat是servlet容器, servlet实现方式: xml中配置: 二. 回顾servlet: 三. SpringMvc学习 3.1 springMvc搭建和讲解: jar包引入spring-webmvc即可。 核心:DispatcherServlet Spring的web…...

NLP高频面试题(四十二)——RAG系统评估:方法、指标与实践指南

1. 引言:RAG系统概述与评估挑战 检索增强生成(Retrieval-Augmented Generation,简称 RAG)是近年来自然语言处理领域的一个重要进展。RAG系统在大型语言模型生成文本的过程中引入了外部检索模块,从外部知识库获取相关信息,以缓解纯生成模型可能出现的幻觉和知识盲点。通过…...

Flutter学习 滚动组件(1):ListView基本使用

目录 一、ListView构造方法1.1 常规方法1.2 ListView.builder1.3 ListView.separated 二、自定义ListView样式和布局:三、ListView性能优化:总结: 一、ListView构造方法 主要以下几种方法: 常规方法,直接使用默认的构…...

处理 Flutter 没有反应

现象 有以下几种 VS Code 中 Initializing the Flutter SDK. This may take a few minutes. 会一直维持在这个右下角提示窗, 但是无后续动作 Flutter CMD flutter_console.bat 执行 --version 或者 doctor [-v] 没有任何输出, 命令卡住 解决办法 参考官方说明 管理员身份…...

java面向对象06:封装

封装 该露的露,该藏的藏 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。 封装(数据的隐藏) 通常&#x…...

测试定时发布

测试定时发布 测试定时发布 测试定时发布 测试定时发布 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变 我…...

2025年4月15日 百度一面 面经

目录 1. 代理相关 从静态代理到动态代理 2. cglib可以代理被final修饰的类吗,为什么 3. JVM 体系结构 4. 垃圾回收算法 5. 什么是注解 如何使用 底层原理 6. synchronized和reentrantlock 7. 讲一下你项目中 redis的分布式锁 与java自带的锁有啥区别 8. post 请求和 ge…...

抖音卸载了ip属地还会更新吗?深度解析

近期,关于抖音IP属地显示功能的讨论热度持续攀升,许多用户提出疑问:如果卸载抖音APP,账号的IP属地还会继续更新吗?这一问题背后,既涉及平台算法的运作逻辑,也关乎用户对隐私保护的深层需求。本文…...

Spring IoC与DI详解:从Bean概念到手写实现

一、Spring Bean的概念与本质 1.1 什么是Bean? 在Spring框架中,Bean是一个由Spring IoC容器实例化、组装和管理的对象。Bean及其之间的依赖关系通过容器使用的配置元数据来定义。简单来说,Bean就是Spring容器管理的Java对象。简单来说&…...

【Qt】信号和槽

文章目录 信号和槽的概念信号和槽的使用链接信号和槽查看内置信号和槽通过 Qt Creator 生成信号槽代码 自定义信号和槽基本语法带参数的信号和槽 信号与槽的连接方式一对一一对多多对一 信号和槽的其他说明信号与槽的断开 使用 Lambda 表达式定义槽函数 信号和槽的概念 在 Qt 中…...

小事务架构下的业务完整性保障:基于业务处理记录与补偿机制的技术实现

随着微服务架构、事件驱动架构(EDA)和最终一致性理念的普及,传统的大事务管理方式被更细粒度的“小事务”所取代。在这种架构中,全局业务流程被拆解成多个局部事务节点,通过异步消息进行编排。这种解耦提高了可扩展性和…...

DELL电脑开机进入自检界面

疑难解答 - 如何解决开机直接进入BIOS画面 添加链接描述 一、DELL电脑开机自检提示please run setup program 未设置一天中的时间-请运行安装程序(Time-of-day not set - please run SETUP program) 配置信息无效-请运行安装程序(Invalid configuration information - ple…...

Spring Boot 微服务中集成 MyBatis-Plus 与集成原生 MyBatis 有哪些配置上的不同?

在Spring Boot 微服务中集成 MyBatis-Plus (MP) 与集成原生 MyBatis (MB) 在配置上的主要不同点。MyBatis-Plus 是在 MyBatis 基础上进行的增强,它兼容 MyBatis 的所有配置方式,并提供了更简洁、更强大的配置选项。 相同点: 基础数据源配置 (DataSource…...

最近准备写个Playbook,详细点的指导手册,作为后续的销售培训文件,也趁着这个机会整理下产品思路,尤其是对于UALink,UEC新的联盟规范的测试用例

# 最近准备写个Playbook,详细点的指导手册,作为后续的销售培训文件,也蹭这个机会整理下产品思路。随着产品线越来越多(其实也是越来越少),东西越来越杂,已经不是三言两语就能解释得清楚了。 其…...

Kimi-VL:开源多模态视觉语言模型的崭新突破

近年来,人工智能在多模态模型的领域取得了显著的进展,特别是在能够处理文本和视觉输入的模型方面。MoonshotAI团队近期开源发布了Kimi-VL模型,这一模型凭借其在视觉理解、推理和智能体任务中的优异表现,受到了广泛关注。与GPT-4o等…...

NLP专业技能2025

Linux: 熟练使用Linux操作系统,熟练使用Linux常用命令进行开发。 熟悉掌握shell脚本编程技术的使用,能够编写简单的Shell脚本并熟练使用shell脚本四剑客(find、sed、grep、awk)进行日志解析。 熟练使用Linux环境进行开…...

C++STL循环队列实现

核心概念 循环队列(Circular Queue),也称为环形队列,是一种特殊的队列数据结构。它通过将队列的首尾相连,解决了传统队列因出队操作导致的空间浪费问题(即“假溢出”),从而更高效地…...

YOLOv3实践教程:使用预训练模型进行目标检测

目录 简介环境准备获取预训练模型图像目标检测视频目标检测模型性能优化常见问题解答进阶学习路径 简介 YOLOv3(You Only Look Once version 3)是一种高效的实时目标检测算法,由Joseph Redmon和Ali Farhadi于2018年提出。与传统的目标检测…...

confluent-kafka入门教程

文章目录 官方文档与kafka-python的对比配置文档配置项 Producer代码示例Consumer代码示例 官方文档 confluent_kafka API — confluent-kafka 2.8.0 documentation Quick Start for Confluent Cloud | Confluent Documentation 与kafka-python的对比 对比维度confluent-ka…...

网络安全-Http\Https协议和Bp抓包

1. http协议,有请求必有相应, 请求协议, 响应协议; 2. 密码学加密机制及常用算法和常用名称说明: 算法 密钥 明文数据 密文; 加密算法分类和常用算法: 加密算法可以归结为三大类&#xff…...

TDengine 语言连接器(C#)

简介 TDengine.Connector 是 TDengine 提供的 C# 语言连接器。C# 开发人员可以通过它开发存取 TDengine 集群数据的 C# 应用软件。 .NET 版本兼容性 .NET Framework 4.6 及以上版本。.NET 5.0 及以上版本。 支持的平台 原生连接支持的平台和 TDengine 客户端驱动支持的平台…...

AI对百度搜索与抖音社区的影响差异?

在AIGC(生成式人工智能)快速发展的背景下,用户获取内容的方式确实变得更加直接和便捷。抖音、小红书等视频内容社区的流量下降速度可能比百度搜索更慢,这一现象可以从以下几个角度分析: 1. 内容形式的差异:…...

《ADVANCING MATHEMATICAL REASONING IN LAN- GUAGE MODELS》全文阅读

《ADVANCING MATHEMATICAL REASONING IN LAN- GUAGE MODELS: THE IMPACT OF PROBLEM-SOLVING DATA, DATA SYNTHESIS METHODS, AND TRAINING STAGES》全文阅读 提升语言模型中的数学推理能力:问题求解数据、数据合成方法及训练阶段的影响 \begin{abstract} 数学推…...

是德科技KEYSIGHT Agilent U2004A功率传感器

是德科技KEYSIGHT Agilent U2004A功率传感器 Keysight U2004A USB功率传感器的特性和规格包括: 频率范围为 9 kHz 至 6 GHz -60 至 20 dBm 的宽动态范围 内部调零功能消除了外部校准 测量速度高达 250 个读数/秒 在 PC 或其他 Agilent 仪器上显示功率测量值 频率…...

Kubernetes(K8S)内部功能总结

Kubernetes(K8S)是云技术的最核心的部分,也是构建是云原生的基石 K8S K8S,是Kubernetes的缩写,是Google开发的容器编排平台,现在由云原生计算基金会(CNCF)进行维护。 K8S&#xff…...

智谱最新模型GLM4是如何练成的

写在前面 这篇博客将基于《ChatGLM: A Family of Large Language Models from GLM-130B to GLM-4 All Tools》,深入剖析 GLM-4 系列在**模型架构设计、预训练、后训练(对齐)、以及关键技术创新(如长上下文处理、Agent 能力构建)**等环节的实现逻辑与设计考量,带你全面了…...

类头文件相互包含的问题

1.预编译指令: #ifndef CLASS_A_ #define CLASS_A_#include CLASS_B.h#endif 2.#pragma once 3.将类A中声明类B,并类中声明类B的指针,在类中的实现文件中包含类B的头文件。在类B中包含类A的头文件 a.h:class Bclass A {public:private:B*…...

云原生周刊:K8s 中的 GPU 共享

开源项目推荐 A2A Google 的 Agent2Agent(A2A)协议是一个开源标准,旨在促进不同框架和供应商构建的 AI 代理之间的互操作性。它允许代理通过统一的协议安全地交换信息、协同执行任务,并在多种企业平台和云环境中无缝协作。 A2A…...

(五)机器学习---决策树和随机森林

在分类问题中还有一个常用算法:就是决策树。本文将会对决策树和随机森林进行介绍。 目录 一.决策树的基本原理 (1)决策树 (2)决策树的构建过程 (3)决策树特征选择 (4&#xff0…...

DeepReaserch写的文献综述示例分享

目录 DeepReaserch提供的文献综述: 人工智能在医疗影像诊断中的研究进展综述(2015–2025) 引言 1 近十年研究进展回顾 1.1 深度学习崛起阶段(2015–2017年) 1.2 方法完善与临床初探(2018–2020年&…...