Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular 单元测试策略 #227

Open
EthanLin-TWer opened this issue Aug 9, 2018 · 1 comment
Open

Angular 单元测试策略 #227

EthanLin-TWer opened this issue Aug 9, 2018 · 1 comment

Comments

@EthanLin-TWer
Copy link
Owner

EthanLin-TWer commented Aug 9, 2018

最近做了三周短期的 Angular 项目,得以从实际项目角度观察其与 React、Vue 等主流框架的区别。单元测试策略,更多都是老生常谈了,大的原则一个都没变,可以原本从 React 单元测试策略 #200 那边抄过来。

本文假设读者已经具备基本的单元测试意识、工具知识,不再赘述基本概念,如 jasmine 基本知识、断言语法、karma 配置等。

目录

一. 理论篇

  • 为什么需要测试
  • 为什么需要单元测试
  • 什么是好的单元测试

二. 实践篇

  • component 测试策略及实例
  • service 测试策略及实例
  • pipe 测试策略及实例

理论篇

为什么需要测试

需要测试应该说已经渐渐成为行业里软件开发的政治正确了。然而,对于为什么需要测试,测试能带来什么样的价值,大家不一定有清晰的感知。在 React #200 那篇文章里,我从 cycle time 这个角度去讲为什么要写测试,现在可以再拔高一个层次来讲:响应力。先不谈组织级别的响应力,单从 IT 响应力来讲,它意味着你能多快地响应变化:新增需求、需求变更、线上问题、bug 定位、验证价值…等。而 cycle time,其实就是响应力的度量标准。

它就像买保险,在你没有买保险的意识之前,总会有这么个疑问:万一我买了没事那不就亏大了么?觉得这东西就是个赔钱玩意儿。要是我写了测试,又没测出 bug 来,那写测试不就亏大了么?干啥浪费这个时间呢?

首先要知道两个大事实:人员会流动,应用会变大。因此,意图依赖人、依赖手工的方式来应对响应力的挑战首先是低效的,从时间维度上来讲也是不现实的。因此,我们才需要一套自动化的、目标明确的套件,来帮我们快速反馈、守卫质量。这组套件,就是自动化测试。

其次,没有测试的代码就意味着不能重构,基本就只能看着代码腐化,没有任何持续改进的机会和氛围。有了自动化测试,你就有机会进行重构自动化回归,才可能做持续改进。

为什么需要单元测试

为了达到高响应力这个目标,测试当然只是其中一个方式,稳定的自动化部署、集成流水线、良好的代码架构、组织架构的必要调整等,都是必须跟上的设施。在一篇单元测试的文章里谈这些未免宏大,暂且按下不表。即便谈自动化测试,也并非全部都是单元测试。

为了使自动化测试套件具备高响应力特征,组合多个层次的测试是必要的。它要依赖于各个项目具体的痛点、成本、资源等进行定制,成为一个测试策略。我们选择对单元测试进行主要覆盖,是因为它具备编写成本低、反馈速度快、保护单元成本高的特点,显然应该是策略中价值较高的部分,并且可以随着 TDD 成为产品代码的一部分被持续交付。但这不意味着测试层次中的其他部分成本高或反馈慢,或不应该写。

image

什么是好的单元测试

#200 所谈,加上「响应力」这个帽子,好的单元测试应该符合这两点大原则:

  1. 与被测单元功能唯一相关
  2. 表达力极强

与被测单元功能唯一相关

也就是说,一个测试应该当且仅当「对于给定输入,代码给出了期望输出」时才通过,当且仅当「对于给定输入,代码未能给出期望输出」时才挂掉。它仅与 输入(input)输出(output) 两个变量相关,这使单元测试成为「功能正确性」的唯一回答者。唯如此,它才能快速准确地对业务功能的变化做出响应。

要达到这条原则其实不很简单,比如举一些我们常见的反模式:

  • 改动了不属于被测功能的代码,会使测试挂掉
    • 比如 Angular 默认的 component 测试设施,改 view 可能使 component 组件的逻辑功能测试挂掉;
    • 比如被测单元有依赖,另一个类挂掉导致一个被测单元挂掉;
  • 期望的输入输出不变,改动了实现,会使测试挂掉 - 测试依赖了实现细节,从而无法支撑重构
    • 比如 redux-saga 官方推荐的 cloneGenerator 测试设施
    • 比如断言实现过程产生的中间变量
    • 比如测试 private 方法等

表达力极强

表达个什么东西呢?大意三点:

  1. 决定输出的输入是什么
  2. 业务是什么
  3. 输出是什么

与此三点无关的元素需要减到最少,比如无关的测试数据、无效的测试描述等。当这个测试挂掉时,它必须能清楚告诉你:在这个业务场景下,对于这个输入,我期望 A 输出,然而被测方法给了 B 输出,A 与 B 在数据内容、结构上的差别是什么。

实践篇

component 测试策略及实例

service 测试策略及实例

  • how to spy on objects? different ways:
    • inject real service by using providers
    • inject fake service through DI: useValue

pipe 测试策略及实例

参考

@JimmyLv
Copy link

JimmyLv commented Aug 9, 2018

前来点赞,🤣 (但是这句话好像没什么营养…)

先占楼吧,幸好comments可以无限修改。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants