Facebook发布了Jest,一个开源的、基于Jasmine框架的JavaScript单元
测试工具。
Jest源于Facebook两年前的构想,用于快速、可靠地测试Web聊天应用。它吸引了公司内部的兴趣,Facebook的一名软件工程师Jeff Morrison半年前又重拾这个项目,改善它的性能,并将其开源。
在最基础层面,Jest被设计用于快速、简单地编写地道的JavaScript测试。Jest自动模拟require()返回的CommonJS模块,并提供了包括内置的测试环境Dom API支持、合理的默认值、预处理代码和默认执行并行测试在内的特性。通过在并行进程中同时运行测试,Jest让测试更快地结束。
Morrison说:
Jest的目标是减少开始测试一个项目所要花费的时间和认知负荷,因此它提供了大部分你需要的现成工具:快速的命令行接口、Mock工具集以及它的自动模块Mock系统。
此外,如果你在寻找隔离工具例如Mock库,大部分其它工具将让你在测试中(甚至经常在你的主代码中)写一些不尽如人意的样板代码,以使其生效。
我们已经在Facebook亲眼看到花更多的时间用于开发你的应用是多么重要(相对于花时间去准备开发你的应用),而这就是Jest关注并正在解决的问题。
Jest与Jasmine框架的区别是在后者之上增加了一些层。最值得注意的是,运行测试时,Jest会自动模拟依赖。Jest自动为每个依赖的模块生成Mock,并默认提供这些Mock,这样就可以很容易地隔离模块的依赖。Morrison说对于新测试,默认会进行隔离,开发人员现在也能够“完全控制”需要隔离多少模块。每个测试都可以指明哪些模块应该或者不应该Mock。
关于自动化Mock,Facebook的文档有进一步的说明:
实际上,Jest在测试环境中执行自己的require()函数。Jest的自定义require()函数加载真正的模块,检查它是什么样子,然后基于它所看到的创建一个Mock版本并返回。也就是说,Jest将给你一个与真实模块具有相同形状的对象,但它模拟每一个Export值而不是实际的值。
尽管Jest引入了自动化Mock,需要注意的是,开发者仍然可以使用jest.mock()和jest.dontMock()控制哪些应该或者不应该进行Mock。
来自社区的反应绝大部分都很正面。在Hacker News,用户Cthulu说:
看起来很有趣:我们现在的AngularJS项目的测试套件越来越慢,部分原因是逐渐增加的测试,但主要的性能瓶颈是:
没有并行,即使测试套件全部是独立的;
DOM测试,导致大量的GC暂停;
(可能是)PhantomJS启动和初始化(未度量)。
我已经做了简单的优化,将我的那些测试分成两半,开两个终端运行(开发时和持续测试中),但它看来有点玄。
直接应对依赖注入和AngularJS,Facebook说:“Jest使用不同的方法来达到相同的结果。”对于Angular,依赖作为参数进行传递,因此测试很容易写。然而,Facebook指出,为了Angular中函数的可测性,开发者必须遵循其特定模式,将其传递给Angular的依赖注入框架。Jest的解决方案略有不同:
Jest也能以Angular相同的方式Mock依赖,但它使用CommonJS,而不是构建一个特定的模块加载器。这让你能够测试任何使用CommonJS的现有代码,不需要重度重构以使其兼容其它模块系统。
用户Caiob认同关于Jest的乐观情绪,他也是这种依赖注入方法的拥护者,他说:“Facebook能够提升像Jasmine这样的现有/熟悉的工具,这非常棒。并且,我喜欢他们处理CommonJS模块的方式。”
Morrison说,通过Jest,Facebook希望开始这样一种趋势,让测试变得更简单,让开发者有更多时间开发应用。读者如果想参与这个项目,可以检出Github库并发送Pull请求,或者在Freenode加入#jestjs。