8.1 单元测试的原则
您可以在百度里搜索“深入浅出React和Redux 艾草文学(www.321553.xyz)”查找最新章节!
8.1 单元测试的原则
从不同的角度,可将测试划分为如下不同的种类:
·从人工操作还是写代码来操作的角度,可以分为手工测试和自动化测试;
·从是否需要考虑系统的内部设计角度,可以分为白盒测试和黑盒测试;
·从测试对象的级别,可以分为单元测试、集成测试和端到端测试;
·从测试验证的系统特性,又可以分为功能测试、性能测试和压力测试。
……
上述的测试种类中,有很多与被测试程序是基于什么语言、什么框架没有任何关系,比如端到端测试,对使用React和Redux写的应用,和对Backbone.js和jQuery写的应用,测试本身没有什么区别。在这里,我们只探讨特定于React和Redux的测试技巧,而体现特殊性的就是单元测试。
单元测试是一种自动化测试,测试代码和被测的对象非常相关,比如测试React组件的代码就和测试jQuery插件的代码完全不是一回事。
单元测试代码一般都由编写对应功能代码的开发者来编写,开发者提交的单元测试代码应该保持一定的覆盖率,而且必须永远能够运行通过。可以说,单元测试是保证代码质量的第一道防线。
既然说到单元测试,就不得不说测试驱动开发(Test Driven Development,TDD),有的开发者对测试驱动开发奉为神器,严格实践先写单元测试测试用例后写功能代码,而且单元测试也保证其他开发者不会因为失误破坏原有的功能;也有开发者对测试驱动开发不以为然,因为写单元测试的时间是写功能代码的好几倍,当需求发生改变的时候,除了要维护功能代码,还要维护测试代码,苦不堪言。
这里我们也不要争论测试驱动开发是否有必要,我们只需要正视一点,那就是单元测试应该是让开发者的工作更轻松更高效,而不是成为开发过程中的包袱。
每个开发团队会根据自身特点决定是否要求测试驱动开发,也可以设定恰当的单元测试覆盖阈值,不过要注意以下几点:
首先,即使单元测试覆盖率达到了100%,也不表示程序是没有bug的,实现高质量的软件有多方面要求,单元测试只是手段之一,不要对单元测试覆盖率有太过偏执的要求。
另外,程序架构的可测试性非常重要,开发者不喜欢写单元测试代码一个很主要的原因就是发现单元测试“太难写”,比如为了写一个单元测试要写太多的模仿对象(Mock),涉及复杂的流程难以全部条件分支。
要克服单元测试“太难写”的问题,就需要架构能把程序拆分成足够小到方便测试的部分,只要每个小的部分被验证能够正确地各司其职,组合起来能够完成整体功能,那么开发者编写的单元测试就可以专注于测试各个小的部分就行,这就是更高的“可测试性”。
只要应用得当,React和Redux应用的可测试性非常高,因为对应单元测试写出来大多就是对纯函数的测试。
在本书前面的例子中,都是尽量不让React存储状态,把状态存储到Redux的Store上,也就是让React组件只是一个根据数据负责渲染的纯函数就好,这样的React组件是非常方便测试的,每个写过单元测试的开发者都会有体会,测试一个根据输入返回输出的纯函数,要比测试一个包含很多状态的对象容易得多。因为纯函数的结果根据输入完全可以预测,而为了测试一个对象在某个状态下的行为,还要首先让这个对象处于那个状态,测试代码自身就会变得很长,让开发者担心测试代码本身就可能因为复杂化而出问题。
既然React组件变成了纯函数,那Redux就承担了复杂的状态管理,那是否Redux部分的可测试性会变低呢?并没有,因为Redux的功能由众多函数组成,这些函数中不少依然是纯函数,所以测试依然非常简单。
使用Redux的应用,开发者书写的大部分代码都属于action构造函数、reducer或者选择器,其中普通的action构造函数和reducer就是纯函数,异步action构造函数有副作用所以并不是纯函数,在接下来我们会介绍如何测试异步action构造函数;选择器虽然包含缓存的副作用,但是对于同样的输入也有同样的输出,测试难度不比测试纯函数更高。
接下来,我们就介绍单元测试React和Redux程序的方法。 深入浅出React和Redux