TypeScript中的突变测试:破坏代码以使其更好

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

你确定你的测试真的有效吗?

\n\n

想象一下:你的代码覆盖率达到95%,所有测试都是绿色的,CI/CD顺利通过。团队很满意,经理很放心。但有一天,生产环境中出现了一个bug。你打开代码,查看测试,然后意识到:它们只是检查函数是否返回一个数字,但没有检查它的值。或者更糟——测试编写得无论如何都会通过。

\n\n

熟悉的情况吗?欢迎来到一个覆盖率只是一个数字,而不是质量保证的世界。这时,突变测试(mutation testing)登场了——这是一种真正让你的测试经受考验并证明其有效性的方法。

\n\n

在本文中,我们将探讨如何使用Stryker在TypeScript项目中引入突变测试,以及为什么这可能会成为你新的最爱工具(或新的头痛来源)。

\n\n

用简单的话来说,什么是突变测试?

\n\n

突变测试是指你拿自己的代码,故意在其中引入微小的错误(突变),然后观察你的测试是否会失败。如果测试没有失败——说明你的测试方式不正确。如果测试失败了——你做得很好,但突变体被消灭了。

\n\n

听起来像施虐?也许吧。但这很有效。想象一下,你是一名QA工程师,偷偷潜入代码,将===替换为==,将>替换为<,或者删除了一个函数调用。一个好的测试必须能发现这一点。一个糟糕的测试则会放过它。

\n\n

在具有严格类型系统的TypeScript中,突变测试特别有用:它能捕获类型正确但逻辑错误的情况。

\n\n

为什么普通的代码覆盖率是一种错觉?

\n\n

假设你有一个函数:

\n\n
function calculateDiscount(price: number, isPremium: boolean): number {\n  if (isPremium) {\n    return price * 0.8;\n  }\n  return price;\n}
\n\n

以及一个测试:

\n\n
test('returns number', () => {\n  const result = calculateDiscount(100, true);\n  expect(typeof result).toBe('number');\n});
\n\n

覆盖率?100%。测试?通过。但是,如果我们将price * 0.8替换为price * 0.5呢?测试仍然会通过——因为它只检查类型,而不检查值。这就是虚假的安全感。

\n\n

突变测试会突出显示这样的突变,并告诉你:“嘿,你的测试没有注意到我改变了折扣!”。然后你就不得不补充一个正常的检查。

\n\n

TypeScript中的突变测试如何工作:分步指南

\n\n

整个过程可以分为三个步骤:

\n\n
    \n
  1. 生成突变体——工具复制你的代码并一次引入一个更改。例如,将&&改为||,或删除一个方法调用。
  2. \n
  3. 运行测试——针对每个突变体运行你的测试。
  4. \n
  5. 分析结果——如果测试失败,突变体被“杀死”。如果没有,它“存活”了下来,这就是风险区域。
  6. \n
\n\n

主要指标是突变分数(被杀死的突变体的百分比)。100%是理想状态,但在实践中,80-90%已经非常好了。

\n\n

TypeScript的第一工具:Stryker

\n\n

在TypeScript和JavaScript的世界里,突变测试的王者是Stryker(StrykerJS)。它速度快,能够与Jest、Vitest、Mocha甚至浏览器测试一起使用。5分钟即可完成配置。

\n\n

安装:

\n\n
npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner
\n\n

创建配置文件stryker.conf.js:

\n\n
// stryker.conf.js\nexport default {\n  mutate: ['src/**/*.ts', '!src/**/*.spec.ts'], // 要突变的内容\n  testRunner: 'jest',\n  reporters: ['html', 'clear-text', 'progress'],\n  jest: {\n    projectType: 'custom',\n    configFile: 'jest.config.ts',\n  },\n  concurrency: 4, // 并发处理的突变体数量                

博客

书籍推荐