这里也是因为和 fetch/xmlHttpRequest 一样,并没有一个全局的API能让我们捕获到请求信息,因此只能通过重写wx.request来达到监听收集的功能。
const originRequest = wx.request; const ctx = this; //重写wx.request,增加中间逻辑 Object.defineProperty(wx, 'request', { value: function () { // sdk code const _complete = config.complete || function (data) {}; config.complete = function (data) { // sdk code return _complete.apply(this, arguments); }; return originRequest.apply(this, arguments); } })当我们已经实现了SDK之后或者说在实现的过程中,就需要编写测试代码了,下面说说编写测试用例。
四、编写测试用例SDK属于一个需要长期维护和更新的独立库,它被使用在很多业务项目中,要求更加稳定,当出现问题的时候,它的更新成本很高。需要经历:更新代码->发布新版本->业务方更新依赖版本,等流程,而如果在这个流程中,假如SDK又改出其它问题,那将会再启上述循环,业务同事肯定会被麻烦死。随着接入监控的系统增多,在迭代过程中改动任何的代码已经让人开始发慌,因为存在很多流程性的关联逻辑,害怕改出问题。在一次代码的重构和优化过程中,决心完善单元测试和流程测试。
4.1 单元测试单元测试主要是对一些有明显输入输出的通用方法,比如SDK的utils中的常用方法,SDK的参数配置方法等。而对于监控SDK来说,更多的测试代码主要集中在流程测试,对于单元测试这里就不具体说明了。
4.2 流程测试监控SDK在业务项目中初始化之后,主要是通过加入探针监听业务项目的运行状态而收集信息并进行上传的,它在大部分情况下并不是业务方调用什么就执行什么。比如我们页面初次加载,SDK在合适的时机会执行首次加载相关信息的收集并上传,那我们需要通过测试代码来模拟这个流程,保障上报的数据是预期的。
我们的SDK运行在浏览器环境中,在node环境下是不支持Web相关API的。因此我们需要让我们的测试代码在浏览器中运行,或者提供相关API的支持。下面我们将会介绍两种不同的方式,来支持我们的测试代码正常运行。
4.2.1 提供Web环境的方式假如我们使用mocha或者jest作为测试框架,可以通过mocha自带的mocha.run方法在html中编写和执行我们的测试代码,并在浏览器中打开运行;jest-lite也可以支持让jest运行在浏览器中。
但有时候我们不想让它打开浏览器,希望在终端中就能完成测试代码运行,可以使用无头浏览器,在node中加载浏览器环境,比如phontomjs或者puppeteer。他们提供了相关的工具,比如mocha-phantomjs就能直接在终端中运行html执行测试流程。
基于写好的html测试文件,再使用mocha-phantomjs和phantomjs,以下是package.json的命令配置。
scripts:{ test: mocha-phantomjs -p ./node_modules/.bin/phantomjs /test/unit/index.html }phontomjs已经被废弃了,不被推荐使用。推荐puppeteer,相关的功能和类似工具都有支持。
举例说明:
以前有在WebSocket的代码库中使用过这种方式。因为依赖Web Api: WebSocket。需要通过new WebSocket(),来完成测试流程,而node环境下没有此API。于是使用mocha在html中写测试用例,如果希望全程使用终端跑测试,还可以配合使用mocha-phantomjs让测试的html文件可以在终端中执行而不用打开本地的网页运行。
当然其实完全可以直接在浏览器中打开html查看测试运行结果,而且phantomjs相关的依赖包非常大、安装也比较慢。但当时我们使用了持续继承服务travis,当我们的代码更新到远程仓库以后,travis将会启动多个独立容器并在终端中执行我们的测试文件,如果不使用mocha-phantomjs在终端中跑测试没有办法在travis中成功通过。
4.2.2 Mock Web API的方式在这次完善监控SDK测试的过程中,尝试了另一种方式,全程使用Mock的方式。
上面的Web环境运行方式需要提供浏览器或者无头浏览器。但实际我们需要测试的代码并不是Web API,我们只是使用了它们。我们假定它们是稳定的,我们只需要在乎它的输入输出,如果它们内部出bug了,我们也是不能控制的,那是浏览器开发商的事情。因此我要做的事情仅仅是在node环境中模拟相关的Web API。