将时间限制放在笑话测试上?

时间:2019-05-28 14:29:58

标签: node.js npm jestjs

我正在与Jest进行一系列测试,以使用两种不同的斐波那契方法来证明Big O。

const fastFib = require('./../fastFib');
const slowFib = require('./../slowFib');

test('Fast way of getting Fibonacci of 44', () => {
  expect(fastFib(44)).toBe(701408733);
});

test('Slow way of getting Fibonacci of 44', () => {
  expect(slowFib(44)).toBe(701408733);
});

我想知道是否可以指定测试的最大长度?我看到您可以为异步超时传递第三个变量,但它似乎对正常功能没有任何影响:

test('Slow way of getting Fibonacci of 44', () => {
  expect(slowFib(44)).toBe(701408733);
}, 5000);

是否可以使用Jest指定函数的最大执行时间?


我将分享slowFib.js供参考:

function fib(n) {
  return (n<=1) ? n : fib(n - 1) + fib(n - 2);
}

module.exports = fib;

4 个答案:

答案 0 :(得分:0)

我认为您需要实现自己的计时器(使用setTimeout或使用Promises)。一种替代方法是对函数使用async关键字,使其与内置参数一起使用:

test('Slow way of getting Fibonacci of 44', async () => {
  expect(slowFib(44)).toBe(701408733);
}, 5000);

答案 1 :(得分:0)

因此您的测试由于同步执行而暂停-无法通过超时来中断测试。您需要“拆分执行”。下一个版本对我来说失败:

test('Slow way of getting Fibonacci of 44', (done) => {
  expect(slowFib(44)).toBe(701408733);
  setTimeout(done, 10); // smallest timeout possible to make different macrotask
}, 5000);

PS我也相信可以通过标记测试async来实现,但是还没有弄清楚到底有多精确。

[UPD]您实际上可以在不使用测试超时的情况下实现目标:

test('Slow way of getting Fibonacci of 44', () => {
  const start = new Date();
  expect(slowFib(44)).toBe(701408733);
  expect(new Date() - start).toBeLessThan(5000);
});

答案 2 :(得分:0)

您可以在测试文件中进行设置 jest.setTimeout(5000);覆盖了一个开玩笑的测试用例的默认超时时间

答案 3 :(得分:0)

这是一个受@skyboyer建议启发的(对打字稿友好的)函数。
(已使用Jest 24.8.0测试,但应与任何版本相关)

// Takes a threshold and a callback.
// if the callback didn't run within the threshold, the returned function will evaluate to a rejected promise.
// else, the returned function will evaluate to a resolved promise with the value returned by 'cb' (T)
const resolveWithin = <T>(threshold: number, cb: () => T): () => Promise<T> => {
  return () => {
    const start = Date.now();

    return Promise.resolve(cb()).then((t: T) => {
      const elapsed = Date.now() - start;

      if (elapsed > threshold) {
        return Promise.reject(elapsed);
      }

      return Promise.resolve(t);
    });
  }
};

// Uses "resolveWithin" to ensure a test has run within the threshold.
const withIn = <T>(threshold: number, fn: () => T): () => Promise<T> => {
  const cb = resolveWithin(threshold, fn);

  // @ts-ignore
  return () => {
    return cb().catch((elapsed) => {
      expect(elapsed).toBeLessThanOrEqual(threshold);
    })
  }
};

it("example", withIn(1000, () => { ... }));

it("example", withIn(1000, async () => { ... }));

关于@Khaled Osman's / @ HRK44答案的注释。

据我所知,使用这两种方法都不会反映为测试失败,也不会出现在Jest生成的报告中。