You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现事件循环运行至所有任务阻塞的测试方案(兼容3.9)

确定性驱动asyncio协程的单元测试方案

需求可行性

完全可行。你可以通过控制事件循环的执行节奏,在所有协程进入阻塞状态时暂停循环,此时进行断言或触发外部事件,再恢复循环继续执行,全程无需修改协程内部逻辑。

是否需要自定义事件循环

不需要依赖自定义事件循环,利用Python标准库asyncio的原生API就能实现所需的run_until_blocked_or_complete函数。核心思路是反复运行事件循环的短周期迭代,直到检测到所有未完成任务都处于阻塞状态。

Python版本支持

Python 3.9完全支持该方案,甚至Python 3.7及以上版本都能正常运行(asyncio.all_tasks()在3.7版本正式成为公开API,替代了之前的asyncio.Task.all_tasks())。无需升级版本。

实现示例

以下是你期望的run_until_blocked_or_complete函数的具体实现,以及完整测试代码:

import asyncio
from asyncio import Event

async def wait_on_event(event: Event):
    print("Waiting on event")
    await event.wait()
    print("Done waiting on event")

def run_until_blocked_or_complete(loop):
    while True:
        # 获取当前所有未完成的任务
        pending_tasks = [task for task in asyncio.all_tasks(loop) if not task.done()]
        if not pending_tasks:
            # 没有待处理任务,直接退出
            break
        
        # 等待0秒,尝试执行所有就绪的任务
        done, _ = loop.run_until_complete(
            asyncio.wait(pending_tasks, timeout=0, return_when=asyncio.FIRST_COMPLETED)
        )
        
        if not done:
            # 没有任务完成,说明所有任务都已阻塞,退出循环
            break

def test_deterministic():
    loop = asyncio.get_event_loop()
    event = Event()
    task = loop.create_task(wait_on_event(event))
    
    run_until_blocked_or_complete(loop)
    # 此时会打印"Waiting on event",协程阻塞在event.wait()
    
    # 这里可以添加断言,比如检查任务状态是否为pending
    assert not task.done()
    
    event.set()
    run_until_blocked_or_complete(loop)
    # 此时会打印"Done waiting on event",协程执行完成
    
    assert task.done()

if __name__ == "__main__":
    test_deterministic()

关键逻辑说明

  • asyncio.wait(..., timeout=0):让事件循环执行所有当前就绪的任务,但不等待任何阻塞操作完成,立即返回。
  • 循环检测:如果某次调用后没有任务完成,说明所有任务都处于等待外部事件的阻塞状态,此时暂停循环,允许你进行测试操作。

内容的提问来源于stack exchange,提问作者Alexander Kondratskiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:50:17