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

为什么简单布尔校验的Jest测试比控制台测试慢很多还超时崩溃

问题原因及解决方案

Jest 完全支持 for 循环语法,测试超时和循环本身无关,根本原因是 generateMove 函数内部出现死循环,超出了 Jest 默认的测试超时时间(通常为 5 秒)。

常见触发原因

  • 已占用列表不同步

    你的 generateMove 函数的防重复校验逻辑,依赖的已占用位置列表和测试代码中手动维护的 alreadyPlayed 不是同一份:
    1. 如果 generateMove 设计为需要接收外部已占用列表作为入参,你在测试调用时没有传入该参数,函数内部会基于空列表做校验,返回的位置可能和之前返回的重复,当你调用到第 N 次时,棋盘实际已被占满,但函数内部认为还有空位,就会一直循环随机查找可用位置,触发死循环。
    2. 如果 generateMove 内部通过闭包、模块顶层变量等方式自行维护已占用列表,Jest 运行测试时默认会共享模块状态,前一次测试跑完后内部已占用列表已经存满 100 个位置,后续测试再调用该函数时,永远找不到可用位置,直接进入死循环。
  • 函数内部容错缺失

    generateMove 没有做边界校验:当棋盘所有位置都被占用时,没有抛出明确错误,而是直接进入无限重试的逻辑,问题无法被直接感知,只会表现为超时。

修复方案

  1. 如果 generateMove 需要外部传入已占用列表,修改测试代码,每次调用都传入当前维护的已占用数组:
    test('ai does not hit places that were already hit', () => {
      const alreadyPlayed = [];
      for (let i=0;i<99;i++) {
          const move = generateMove(alreadyPlayed);
          alreadyPlayed.push(move);
      }
      const last = generateMove(alreadyPlayed);
      expect(alreadyPlayed.includes(last)).toBe(false);
    })
    
  2. 如果 generateMove 内部自行维护状态,新增状态重置方法,每次测试执行前清空内部已占用列表:
    // 每次测试运行前重置 generateMove 内部状态
    beforeEach(() => {
      generateMove.reset();
    })
    
    test('ai does not hit places that were already hit', () => {
      const alreadyPlayed = [];
      for (let i=0;i<99;i++) {
          alreadyPlayed.push(generateMove());
      }
      const last = generateMove();
      expect(alreadyPlayed.includes(last)).toBe(false);
    })
    
  3. 给 generateMove 增加边界校验,当检测到所有位置都被占满时直接抛出错误,避免无意义的死循环:
    // generateMove 内部新增逻辑示例
    if (takenList.length >= 100) {
      throw new Error('棋盘所有位置已被占用');
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:06:00