使用Jest+React Testing Library测试计算函数返回值的最佳实践
问题解答
1. 硬编码测试纯计算逻辑是否属于最佳实践
对于纯函数(输入确定则输出固定、无副作用、不依赖外部状态)来说,用硬编码固定用例测试核心逻辑反而是最推荐的做法。你现在的calcAnnualSalary就是典型的纯函数,输入固定的月工资字符串,输出结果完全可预期,硬编码用例能最直接验证计算逻辑正确性,无额外依赖,运行速度也最快。你当前的单测写法本身没有问题,只是覆盖的场景太少。
2. 是否需要从表单获取值测试这个计算函数
不需要。纯计算逻辑的单元测试不需要和UI层耦合,如果把表单作为输入来源,反而会引入不必要的问题:
- 测试会依赖UI组件的渲染状态,表单出现问题会直接导致计算逻辑的单测报错,无法快速定位是计算逻辑错误还是表单传值错误
- 测试运行速度变慢,还要额外处理组件渲染逻辑
- 耦合后如果后续表单重构,还要同步修改计算逻辑的单测,维护成本很高
如果要测试表单和计算逻辑的联动,属于集成测试的范畴,和当前验证计算函数本身的单元测试是两类测试,不要混在一起。
3. 相关优化建议
- 优化单元测试用例覆盖:
- 补全边界值用例:比如月工资为空、格式异常(带特殊字符、小数点超过两位)、零值、大额数值(比如
'100.000.000,00'这种多位千分符的场景)的处理逻辑 - 补全所有入参的测试:当前函数还有医保、交通补贴、餐补、周六计薪几个未启用的参数,后续逻辑补全后要对应增加不同参数组合的用例
- 用参数化测试减少重复代码:比如Jest的
test.each语法,把多组输入和预期输出放在数组里批量执行,不用每个用例都写重复的调用逻辑,示例如下:
describe('calcAnnualSalary', () => { test.each([ ['1.000,00', 12000, 1000, 1000/3, 12000+1000+1000/3], ['2.500,50', 30006, 2500.5, 2500.5/3, 30006+2500.5+2500.5/3], ['0,00', 0, 0, 0, 0], ])('输入月工资 %s 计算结果正确', (monthly, expectedAnnual, expected13th, expectedHoliday, expectedTotal) => { const res = Calc.calcAnnualSalary(monthly) expect(res.annualSalary).toBeCloseTo(expectedAnnual) expect(res.thirteenth).toBeCloseTo(expected13th) expect(res.extraHoliday).toBeCloseTo(expectedHoliday) expect(res.totalAnnualCrude).toBeCloseTo(expectedTotal) }) }) - 补全边界值用例:比如月工资为空、格式异常(带特殊字符、小数点超过两位)、零值、大额数值(比如
- 优化函数本身的重复逻辑:当前代码三次执行了
parseFloat(monthlySalary.replace(/\./g, '').replace(',', '.')),可以把这个格式化转数字的逻辑抽成单独的变量或者公共工具函数,避免重复执行,后续维护也更方便。 - 单独补充集成测试:如果要验证用户从表单输入到结果展示的完整流程,可以单独写集成测试:模拟用户在表单输入对应数值、提交操作,断言页面展示的最终结果是否符合预期,这部分测试和计算逻辑的单元测试分开维护即可。
内容的提问来源于stack exchange,提问作者Renan Bessa
相关产品推荐
相关产品推荐

