单元测试

  1. 什么是单元测试
    如果你正在使用函数式编程,一个单元最有可能指的是一个函数。你的单元测试将使用不同的参数调用这个函数,并断言它返回了期待的结果;在面向对象语言里,下至一个方法,上至一个类都可以是一个单元(从一个单一的方法到一整个的类都可以是一个单元)。意图很重要(“意图”二字是本文中第一次提到,它很重要) 我们有单元测试、增量测试、集成测试、回归测试、冒烟测试等等,名字非常多。谷歌看到这种“百家争鸣”的现象,创立了自己的命名方式,只分为小型测试、中型测试和大型测试。

小型测试,针对单个函数的测试,关注其内部逻辑,mock所有需要的服务。小型测试带来优秀的代码质量、良好的异常处理、优雅的错误报告。
中型测试,验证两个或多个制定的模块应用之间的交互。
大型测试,也被称为“系统测试”或“端到端测试”。大型测试在一个较高层次上运行,验证系统作为一个整体是如何工作的。

结论:我们的单元测试,既可以针对一个函数写case,也可以按照函数的调用关系串起来写case。 金字塔模型

在金字塔模型之前,流行的是冰淇淋模型。包含了大量的手工测试、端到端的自动化测试及少量的单元测试。造成的后果是,随着产品壮大,手工回归测试时间越来越长,质量很难把控;自动化case频频失败,每一个失败对应着一个长长的函数调用,到底哪里出了问题?单元测试少的可怜,基本没作用。

Mike Cohn 在他的着作《Succeeding with Agile》一书中提出了“测试金字塔”这个概念。这个比喻非常形象,它让你一眼就知道测试是需要分层的。它还告诉你每一层需要写多少测试。 测试金字塔本身是一条很好的经验法则,我们最好记住Cohn在金字塔模型中提到的两件事:

编写不同粒度的测试
层次越高,你写的测试应该越少

同时,我们对金字塔的理解绝不能止步于此,要进一步理解: 我把金字塔模型理解为——冰激凌融化了。就是指,最顶部的“手工测试”理论上全部要自动化,向下融化,优先全部考虑融化成单元测试,单元测试覆盖不了的 放在中间层(分层测试),再覆盖不了的才会放到UI层。因此,UI层的case,能没有就不要有,跑的慢还不稳定。

  1. 单元测试的阶段
    代码编写完成后的单元测试工作主要分为两个步骤:人工静态检查和动态执行跟踪。
    人工静态检查
    这是测试的第一步,这个阶段工作主要是保证代码算法的逻辑正确性(尽量通过人工检查发现代码的逻辑错误)、清晰性、规范性、一致性、算法高效性。并尽可能的发现程序中没有发现的错误。人工检查需进行算法逻辑正确性检查、模块接口的正确性检查、输入参数的正确性检查、调用其他方法的正确性检查、表达式及SQL语句的正确性检查、常量或全局变量使用的正确性检查、表示符定义的规范一致性检查等等。
    动态执行跟踪
    执行待测程序来跟踪比较实际结果与预期结果来发现错误。经验表明,使用人工静态检查法能够有效的发现30%到70%的逻辑设计和编码错误。但是代码中仍会有大量的隐性错误无法通过视觉检查发现,必须通过跟踪调试法细心分析才能够捕捉到。所以,动态跟踪调试方法也成了单元测试的重点与难点。

  2. 单元测试 19 法则
    3.1. 不应该编写成功通过的单元测试-它们应该被写成不通过的。你可以在几分钟内让任何一组测试通过,但这只是在欺骗你自己。
    3.2. 测试类应该只测试一个功能-你应该用一个功能去测试一个方法。否则,你会违反了单一职责原则。
    3.3. 测试类具备可读性-确保测试类标有注释并且容易理解,就像其他的代码一样。
    3.4. 良好的命名规范-再次测试时应该像其他代码一样-便于人们理解。
    3.5. 把断言从行为中分离出来-你的断言应该用来检验结果,而不是执行逻辑操作的。
    3.6. 使用具体的输入-不要使用任何的自动化测试数据来输入,像date()这些产生的数据会引入差异。
    3.7. 把测试类分类,放在不同的地方-从逻辑的角度看,当没有错误指向特定的问题时这更容易去查找。
    3.8. 好的测试都是一些独立的测试类-你应该让测试类与其他的测试、环境设置等没有任何依赖。这利于创建多个测试点。
    3.9. 不要包含私有的方法-他们都是一些具体的实现,不应该包含在单元测试里。
    3.10. 不要连接数据库或者数据源-这是不靠谱的。因为你不能确保数据服务总是一样的并且能够创建测试点。
    3.11. 一个测试不要超过一个模拟(mock对象)-我们努力去消除错误和不一致性。
    3.12. 单元测试不是集成测试-如果你想测试结果,不要使用单元测试。
    3.13. 测试必须具有确定性-你需要一个确定的预测结果,所以,如果有时候测试通过了,但是不意味着完成测试了。
    3.14. 保持你的测试是幂等的-你应该能够运行你的测试多次而不改变它的输出结果,并且测试也不应该改变任何的数据或者添加任何东西。无论是运行一次还是一百万次,它的效果都应该是一样的。
    3.15. 测试类一次仅测试一个类,测试方法一次仅测试一个方法-组织方法能够在问题出现时检测出来,并帮你确定测试依赖。
    3.16. 在你的测试里使用异常-你在测试里会遇到异常,所以,请不要忽略它,要使用它。
    3.17. 不要使用你自己的测试类去测试第三方库的功能-大多数好的库都应该有它们自己的测试,如果没考虑用mocks去产生一致性的结果的话。
    3.18. 限制规则-当在一些规则下写测试时,记住你的限制和它们(最小和最大)设置成最大的一致性。
    3.19. 测试类不应该需要配置或者自定义安装-你的测试类应该能够给任何人使用并且使它运行。“在我的机器上运行”不应该出现在这。

posted @ 2021-03-18 22:54  FrancisForeverhappy  阅读(59)  评论(0编辑  收藏  举报