Playwright 中 page.clock 的常用方法和示例

Playwright 中的 page.clock API 允许你在测试中控制和模拟时间流逝,这对于测试定时器、延迟和日期相关功能非常有用。

常用方法

1. 安装时钟

await page.clock.install()

安装 fake timers,替换原生的定时器函数。

2. 前进时间

await page.clock.tick(ms)  # 前进指定的毫秒数
await page.clock.next()    # 前进到下一个定时器触发

3. 取消时钟

await page.clock.uninstall()

恢复原生的定时器函数。

4. 设置系统时间

await page.clock.set_system_time(time)  # time可以是时间戳或datetime对象

示例

基本使用示例

import pytest
from playwright.async_api import Page

@pytest.mark.asyncio
async def test_timer(page: Page):
    await page.clock.install()
    
    # 在页面中设置一个定时器
    await page.evaluate("""
        setTimeout(() => {
            document.body.innerHTML = '<div id="done">Done!</div>';
        }, 1000);
    """)
    
    # 前进时间
    await page.clock.tick(1000)
    
    # 验证定时器是否触发
    await page.wait_for_selector("#done")
    
    await page.clock.uninstall()

测试延迟加载

@pytest.mark.asyncio
async def test_lazy_loading(page: Page):
    await page.clock.install()
    
    await page.goto("http://example.com")
    
    # 页面中有延迟加载的逻辑
    await page.evaluate("""
        setTimeout(() => {
            fetch('/api/data').then(/* ... */);
        }, 5000);
    """)
    
    # 立即前进5秒,而不是实际等待
    await page.clock.tick(5000)
    
    # 验证API调用是否发生
    # ...
    
    await page.clock.uninstall()

测试日期相关逻辑

from datetime import datetime

@pytest.mark.asyncio
async def test_date_functionality(page: Page):
    await page.clock.install()
    
    # 设置固定日期
    fixed_date = datetime(2023, 1, 1)
    await page.clock.set_system_time(fixed_date)
    
    # 验证页面中的日期显示
    await page.goto("http://example.com/date-display")
    displayed_date = await page.text_content(".current-date")
    assert "2023-01-01" in displayed_date
    
    await page.clock.uninstall()

底层原理

Playwright Python 中的 page.clock 实现原理与 JavaScript 版本类似,但通过 Python 桥接层与浏览器通信:

  1. Python 到 JavaScript 的桥接:

    • Python API 通过 WebSocket 或管道与浏览器通信
    • 所有 clock 相关调用被转换为浏览器端的 JavaScript 执行
  2. Sinon.JS 集成:

    • 底层仍然使用 Sinon.JS 的 fake timers 实现
    • 通过 Playwright 的注入机制将 Sinon.JS 代码注入到页面上下文
  3. 时间控制流程:

    Python代码 → Playwright Python客户端 → 浏览器通信协议 → 页面JavaScript环境 → Sinon.JS实现

  4. 定时器管理:

    • 维护一个虚拟的时间轴
    • 当调用 tick() 时,会触发所有到期定时器
    • 保持定时器的执行顺序与原生实现一致
  5. Date 对象覆盖:

    • 替换原生的 Date 构造函数和相关方法
    • 确保所有时间相关调用都使用模拟时间
  6. 上下文隔离:

    • 每个页面有独立的时钟实例
    • iframe 也可以有自己的时钟控制

这种实现方式使得你可以在 Python 测试代码中精确控制浏览器内的时间流逝,而无需实际等待,大大加速了时间相关测试的执行速度。

注意事项

  1. 仅适用于测试:不要在生产代码中使用这些功能
  2. 异步操作:所有方法都是异步的,需要使用 await
  3. 清理:测试完成后应该调用 uninstall() 恢复原生日志
  4. 兼容性:某些复杂的时间相关库可能不完全兼容 fake timers
posted @ 2025-07-04 08:14  蛋仔聊测试  阅读(24)  评论(0)    收藏  举报