凌晨两点,你的CI流水线又超时了。加机器?改代码?还是先看看那个叫--fully-parallel的开关到底在干什么。
Alexandru A,这位做了10年前端、现在做AI测试管理的罗马尼亚开发者,用一组极简测试套件,把Playwright的调度机制扒了个底朝天。他的发现很具体:同一个开关,能让测试从5.6秒降到3.5秒,也能让15秒涨到20秒。差别不在硬件,在调度逻辑。
默认模式:文件是牢笼
Playwright的默认行为很直观——按文件分配工人。你指定--workers 2,它就把测试文件丢给两个工人,一个文件一个坑。
Alexandru的实验套件很简单:spec1只有1个测试,spec2有5个测试。默认跑下来,Worker 1闲了4/5的时间,Worker 2累死。总耗时5.6秒,由最长的文件决定,而非总工作量。
这里的关键约束是:文件内的测试不能跳槽。即使Worker 1空了,也不能帮Worker 2分担spec2的剩余测试。文件边界是硬隔离。
这种模式在文件粒度均匀时没问题。但现实是,测试文件像城市房价——分布极不均衡。有人写10行,有人写1000行。
完全并行模式:测试颗粒度自由流动
打开--fully-parallel,调度单位从"文件"变成"单个测试"。文件边界消失,工人抢下一个可用的测试。
同样的套件,同样的2个工人,spec2的5个测试被拆到两边。时间线拉平,总耗时从5.6秒压到3.5秒。提升来自利用率,而非硬件。
执行模型彻底转向:瓶颈从"最长文件"变成"总工作量除以工人数量"。这是理论最优,前提是测试之间没有依赖。
反方:当钩子成本成为主导
Alexandru的第二个实验揭示了陷阱。他在spec2加了重型的beforeAll钩子——模拟昂贵的环境初始化。
默认模式下,这个钩子只在Worker 2执行一次,后续5个测试复用同一份环境。总耗时15秒。
切换到完全并行,钩子跟着测试走。5个测试被拆到2个工人,beforeAll执行2次。工人越多,重复初始化越多。总耗时涨到20秒。
这不是边际损耗,是结构性成本。当设置时间主导测试时间,颗粒度细化反而放大浪费。
判断:没有银弹,只有场景
Alexandru的对比很干净。两个变量控制了一切:调度粒度与钩子复用。
完全并行适合测试轻量、文件分布不均的场景——典型的单元测试或纯UI断言。默认模式适合重型初始化、测试内聚于文件的场景——比如需要数据库快照、浏览器实例复用的集成测试。
Playwright把这个选择权暴露给用户,而非替你做决定。这是工具设计的诚实:性能优化从来不是单选题,是权衡题。
那个凌晨两点的超时问题?先profile你的测试时间分布,再动开关。5.6秒到3.5秒的快感,和15秒到20秒的惊吓,可能只隔一个beforeAll的距离。
热门跟贴