实现比任何其他类型的测试更多的集成测试
单元测试在后端服务中使用起来很棒,但是在前端则有些棘,因为前端UI细节经常发生变化而不改变更大的用户流程,这会导致很多单元测试失败。需要花很多时间去更新单元测试。
集成测试验证大功能甚至整个页面,但没有任何后端、真实数据或真实浏览器。六日渲染登录页面,输入用户名和密码,点击”登录“按钮并验证是否发送了正确的网络请求,但实际上并没有进行任何网络请求。
单元测试 | 集成测试 |
---|---|
一个测试仅涵盖一个模块 | 一个测试涵盖整个功能或页面 |
重构后经常需要重写 | 大多数情况下经受得住重构 |
难以避免测试实现细节 | 更好地模拟用户使用应用程序 |
奖杯模型
从底层开始:
- Static analysis - 静态分析,捕捉语法错误、不良实践和错误使用的API
- Code formatters, like Prettier
- Linters, like ESLint
- Type Checkers, like TypeScript and Flow
- Unit tests - 单元测试工具 验证复杂算法是否正确工作
- Integration tests - 集成测试工具 让您确信引用程序的所有功能都能按照预期工作
- End-to-end tests - 端到端测试 - 确保应用作为一个整体运行:前后端、数据库和其他所有内容
避免测试内部问题
上面测试存在的问题:
- 如果您更改处理状态的方式(例如,将 React 状态替换为 Redux 或钩子),甚至重命名状态字段或方法,此测试将失败;
- 它不测试表单是否实际从用户的角度正常工作:表单可能未连接到
handleSubmit
方法,当isSubmitted
为真时,成功消息可能不会出现;
TIP
- 第一个问题称为假负:即使行为保持不变,测试也会失败。这样的测试使重构变得非常困难,您永远不知道测试失败是因为您破坏了某些内容还是因为测试不好。
- 第二个问题被称为假阳性:即使代码出错,测试也会通过。这样的测试并不能让你确信代码实际上对用户有用。
测试应该是确定性的
有些测试可能有时候通过有时候不通过,这种测试用例叫做 非确定性测试,造成这一问题的因素可能包括
- 时区问题
- 不同的文件系统
- 在每次测试之前不清除和重新填充数据库
- 多个测试用例之间存在共享的状态
- 等等…
良好的测试是确定性的,它们不依赖于环境
避免不必要的期望和测试
如果第一个 pizza 没有定义,那么第二个用例无论如何都是会失败的,所以第一个测试用例是没有必要实现的
不要追求100%的测试覆盖率
一味的追求测试覆盖率存在一些问题
- 高测试覆盖率会让你产生一种虚假的安全感。“覆盖的代码”意味着代码在测试运行期间被执行,但这并不意味着测试实际上在验证这段代码的功能。即使测试覆盖率不到 100%,你可以确定你没有测试某些代码,但即使覆盖率达到 100%,你也不能确定你测试了所有内容。
- 有些功能真的很难测试,比如浏览器中的文件上传或拖放。你开始模拟或访问组件内部,因此你的测试不再像用户使用应用程序的方式,而且难以维护。最终,你开始花更多时间编写不太有用的测试,这就是所谓的收益递减问题。
100% 的测试覆盖率在两种情况下是有用的:库和开源项目中
来源: